首页 > 编程语言 >Java网络编程

Java网络编程

时间:2023-06-18 16:36:48浏览次数:38  
标签:Java String 编程 网络 System close new null 客户端

一、Java网络编程

网络编程是指编写运行在多个设备(计算机)的程序,设备通过网络连接起来。java.net 包中 J2SE 的 API 包含有类和接口,提供了低层次的通信细节。可以直接使用这些类和接口,来专注于解决问题,而不用关注通信细节。

协议:计算机网络中,连接和通信的规则被称为网络通信协议

1.UDP协议

  • 用户数据报协议(User Datagram Protocol)
  • UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据
  • 由于使用UDP协议消耗资源少,通信效率高,所以通常都会用于音频、视频和普通数据的传输
  • 例如视频会议通常采用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议

2.TCP协议

  • 传输控制协议(Transmission Control Protocol)
  • TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据出啊u念书。在TCP连接中必须明确客户端与服务器端,由于客户端向服务器端发出连接请求,每次连接的创建都需要经过“三次握手”

3.三次握手

  • TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠
  • 第一次握手:客户端向服务器端发出连接请求,等待服务器确认
  • 第二次握手:服务器端向客户端回送一个响应,通知客户端收到了连接请求
  • 第三次握手:客户端再次向服务器端发送确认信息,确认连接

Java网络编程_数据

 完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用非常广泛。例如上传文件、下载文件、浏览网页

二、Java中InetAddress的使用

Java具有较好的网络编程模型/库,其中非常重要的一个API便是InetAddress。在在java.net网络编程中中有许多类都使用到了InetAddress,包括ServerSocket,Socket,DatagramSocket等等。

Java提供InetAddress类(有Inet4Address和Inet6Address两种实现),可以对域名-IP进行正向、逆向解析。InetAddress解析的时候一般是调用系统自带的DNS程序,比如:Linux下默认使用哪个DNS去解析以及其规则是由/etc/resolv.conf该文件制定

IP地址是IP使用的32位(IPv4)或者128位(IPv6)位无符号数字,它是传输层协议TCP,UDP的基础。InetAddress是Java对IP地址的封装。

java.net.IntAddress类是Java对IP地址的高层表示。大多数其它网络类都要用到这个类,包括Socket、ServerSocket、URL、DatagramSocket、DatagramPacket等。InetAddress的实例对象包含了IP地址,同时还可能包含主机名(如果使用主机名来获取InetAddress的实例,或者使用数字来构造,并且启用了反向主机名解析的功能)。InetAddress类提供了将主机名解析为IP地址(或反之)的方法。

InetAddress对域名进行解析是使用本地机器配置(如域名系统DNS和网络信息服务(Network Information Service,NIS))来实现。本地需要向DNS服务器发送查询的请求,然后服务器根据一系列的操作,返回对应的IP地址,为了提高效率,通常本地会缓存一些主机名与IP地址的映射,这样访问相同的地址,就不需要重复发送DNS请求了。如下:

public class Test01 {
    public static void main(String[] args) throws UnknownHostException {
        //InetAddress ia = new InetAddress();不能直接创建对象,因为InetAddress()被default修饰了。
        /*InetAddress ia = InetAddress.getByName("192.168.200.114");
        System.out.println(ia);
        InetAddress ia2 = InetAddress.getByName("localhost");//localhost指代的是本机的ip地址
        System.out.println(ia2);
        InetAddress ia3 = InetAddress.getByName("127.0.0.1");//127.0.0.1指代的是本机的ip地址
        System.out.println(ia3);
        InetAddress ia4 = InetAddress.getByName("DESKTOP-A5TIRM1");//封装计算机名
        System.out.println(ia4);
        InetAddress ia5 = InetAddress.getByName("www.augus.com");//封装域名
        System.out.println(ia5);*/


        // InetSocketAddress  ---》封装了IP,端口号
        InetSocketAddress inetSocketAddress = new InetSocketAddress("192.168.200.114", 9999);
        System.out.println(inetSocketAddress); ///192.168.200.114:9999
        System.out.println(inetSocketAddress.getHostName()); //输出计算机的名称 DESKTOP-A5TIRM1
        System.out.println(inetSocketAddress.getPort());//输出端口

        InetAddress ia1 = inetSocketAddress.getAddress();
        System.out.println(ia1.getHostName());//输出计算机的名称 DESKTOP-A5TIRM1
        System.out.println(ia1.getHostAddress());//192.168.200.114
        

    }
}

