Java实现UDP通信/TCP通信

UDP通信

UDP 通信的基本概念

  • 无连接:UDP是一种无连接协议,发送数据之前不需要建立连接。
  • 不可靠:UDP不保证数据包的可靠传输,数据包可能会丢失。
  • 轻量级:由于不需要维护连接状态,UDP比TCP更轻量级。
  • 广播和多播:UDP支持广播和多播,适合于需要向多个接收者发送消息的应用场景。

UDP 是无连接的,所以我们不需要先建立连接,只需要指定 IP 和端口号。

Java 中的 UDP 编程

Java 通过 DatagramSocketDatagramPacket 类可以实现 UDP 通信:

  1. 发送消息:使用 DatagramSocket 来创建一个用于发送数据的 UDP 套接字。通过 DatagramPacket 将要发送的数据、目标 IP 地址和端口号封装成数据报,然后使用 send 方法发送数据。

  2. 接收消息:同样使用 DatagramSocket 来创建一个 UDP 套接字,但需要绑定到一个特定的端口,用于监听传入的数据报。利用 DatagramPacket 创建一个数据包作为接收缓冲区,然后调用 receive 方法接收数据。

  3. 区别:发送方不需要指定端口,可以使用任意可用端口发送数据。而接收方则必须绑定到一个特定的端口,以便监听和接收数据报。

入门例子

发送端

public class UdpClient {
    public static void main(String[] args) throws Exception {
        // 创建一个 UDP 套接字
        DatagramSocket socket = new DatagramSocket();

        // 要发送的数据
        byte[] data = "hello".getBytes();

        // 创建一个数据包,包含数据、数据长度、目标 IP 地址和端口号
        DatagramPacket packet = new DatagramPacket(
                data,                           
                data.length,                   
                InetAddress.getByName("127.0.0.1"),  
                10010              
        );

        // 发送数据包
        socket.send(packet);
        System.out.println("消息已发送~~~");

        // 关闭套接字
        socket.close();
    }
}

接收方

public class UdpServer {
    public static void main(String[] args) throws Exception {
        System.out.println("服务端启动~~~");

        // 创建一个 UDP 套接字,并绑定到指定端口(10010)
        DatagramSocket socket = new DatagramSocket(10010);

        // 用于接收数据的字节数组
        byte[] buffer = new byte[1024];

        // 创建一个数据包,用于接收数据
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        // 等待接收数据(阻塞调用)
        socket.receive(packet);

        // 从数据包中提取数据
        byte[] data = packet.getData();
        int length = packet.getLength();
        String receivedMessage = new String(data, 0, length); // 根据实际长度构建字符串
        System.out.println("收到数据: " + receivedMessage);
        socket.close();
    }
}

在这里插入图片描述

实时通信和多发多收

发送端

