网络编程 --- TCP和UDP协议

网络编程 — TCP和UDP协议

TCP通信

  • TCP通信的概念

TCP协议
TCP协议是面向连接的通信协议,即在传输数据前先在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”。第一次握手,客户端向服务器端发出连接请求,等待服务器确认,第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求,第三次握手,客户端再次向服务器端发送确认信息,确认连接。
网络编程 --- TCP和UDP协议

  • 在JDK中提供了两个类用于实现TCP程序

    ServerSocket类 用于表示服务器端
    Socket类 用于表示客户端
  • ServerSocket类的构造方法和普通方法

    1. 构造方法
      ServerSocket(int port) 创建绑定特定端口的服务器端口号(套接字)
    1. 常用方法
      accept() 侦听并接受此套接字的连接,返回值是Socket类对象
      getInetAddress() 返回次服务器套接字的本地地址,返回值是InetAddress对象
  • Socket类的构造方法和普通方法
    1. 构造方法
      Socket(String host, int port) 使用该构造方法在创建Socket对象时,会根据参数去连接在指定地址和端口上运行的服务器程序,其中参数host接收的是一个字符串类型的IP地址。
      Socket(InetAddress address, int post) 接收一个InetAddress对象封装的IP地址连接到指定的端口号
    1. 常用方法
      int getPort() 该方法返回一个int类型对象,该对象是Socket对象与服务器端连接的端口号
      InetAddress getLocalAddress() 该方法用于获取Socket对象绑定的本地IP地址,并将IP地址封装成InetAddress类型的对象返回
      void close() 该方法用于关闭Socket连接,结束本次通信。在关闭socket之前,应将与socket相关的所有的输入/输出流全部关闭,这是因为一个良好的程序应该在执行完毕时释放所有的资源
      InputStream getInputStream() 该方法返回一个InputStream类型的输入流对象,如果该对象是由服务器端的Socket返回,就用于读取客户端发送的数据,反之,用于读取服务器端发送的数据
      OutputStream getOutputStream() 该方法返回一个OutputStream类型的输出流对象,如果该对象是由服务器端的Socket返回,就用于向客户端发送数据,反之,用于向服务器端发送数据
简单的TCP通信Demo
  • 代码准备 服务器端
public class MyServer {
    public static void main(String[] args) {
        try {
            //创建服务器端对象,并指定连接的端口号
            ServerSocket server = new ServerSocket(9090);
            //侦听并接受此套接字的连接,返回Socket类对象
            Socket socket = server.accept();
            //读取客户端发送来的数据
            InputStream is = socket.getInputStream();
            byte[] bytes = new byte[1024];
            int length = is.read(bytes);
            //将数据转换成字符串,并打印到控制台
            String thisData = new String(bytes, 0, length);
            System.out.println(thisData);

            //向客户端返回一条数据
            OutputStream os = socket.getOutputStream();
            byte[] bytes1 = "访问成功".getBytes();
            os.write(bytes1,0,bytes1.length);
            //关闭流
            is.close();
            os.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 客户端
public class MyClient {
    public static void main(String[] args) {
        //创建客户端对象,连接指定服务器的IP和端口号
        try {
            Socket socket = new Socket(InetAddress.getLocalHost().getHostAddress(),9090);
            //向服务器端发送一条数据
            OutputStream os = socket.getOutputStream();
            byte[] bytes = "请求访问".getBytes();
            os.write(bytes,0,bytes.length);
            //接收服务器端返回来的数据
            InputStream is = socket.getInputStream();
            byte[] bytes1 = new byte[1024];
            int length = is.read(bytes1);
            //将返回来的数据转换为字符串并打印
            String thisData = new String(bytes1, 0, length);
            System.out.println(thisData);
            //关闭流
            os.close();
            is.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

开启服务器客户端访问服务器打印结果:
服务器端:请求访问
客户端:访问成功

UDP通信

  • UDP通信的概念

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

  • 在JDK中提供了两个类用于实现UDP程序

    DatagramPacket类,该类的实例对象就相当于一个集装箱,用于封装UDP通信中发送或者接收的数据。
    DatagramSocket类,该类的作用就类似于码头,使用这个类的实例对象就可以发送和接收DatagramPacket数据包
  • DatagramPacket的构造方法和普通方法

    1. 构造方法
      DatagramPacket(byte[] buf,int length) 构造DatagramPacket,用来接收长度为length的数据包
      DatagramPacket(byte[] buf,int length,InetAddress address,int post) 构造数据包,用来将长度为length的包发送到指定主机上的指定端口号
    1. 常用方法
      getAddres() 返回某台机器的IP地址
      getPost() 返回某台远程主机的端口号
      getData() 返回数据缓冲区
      getLength() 返回将要发送或接收到的数据长度
  • DatagramSocket的构造方法和普通方法
    1. 构造方法
      DatagramSocket() 构造数据报套接字并将其绑定到本地主机上任何可以端口
      DatagramSocket(int post) 创建数据报套接字并将其绑定到本地主机上的指定端口
  • 常用方法
    receive(DatagramPacket p) 接收数据报包
    send(DatagramPacket p) 发送数据报包
简单的UDP通信Demo
  • 代码准备 接收端
public class MyReceiving {
    public static void main(String[] args) {
        try {
            //创建DatagramSocket对象(码头),并指定端口号
            DatagramSocket socket = new DatagramSocket(4573);
            //创建DatagramPacket对象(集装箱),将接收到的数据进行打包
            byte[] bytes = new byte[1024];
            DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
            //接收数据报包
            socket.receive(packet);
            //获取发送端发来的数据
            byte[] data = packet.getData();
            //获取数据的长度
            int length = packet.getLength();
            //查看主机IP为?
            String ip = packet.getAddress().getHostAddress();
            System.out.println("主机IP为:"+ip+" 发来的数据为:"+new String(data,0,length));
            //关闭流资源
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 发送端
public class MySender {
    public static void main(String[] args) {
        try {
            //创建DatagramSocket码头,用来发送数据报包
            DatagramSocket socket = new DatagramSocket();
            //准备数据
            byte[] bytes = "你好,世界".getBytes();
            int length = bytes.length;
            //创建DatagramPacket集装箱,将数据打包
            DatagramPacket packet = new DatagramPacket(bytes,length, InetAddress.getByName(InetAddress.getLocalHost().getHostAddress()),4573);
            //发送数据报包
            socket.send(packet);
            //关闭流资源
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

向运行接收端,再运行发送端
运行结果:
接收端:主机IP为:192.168.1.35 发来的数据为:你好,世界