三、基于TCP的网络编程

TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,从而在通信的两端形成网络虚拟链路,一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信。

  • 使用基于TCP协议的Socket网络编程实现,使用Socket对象来代表两端的通信端口
  • TCP协议基于请求-响应模式,第一次主动发起的程序被称为客户端(Client)程序
  • 第一次通讯中等待连接的程序被称为服务器端(Sercer)程序

Java网络编程_数据_02

利用IO流实现数据的传输

Java网络编程_System_03

原理说明及详细步骤

  1. 在服务端指定一个端口号来创建ServerSocket,并使用accept方法进行侦听,这将阻塞服务器线程,等待用户请求。
  2. 在客户端指定服务的主机IP和端口号来创建socket,并连接服务端ServerSocket,此时服务端accept方法被唤醒,同时返回一个和客户端通信的socket。
  3. 在客户端和服务端分别使用socket来获取网络通信输入/输出流,并按照一定的通信协议对socket进行读/写操作。
  4. 通信完成后,在客户端和服务端中分别关闭socket。

3.1.单向通信

功能:客户端发送一句话到服务器:

  • 服务端代码:
public class TestServer {
    public static void main(String[] args) throws IOException {
        //1.创建套接字:指定端口号
        ServerSocket serverSocket = new ServerSocket(9999);
        //2.等待客户端发来的信息
        //accept()返回值为一个Socket,这个Socket其实就是客户端的Socket
        //接到这个Socket以后,客户端和服务器才真正产生了连接,才真正可以通信了
        Socket accept = serverSocket.accept();//阻塞方法:等待接收客户端的数据,什么时候接收到数据,什么时候程序继续向下执行。

        //操作流
        InputStream inputStream = accept.getInputStream();
        DataInputStream dataInputStream = new DataInputStream(inputStream);// 数据输入流

        //4.读取客户端发来的数据:
        String s = dataInputStream.readUTF();

        //5.输出客户端信息
        System.out.println("客户端发送消息:"+s);

        //6.关闭流操作
        dataInputStream.close();
        inputStream.close();
        accept.close();
        serverSocket.close();

    }
}
  • 客户端代码
public class TestClient {
    public static void main(String[] args) throws IOException {
        //1.创建套接字:指定服务器的ip和端口号:
        Socket socket = new Socket("192.168.200.114",9999);

        //2.利用输出流。发送数据

        // 利用这个OutputStream就可以向外发送数据了,但是没有直接发送String的方法
        // 所以在OutputStream外面套了一个处理流:DataOutputStream
        OutputStream outputStream = socket.getOutputStream();
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);//数据输出流

        dataOutputStream.writeUTF("你好");

        //3.关闭流和网络资源
        dataOutputStream.close();
        outputStream.close();
        socket.close();
    }
}

注意,测试的时候,先启动服务端,在启动客户端,执行后如下:

Java网络编程_System_04

3.2.双向通信

 修改为通信双方均可进行消息的处理

服务端:

public class TestServer {
    public static void main(String[] args) throws IOException {
        //1.创建套接字:指定端口号
        ServerSocket serverSocket = new ServerSocket(9999);
        //2.等待客户端发来的信息
        //accept()返回值为一个Socket,这个Socket其实就是客户端的Socket
        //接到这个Socket以后,客户端和服务器才真正产生了连接,才真正可以通信了
        Socket accept = serverSocket.accept();//阻塞方法:等待接收客户端的数据,什么时候接收到数据,什么时候程序继续向下执行。

        //操作流
        InputStream inputStream = accept.getInputStream();
        DataInputStream dataInputStream = new DataInputStream(inputStream);// 数据输入流

        //4.读取客户端发来的数据:
        String s = dataInputStream.readUTF();

        //5.输出客户端信息
        System.out.println("接受到客户端发送消息:"+s);

        //6.向客户端发送消息
        OutputStream outputStream = accept.getOutputStream();
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
        dataOutputStream.writeUTF("你好,很高兴认识你,我是TestServer");

        //6.关闭流操作
        dataOutputStream.close();
        outputStream.close();
        dataInputStream.close();
        inputStream.close();
        accept.close();
        serverSocket.close();

    }
}

