UDP 和 TCP 通信中发送与接收的核心代码片段

可以用类似下面这种方式包装类

TCP服务端:

1
2
3
4
5
6
7
8
ServerSocket serverSocket = new ServerSocket(9000);  
Socket accept = serverSocket.accept();

BufferedReader br = new BufferedReader(new InputStreamReader(accept.getInputStream())); //获取客户端消息

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream())); //相应消息

PrintWriter pw = new PrintWriter(accept.getOutputStream(),true); //自动刷新缓冲区

TCP客户端:

1
2
3
4
5
6
7
Socket socket = new Socket(InetAddress.getLoopbackAddress(),9000); //确认发送地址  

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); //发送数据

BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //输入数据

BufferedReader brResult = new BufferedReader(new InputStreamReader(socket.getInputStream())); //读入返回数据

一、TCP 核心代码(面向连接、字节流)

1. 服务端(接收与响应)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.net.*;
import java.io.*;

public class TCPServer {
public static void main(String[] args) throws IOException {
// 1. 监听端口(建立连接的入口)
ServerSocket serverSocket = new ServerSocket(8888);
// 2. 阻塞等待客户端连接(三次握手)
Socket clientSocket = serverSocket.accept();

// 3. 获取输入流(接收数据,需缓冲区)
InputStream in = clientSocket.getInputStream();
byte[] recvBuf = new byte[1024]; // 接收缓冲区(核心)
int len = in.read(recvBuf); // 阻塞读数据,返回实际长度
String recvData = new String(recvBuf, 0, len);
System.out.println("收到客户端:" + recvData);

// 4. 获取输出流(发送响应)
OutputStream out = clientSocket.getOutputStream();
out.write("服务端已收到".getBytes()); // 直接发送字节流

// 5. 关闭资源
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
}

2. 客户端(发送与接收)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.net.*;
import java.io.*;

public class TCPClient {
public static void main(String[] args) throws IOException {
// 1. 连接服务端(三次握手)
Socket socket = new Socket("127.0.0.1", 8888);

// 2. 获取输出流(发送数据)
OutputStream out = socket.getOutputStream();
out.write("客户端发送数据".getBytes()); // 发送字节流

// 3. 获取输入流(接收响应,需缓冲区)
InputStream in = socket.getInputStream();
byte[] recvBuf = new byte[1024]; // 接收缓冲区(核心)
int len = in.read(recvBuf);
String recvData = new String(recvBuf, 0, len);
System.out.println("收到服务端:" + recvData);

// 4. 关闭资源
out.close();
in.close();
socket.close();
}
}

二、UDP 核心代码(无连接、数据报)

1. 接收端(服务端角色)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.net.*;

public class UDPReceiver {
public static void main(String[] args) throws Exception {
// 1. 创建Socket并绑定端口
DatagramSocket socket = new DatagramSocket(9999);

// 2. 创建接收缓冲区和数据报(核心)
byte[] recvBuf = new byte[1024]; // 接收缓冲区
DatagramPacket recvPacket = new DatagramPacket(recvBuf, recvBuf.length);

// 3. 阻塞接收数据(无连接,直接等数据报)
socket.receive(recvPacket); // 数据存入recvPacket

// 4. 解析数据(从缓冲区取实际长度)
int len = recvPacket.getLength(); // 实际数据长度
String recvData = new String(recvBuf, 0, len);
System.out.println("收到:" + recvData);

// 5. 关闭Socket
socket.close();
}
}

2. 发送端(客户端角色)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.net.*;

public class UDPSender {
public static void main(String[] args) throws Exception {
// 1. 创建Socket(无需连接)
DatagramSocket socket = new DatagramSocket();

// 2. 准备发送数据(打包成数据报)
String sendData = "UDP发送的数据报";
byte[] sendBuf = sendData.getBytes(); // 发送数据转字节
// 目标地址和端口(必须指定,无连接特性)
InetAddress targetIp = InetAddress.getByName("127.0.0.1");
int targetPort = 9999;
// 封装数据报(含缓冲区、长度、目标地址)
DatagramPacket sendPacket = new DatagramPacket(
sendBuf, sendBuf.length, targetIp, targetPort
);

// 3. 发送数据报
socket.send(sendPacket);

// 4. 关闭Socket
socket.close();
}
}

三、核心代码对比关键点

场景 核心代码差异
TCP 连接 服务端用ServerSocket.accept()阻塞等连接,客户端用new Socket(ip, port)主动连接
TCP 收发 依赖SocketInputStream/OutputStream,通过read(缓冲区)/write(字节)操作
UDP 收发 无连接,收发均用DatagramPacket,接收必须绑定byte[]缓冲区,发送必须指定目标 IP + 端口
缓冲区作用 TCP:存字节流片段,需用read()返回值判断实际长度;UDP:存完整数据报,用getLength()取有效长度