public class UdpClient {
    public static void main(String[] args) {
        // 创建一个 UDP 套接字
        try (DatagramSocket socket = new DatagramSocket();
             Scanner scanner = new Scanner(System.in)) {

            System.out.println("客户端启动,输入消息并按回车发送,输入 'exit' 退出:");

            while (true) {
                String message = scanner.nextLine();

                if ("exit".equalsIgnoreCase(message)) {
                    System.out.println("客户端退出");
                    break;
                }

                byte[] data = message.getBytes();
                // 创建数据包,包含数据、目标 IP 地址和端口号
                DatagramPacket packet = new DatagramPacket(
                        data,
                        data.length,
                        InetAddress.getByName("127.0.0.1"),
                        10010
                );
                socket.send(packet);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

接收方

public class UdpServer {
    public static void main(String[] args) {
        System.out.println("服务端启动,监听端口 10010");

        // 创建并绑定一个 UDP 套接字到端口 10010
        try (DatagramSocket socket = new DatagramSocket(10010)) {
            while (true) {
                // 用于接收数据的字节数组
                byte[] buffer = new byte[1024];

                // 创建数据包用于接收数据
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

                // 接收数据包(阻塞调用)
                socket.receive(packet);

                // 从数据包中提取数据
                String receivedMessage = new String(packet.getData(), 0, packet.getLength());

                System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) +"收到消息: " + receivedMessage);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

多发多收改一改就出来了


注意:UDP通信的形式

  • 单播:单台主机与单台主机之间的通信。
  • 广播:当前主机与所在网络中的所有主机通信。
  • 组播:当前主机与选定的一组主机的通信。

TCP通信

TCP通信中的核心类和数据流

在 Java 中,TCP 通信涉及两个主要的类:SocketServerSocket

1. 代表客户端的类:Socket

  • 用途Socket 类用于客户端与服务器端进行通信。它提供了流式 I/O 操作的功能,使客户端能够通过网络发送和接收数据。
  • 主要方法
    • getOutputStream():获取一个 OutputStream 对象,用于向服务器发送数据。
    • getInputStream():获取一个 InputStream 对象,用于从服务器接收数据。
  • 创建实例:客户端通过 new Socket(String host, int port) 创建连接到指定 IP 地址和端口的套接字实例。

2. 代表服务端的类:ServerSocket

  • 用途ServerSocket 类用于服务器端监听并接受来自客户端的连接请求。它用于在指定端口上等待客户端的连接,并为每个连接创建一个新的 Socket 对象。
  • 主要方法
    • accept():接受来自客户端的连接请求,返回一个新的 Socket 实例,用于与客户端通信。
  • 创建实例:服务器端通过 new ServerSocket(int port) 创建一个在指定端口上监听连接的套接字实例。

Java 实现 TCP 通信例子

客户端

public class TcpClient {
    public static void main(String[] args) {
        System.out.println("客户端启动,连接到服务器...");
        try (Socket socket = new Socket("127.0.0.1", 10010);
             OutputStream os = socket.getOutputStream();
             InputStream is = socket.getInputStream();
             Scanner scanner = new Scanner(System.in)) {

            while (true) {
                System.out.print("输入消息 (输入 'exit' 退出): ");
                String message = scanner.nextLine();

                if ("exit".equalsIgnoreCase(message)) {
                    System.out.println("客户端退出");
                    break;
                }

                // 发送消息到服务器
                os.write(message.getBytes());
                os.flush();

                // 接收服务器的响应
                byte[] bytes = new byte[1024];
                int len = is.read(bytes);
                if (len != -1) {
                    String response = new String(bytes, 0, len);
                    System.out.println("服务端返回数据: " + response);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务端

public class TcpServer {
    public static void main(String[] args) {
        System.out.println("服务器启动,等待客户端连接...");
        try (ServerSocket server = new ServerSocket(10010)) {
            while (true) {
                // 接受客户端连接
                try (Socket socket = server.accept()) {
                    System.out.println("客户端已连接:" + socket.getInetAddress());

                    // 读取客户端发送的数据
                    try (InputStream is = socket.getInputStream();
                         OutputStream os = socket.getOutputStream()) {

                        byte[] bytes = new byte[1024];
                        int len;
                        while ((len = is.read(bytes)) != -1) {
                            String receivedMessage = new String(bytes, 0, len);
                            System.out.println("接收到客户端数据: " + receivedMessage);

                            // 发送响应到客户端
                            String response = "服务端接收成功";
                            os.write(response.getBytes());
                            os.flush(); // 确保数据被及时发送
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Socket socket = server.accept(); 用于接受来自客户端的连接请求,并返回一个新的 Socket 实例,用于与客户端进行通信。accept() 方法是一个阻塞调用,这意味着服务器在调用此方法时会等待,直到有客户端尝试连接。如果没有客户端连接请求,服务器会在这里暂停执行,直到一个连接请求到达。

总结

  • 客户端 (Socket) 用于创建连接并进行数据发送和接收。
  • 服务端 (ServerSocket) 用于监听端口并接受客户端连接。
  • OutputStreamInputStream 用于在 TCP 连接中发送和接收数据。

在实际应用中,确保在发送数据后调用 flush() 方法,以确保数据及时发送,并在接收数据时正确处理流的关闭和异常情况。


❤觉得有用的可以留个关注~~❤

参考资源链接:[Java UDP穿透NAT实现P2P通信示例](https://wenku.youkuaiyun.com/doc/7az02nummb?utm_source=wenku_answer2doc_content) 要使用Java实现UDP通信并解决NAT穿透问题,可以参考《Java UDP穿透NAT实现P2P通信示例》。首先,需要了解Java的`DatagramSocket`类,它能够创建一个数据报套接字,并通过它可以发送和接收数据包。而`DatagramPacket`类代表了一个数据报包,包含了发送和接收数据所需的所有信息。实现UDP通信的步骤通常包括: 1. 初始化`DatagramSocket`,在NAT设备后创建监听端口。 2. 创建`DatagramPacket`对象,用于封送数据。 3. 使用`send()`方法发送`DatagramPacket`对象。 4. 使用`receive()`方法接收对端发送的`DatagramPacket`对象。 NAT穿透的关键在于如何让两个位于NAT之后的设备互相发现对方的真实IP地址和端口号。通过中介服务器的方式,客户端可以在连接到中介服务器后,交换自己的公网IP和端口信息。然后,它们可以尝试直接连接对方,如果成功,就可以建立点对点的UDP通信。如果无法直接连接,可能需要使用STUN或者TURN等技术来辅助完成NAT穿透。 具体到代码实现,需要处理异常情况,比如网络异常、超时等,并且在实际应用中,还需要考虑加密通信、身份验证等问题,以确保传输的安全性。《Java UDP穿透NAT实现P2P通信示例》中提供的示例代码是理解这些概念和实践这些技术的一个良好起点。如果你希望在解决当前问题后继续深入学习UDP通信和NAT穿透的高级话题,这份资料将是一个宝贵的学习资源。 参考资源链接:[Java UDP穿透NAT实现P2P通信示例](https://wenku.youkuaiyun.com/doc/7az02nummb?utm_source=wenku_answer2doc_content)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值