客户端

public class TestClient {
    public static void main(String[] args) throws IOException {
        //1.创建套接字:指定服务器的ip和端口号:
        Socket socket = new Socket("192.168.200.114",9999);

        //2.利用输出流。发送数据

        // 利用这个OutputStream就可以向外发送数据了,但是没有直接发送String的方法
        // 所以在OutputStream外面套了一个处理流:DataOutputStream
        OutputStream outputStream = socket.getOutputStream();
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);//数据输出流

        dataOutputStream.writeUTF("你好");

        //3.接收从服务端 发送的消息
        InputStream inputStream = socket.getInputStream();
        DataInputStream dataInputStream = new DataInputStream(inputStream);
        System.out.println("接收到服务端发送的数据:"+dataInputStream.readUTF());

        //4.关闭流和网络资源
        dataOutputStream.close();
        outputStream.close();
        socket.close();
    }
}

执行后结果如下:

Java网络编程_客户端_05

Java网络编程_数据_06

3.3.对象流传送

  • User实体类封装对象,传递用户名和密码
public class User implements Serializable {
    private String username;
    private String password;

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}
  • 服务端:
public class TestServer {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1.创建套接字:指定端口号
        ServerSocket serverSocket = new ServerSocket(9999);
        //2.等待客户端发来的信息
        //accept()返回值为一个Socket,这个Socket其实就是客户端的Socket
        //接到这个Socket以后,客户端和服务器才真正产生了连接,才真正可以通信了
        Socket accept = serverSocket.accept();//阻塞方法:等待接收客户端的数据,什么时候接收到数据,什么时候程序继续向下执行。

        //操作流
        InputStream inputStream = accept.getInputStream();
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);// 数据输入流

        //4.读取客户端发来的数据:
        User user = (User) objectInputStream.readObject();

        //验证
        boolean flae = false;
        if(user.getUsername().equals("admin")&& user.getPassword().equals("123321")){
            flae = true;
        }

        //5.输出客户端信息
        System.out.println("接受到客户端发送消息:"+user.toString());

        //6.向客户端发送消息
        OutputStream outputStream = accept.getOutputStream();
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
        //向客户端发送数据
        dataOutputStream.writeBoolean(flae);

        //6.关闭流操作
        dataOutputStream.close();
        outputStream.close();
        objectInputStream.close();
        inputStream.close();
        accept.close();
        serverSocket.close();

    }
}
  • 客户端
public class TestClient {
    public static void main(String[] args) throws IOException {
        //1.创建套接字:指定服务器的ip和端口号:
        Socket socket = new Socket("192.168.200.114",9999);

        //2.从键盘录入用户名和密码
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入用户名:");
        String name = scanner.next();
        System.out.print("请输入密码:");
        String pwd = scanner.next();
        //封装User对象传递
        User user = new User(name,pwd);


        //2.利用输出流。发送数据
        // 利用这个OutputStream就可以向外发送数据了,但是没有直接发送String的方法
        // 所以在OutputStream外面套了一个处理流:DataOutputStream
        OutputStream outputStream = socket.getOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);//数据输出流
        //发送对象
        objectOutputStream.writeObject(user);

        //3.接收从服务端 发送的消息
        InputStream inputStream = socket.getInputStream();
        DataInputStream dataInputStream = new DataInputStream(inputStream);
        //接受发送过来的boolean类型的数据
        boolean b = dataInputStream.readBoolean();
        if (b){
            System.out.println("恭喜,登陆成功");
        }else {
            System.out.println("用户名或者密码错误");
        }

        //4.关闭流和网络资源
        dataInputStream.close();
        inputStream.close();
        objectOutputStream.close();
        outputStream.close();
        socket.close();
    }
}

执行后结果如下:

Java网络编程_System_07

Java网络编程_System_08

3.4.加入完成处理异常方式

加入异常处理,保证代码的健壮性

  • 服务端
public class TestServer {
    public static void main(String[] args){
        //
        ServerSocket serverSocket=null;
        Socket accept=null;
        InputStream inputStream=null;
        ObjectInputStream objectInputStream=null;
        OutputStream outputStream=null;
        DataOutputStream dataOutputStream=null;

        try {
            //1.创建套接字:指定端口号
            serverSocket = new ServerSocket(9999);
            //2.等待客户端发来的信息
            //accept()返回值为一个Socket,这个Socket其实就是客户端的Socket
            //接到这个Socket以后,客户端和服务器才真正产生了连接,才真正可以通信了
            accept = serverSocket.accept();//阻塞方法:等待接收客户端的数据,什么时候接收到数据,什么时候程序继续向下执行。

            //操作流
            inputStream = accept.getInputStream();
            objectInputStream = new ObjectInputStream(inputStream);// 数据输入流

            //4.读取客户端发来的数据:
            User user = (User) objectInputStream.readObject();

            //验证
            boolean flae = false;
            if(user.getUsername().equals("admin")&& user.getPassword().equals("123321")){
                flae = true;
            }

            //5.输出客户端信息
            System.out.println("接受到客户端发送消息:"+user.toString());

            //6.向客户端发送消息
            outputStream = accept.getOutputStream();
            dataOutputStream = new DataOutputStream(outputStream);
            //向客户端发送数据
            dataOutputStream.writeBoolean(flae);
        }catch (IOException | ClassNotFoundException e){
            e.printStackTrace();
        }finally {
            //6.关闭流操作
            try {
                //不为null在关闭
                if(dataOutputStream != null){
                    dataOutputStream.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                //不为null在关闭
                if(outputStream != null){
                    outputStream.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                //不为null在关闭
                if(objectInputStream != null){
                    objectInputStream.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                //不为null在关闭
                if(inputStream != null){
                    inputStream.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                //不为null在关闭
                if(accept != null){
                    accept.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                if(serverSocket != null){
                    serverSocket.close();
                }
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }
}
  • 客户端
public class TestClient {
    public static void main(String[] args) {
        //创建
        Socket socket= null;
        OutputStream outputStream= null;
        ObjectOutputStream objectOutputStream= null;
        InputStream inputStream= null;
        DataInputStream dataInputStream= null;


        try {
            //1.创建套接字:指定服务器的ip和端口号:
            socket = new Socket("192.168.200.114",9999);

            //2.从键盘录入用户名和密码
            Scanner scanner = new Scanner(System.in);
            System.out.print("请输入用户名:");
            String name = scanner.next();
            System.out.print("请输入密码:");
            String pwd = scanner.next();
            //封装User对象传递
            User user = new User(name,pwd);


            //2.利用输出流。发送数据
            // 利用这个OutputStream就可以向外发送数据了,但是没有直接发送String的方法
            // 所以在OutputStream外面套了一个处理流:DataOutputStream
            outputStream = socket.getOutputStream();
            objectOutputStream = new ObjectOutputStream(outputStream);//数据输出流
            //发送对象
            objectOutputStream.writeObject(user);

            //3.接收从服务端 发送的消息
            inputStream = socket.getInputStream();
            dataInputStream = new DataInputStream(inputStream);
            //接受发送过来的boolean类型的数据
            boolean b = dataInputStream.readBoolean();
            if (b){
                System.out.println("恭喜,登陆成功");
            }else {
                System.out.println("用户名或者密码错误");
            }
        }catch (IOException ioException){
            ioException.printStackTrace();
        }finally {
            //关闭流
            try {
                if(dataInputStream != null){
                    dataInputStream.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                if(inputStream != null){
                    inputStream.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                if(objectOutputStream != null){
                    objectOutputStream.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                if(outputStream != null){
                    outputStream.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                if(socket != null){
                    socket.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }
        }
    }
}

3.5.多线程接受用户请求

服务器针对一个请求服务,之后服务器就关闭了(程序自然结束了)现在需要解决:服务器必须一直在监听 ,一直开着,等待客户端的请求,这里对于服务端进行多线程改造

  • 多线程类:ServerThread
public class ServerThread extends Thread{
    ServerSocket serverSocket=null;
    Socket accept=null;
    InputStream inputStream=null;
    ObjectInputStream objectInputStream=null;
    OutputStream outputStream=null;
    DataOutputStream dataOutputStream=null;

    public ServerThread(Socket accept) {
        this.accept = accept;
    }

    @Override
    public void run() {
        try{

            //操作流
            inputStream = accept.getInputStream();
            objectInputStream = new ObjectInputStream(inputStream);// 数据输入流

            //4.读取客户端发来的数据:
            User user = (User) objectInputStream.readObject();

            //验证
            boolean flae = false;
            if(user.getUsername().equals("admin")&& user.getPassword().equals("123321")){
                flae = true;
            }

            //5.输出客户端信息
            System.out.println("接受到客户端发送消息:"+user.toString());

            //6.向客户端发送消息
            outputStream = accept.getOutputStream();
            dataOutputStream = new DataOutputStream(outputStream);
            //向客户端发送数据
            dataOutputStream.writeBoolean(flae);

        }catch (IOException | ClassNotFoundException e){
            e.printStackTrace();
        }finally {
            //6.关闭流操作
            try {
                //不为null在关闭
                if(dataOutputStream != null){
                    dataOutputStream.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                //不为null在关闭
                if(outputStream != null){
                    outputStream.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                //不为null在关闭
                if(objectInputStream != null){
                    objectInputStream.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                //不为null在关闭
                if(inputStream != null){
                    inputStream.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                //不为null在关闭
                if(accept != null){
                    accept.close();
                }
            }catch (IOException ioException){
                ioException.printStackTrace();
            }

            try {
                if(serverSocket != null){
                    serverSocket.close();
                }
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }
}

服务端

public class TestServer {
    public static void main(String[] args){
        System.out.println("=================服务端已启动===============");

        //1.创建套接字:指定服务器的端口号
        ServerSocket serverSocket = null;
        Socket accept = null;

        //用于记数,确定客户端的连接次数
        int count = 0;

        try {
            //创建套接字对象:指定端口号
            serverSocket = new ServerSocket(9999);
            while (true){
                //加入死循环,让服务器一直处于监听状态

                //阻塞方法:等待接收客户端的数据,什么时候接收到数据,什么时候程序继续向下执行。
                accept = serverSocket.accept();

                count++;
                //输入请求的客户端的信息:
                System.out.println("当前是第"+count+"个用户访问我们的服务器,对应的用户是:"+accept.getInetAddress());
                //每次过来的客户端的请求靠线程处理:
                new ServerThread(accept).start();//创建启动线程
            }

        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    }
}

执行后结果如下:

Java网络编程_客户端_09

四、基于UDP的网络编程

TCP(客户端和服务器端地位不平等):

  • 客户端:Socket 程序感受到的 使用流 :输出流
  • 服务器端: ServerSocket --->Socket 程序感受到的 使用流 :输入流

UDP(发送方和接收方的地址是平等的):

  • DatagramSocket:用于发送或接收数据包的套接字
  • DatagramPacket:数据包
  • UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象
  • 基于UDP协议的通信双方而言,没有客户端和服务器概念

UDP案例: 完成网站的咨询聊天

4.1.单向通信

  • 发送方
public class TestSend {//发送方

    public static void main(String[] args) throws Exception {
        System.out.println("发送方 学生上线:");
        //1.准备套接字:指定发送方的端口号
        DatagramSocket ds = new DatagramSocket(8888);
        //2.准备数据包
        String str1 = "你好呀";
        //转换为byte类型
        byte[] bytes = str1.getBytes();

        /*
        需要四个参数:
        1.指的是传送数据转为字节数组
        2.字节数组的长度
        3.封装接收方的ip
        4.指定接收方的端口号
         */
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"),9999);

        //发送
        ds.send(dp);

        //关闭资源
        ds.close();
    }
}
  • 接受方
public class TestReceive {
    public static void main(String[] args) throws IOException {
        System.out.println("接收方 老师即将上线:");
        //1.创建套接字:指定接受方的端口
        DatagramSocket ds = new DatagramSocket(9999);

        //2.创建空的数据包,打算用来接收  对方传过来的数据包:
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);

        //3.接收对方的数据包,然后放入我们的dp数据包中填充
        ds.receive(dp);//接收完以后 dp里面就填充好内容了

        //取出数据
        byte[] data = dp.getData();

        //注意这里不要导错包
        String s = new String(data, 0, dp.getLength());

        System.out.println("学生说:"+s);

        //关闭
        ds.close();

    }
}

4.2.双向通信

  • 发送方
public class TestSend {//发送方

    public static void main(String[] args) throws Exception {
        System.out.println("发送方 学生上线:");
        //1.准备套接字:指定发送方的端口号
        DatagramSocket ds = new DatagramSocket(8888);
        //2.准备数据包
        Scanner scanner = new Scanner(System.in);
        System.out.print("学生输入信息:");
        String str1 = scanner.next();
        //转换为byte类型
        byte[] bytes = str1.getBytes();

        /*
        需要四个参数:
        1.指的是传送数据转为字节数组
        2.字节数组的长度
        3.封装接收方的ip
        4.指定接收方的端口号
         */
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"),9999);

        //发送
        ds.send(dp);

        //接受老师发送的数据
        //创建空的数据包,打算用来接收  对方传过来的数据包:
        byte[] bytes2 = new byte[1024];
        DatagramPacket dp2 = new DatagramPacket(bytes2, bytes2.length);
        ds.receive(dp2);//接收完以后 dp里面就填充好内容了、

        //取出数据
        //注意这里不要导错包
        String s = new String(dp2.getData(), 0, dp.getLength());
        System.out.println("老师回复说:"+s);

        //关闭资源
        ds.close();
    }
}
  • 接受方
public class TestReceive {
    public static void main(String[] args) throws IOException {
        System.out.println("接收方 老师即将上线:");
        //1.创建套接字:指定接受方的端口
        DatagramSocket ds = new DatagramSocket(9999);

        //2.创建空的数据包,打算用来接收  对方传过来的数据包:
        byte[] bytes = new byte[1024];
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length);

        //3.接收对方的数据包,然后放入我们的dp数据包中填充
        ds.receive(dp);//接收完以后 dp里面就填充好内容了

        //取出数据
        byte[] data = dp.getData();

        //注意这里不要导错包
        String s = new String(data, 0, dp.getLength());

        System.out.println("学生说:"+s);

        //向学生发送数据
        Scanner scanner = new Scanner(System.in);
        System.out.print("给学生回复信息:");
        String str1 = scanner.next();
        //转换为byte类型
        byte[] bytes2 = str1.getBytes();

        /*
        需要四个参数:
        1.指的是传送数据转为字节数组
        2.字节数组的长度
        3.封装接收方的ip
        4.指定接收方的端口号
         */
        DatagramPacket dp2 = new DatagramPacket(bytes2, bytes2.length, InetAddress.getByName("localhost"),8888);

        //发送
        ds.send(dp2);

        //关闭
        ds.close();

    }
}

4.3.异常处理

  • 发送方
public class TestSend {//发送方

    public static void main(String[] args) {
        System.out.println("发送方 学生上线:");
        DatagramSocket ds = null;

        try {
            //1.准备套接字:指定发送方的端口号
            ds = new DatagramSocket(8888);
            //2.准备数据包
            Scanner scanner = new Scanner(System.in);
            System.out.print("学生输入信息:");
            String str1 = scanner.next();
            //转换为byte类型
            byte[] bytes = str1.getBytes();

            /*
            需要四个参数:
            1.指的是传送数据转为字节数组
            2.字节数组的长度
            3.封装接收方的ip
            4.指定接收方的端口号
             */
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"),9999);

            //发送
            ds.send(dp);

            //接受老师发送的数据
            //创建空的数据包,打算用来接收  对方传过来的数据包:
            byte[] bytes2 = new byte[1024];
            DatagramPacket dp2 = new DatagramPacket(bytes2, bytes2.length);
            ds.receive(dp2);//接收完以后 dp里面就填充好内容了、

            //取出数据
            //注意这里不要导错包
            String s = new String(dp2.getData(), 0, dp.getLength());
            System.out.println("老师回复说:"+s);
        }catch (IOException ioException){
            ioException.printStackTrace();
        }finally {
            //关闭资源
            if(ds != null){
                ds.close();
            }
        }
    }
}
  • 接受方
public class TestReceive {
    public static void main(String[] args) throws IOException {
        System.out.println("接收方 老师即将上线:");
        DatagramSocket ds = null;

        try {
            //1.创建套接字:指定接受方的端口
            ds = new DatagramSocket(9999);

            //2.创建空的数据包,打算用来接收  对方传过来的数据包:
            byte[] bytes = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length);

            //3.接收对方的数据包,然后放入我们的dp数据包中填充
            ds.receive(dp);//接收完以后 dp里面就填充好内容了

            //取出数据
            byte[] data = dp.getData();

            //注意这里不要导错包
            String s = new String(data, 0, dp.getLength());

            System.out.println("学生说:"+s);

            //向学生发送数据
            Scanner scanner = new Scanner(System.in);
            System.out.print("给学生回复信息:");
            String str1 = scanner.next();
            //转换为byte类型
            byte[] bytes2 = str1.getBytes();

            /*
            需要四个参数:
            1.指的是传送数据转为字节数组
            2.字节数组的长度
            3.封装接收方的ip
            4.指定接收方的端口号
             */
            DatagramPacket dp2 = new DatagramPacket(bytes2, bytes2.length, InetAddress.getByName("localhost"),8888);

            //发送
            ds.send(dp2);
        }finally {

            if(ds != null){
                //关闭
                ds.close();
            }

        }
    }
}

4.4.正常通信

  • 发送方
public class TestSend {//发送方

    public static void main(String[] args) {
        System.out.println("发送方 学生上线:");
        DatagramSocket ds = null;

        try {
            //1.准备套接字:指定发送方的端口号
            ds = new DatagramSocket(8888);
            while (true){
                //2.准备数据包
                Scanner scanner = new Scanner(System.in);
                System.out.print("学生输入信息:");
                String str1 = scanner.next();
                //转换为byte类型
                byte[] bytes = str1.getBytes();

                /*
                需要四个参数:
                1.指的是传送数据转为字节数组
                2.字节数组的长度
                3.封装接收方的ip
                4.指定接收方的端口号
                 */
                DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"),9999);

                //发送
                ds.send(dp);

                //接受老师发送的数据
                //创建空的数据包,打算用来接收  对方传过来的数据包:
                byte[] bytes2 = new byte[1024];
                DatagramPacket dp2 = new DatagramPacket(bytes2, bytes2.length);
                ds.receive(dp2);//接收完以后 dp里面就填充好内容了、

                //取出数据
                //注意这里不要导错包
                String s = new String(dp2.getData(), 0, dp.getLength());
                System.out.println("老师回复说:"+s);
            }
        }catch (IOException ioException){
            ioException.printStackTrace();
        }finally {
            //关闭资源
            if(ds != null){
                ds.close();
            }
        }
    }
}
  • 接受方
public class TestReceive {
    public static void main(String[] args) throws IOException {
        System.out.println("接收方 老师即将上线:");
        DatagramSocket ds = null;

        try {
            //1.创建套接字:指定接受方的端口
            ds = new DatagramSocket(9999);

            while (true){
                //2.创建空的数据包,打算用来接收  对方传过来的数据包:
                byte[] bytes = new byte[1024];
                DatagramPacket dp = new DatagramPacket(bytes, bytes.length);

                //3.接收对方的数据包,然后放入我们的dp数据包中填充
                ds.receive(dp);//接收完以后 dp里面就填充好内容了

                //取出数据
                byte[] data = dp.getData();

                //注意这里不要导错包
                String s = new String(data, 0, dp.getLength());

                System.out.println("学生说:"+s);

                //向学生发送数据
                Scanner scanner = new Scanner(System.in);
                System.out.print("给学生回复信息:");
                String str1 = scanner.next();
                //转换为byte类型
                byte[] bytes2 = str1.getBytes();

                /*
                需要四个参数:
                1.指的是传送数据转为字节数组
                2.字节数组的长度
                3.封装接收方的ip
                4.指定接收方的端口号
                 */
                DatagramPacket dp2 = new DatagramPacket(bytes2, bytes2.length, InetAddress.getByName("localhost"),8888);

                //发送
                ds.send(dp2);
            }
        }finally {

            if(ds != null){
                //关闭
                ds.close();
            }
        }
    }
}

 



标签:Java,String,编程,网络,System,close,new,null,客户端
From: https://blog.51cto.com/u_13661275/6508749

相关文章

  • Java 注解
    一、Java注解(Annotation)简介从Java5版本之后可以在源代码中嵌入一些补充信息,这种补充信息称为注解(Annotation),是Java平台中非常重要的一部分。注解都是@符号开头的,例如:在学习方法重写时使用过的@Override注解。同Class和Interface一样,注解也属于一种类型。Annotation......
  • Java反射机制
    一、Java反射机制是什么?Java 反射机制是Java语言的一个重要特性。在学习Java反射机制前,大家应该先了解编译期和运行期两个概念:编译期是指把源码交给编译器编译成计算机可以执行的文件的过程。在Java中也就是把Java代码编成class文件的过程。编译期只是做了一些翻译功能,......
  • java操作redis之jedis
    我们之前对Redis的学习都是在命令行窗口,那么如何使用Java来对Redis进行操作呢?对于Java连接Redis的开发工具有很多,这里先介绍通过Jedis实现对Redis的各种操作。(前提是你的redis已经配置了远程访问)1.创建一个maven工程,并且添加以下依赖<dependencies><!--jedis--><......
  • java web模板学习+1
    今天找到一个模板很厉害,代码开源的,拔下来就能跑。下面是他的博客地址和他的源代码地址。博客地址:开源一套简单通用的后台管理系统-huanzi-qch-博客园(cnblogs.com)开源地址:https://gitee.com/huanzi-qch/base-admin......
  • TensorFlow05.3 神经网络反向传播算法-多层感知机梯度(理论知识)
    首先这个是链式法则:如果扩展到多层感知机的话:我们在学这个的时候首先知道一个东西:所以这个整体的步骤就是:1.2.3.......
  • /usr/bin/java -> /etc/alternatives/java
    [root@localhosteclipse]#whichjava/usr/bin/java[root@localhosteclipse]#ls-l/usr/bin/javalrwxrwxrwx1rootroot22Aug12012/usr/bin/java->/etc/alternatives/java[root@localhosteclipse]#ls/etc/alternatives/antlr......
  • TensorFlow05.3 神经网络反向传播算法-链式法则
    1BasicRule2Productrule3QuotientRule4Chainrule(链式法则)在这个神经网络中:......
  • linux shell 编程比较详解
    shell编程字符串比较shell中整数比较和字符串比较方法,如等于,不等于,大于,大于等于,小于,小于等于等。1、整数比较-eq等于,如if["$a"-eq"$b"]-ne不等于,如if["$a"-ne"$b"]-gt大于,如if["$a"-gt"$b"]-ge大于等于,如if["$a"-ge"......
  • socket网络编程(一)——初识socket
    出现一项技术,首先我们弄懂一下,为什么要出现。那么为什么要出现socket这玩意呢?可以很简单的用一句话来概括:为了实现两台计算机的通信1、socket诞生的原因两台装有操作系统的机子要想实现通信,第一要联网,第二通信双方一定制定某种规则。我们平时最为常见的http请求也是一种通信协......
  • TensorFlow05.2 神经网络反向传播算法-单输出感知机和多输出感知机及其梯度
    1单输出感知机在这里我们可以看到,\(W_2,1^1\)其中他的下标第一个2,表示的连着上一层的x2,下标第一个1代表着连着下一侧的x1。然后上标1代表着第一层。E是做了一个loss处理。\(X_i^1\)这个下标的i代表当前层数节点的编号,然后这个1代表着第1层。\(W_i,j^k\),i表示上一层的节点编......