文章目录
- 1. Socket简介
- 2. DatagramSocket
- 3. DatagramPacket
- 4. InetSocketAddress
- 5. 实现UDP版的回显服务器
1. Socket简介
Socket(Java套接字)是Java编程语言提供的一组类和接口,用于实现网络通信。它基于Socket编程接口,提供了一种简单而强大的方式来实现网络应用程序。
socket类库提供了丰富的方法和功能,用于处理网络通信的各个方面。它支持TCP和UDP协议,可以实现可靠的、面向连接的通信(TCP)或不可靠的、无连接的通信(UDP)。Java Socket还提供了一些高级功能,如多线程处理、异步通信、加密通信等,以满足不同网络应用的需求。
本文主要使用Socket实现UDP版的客户端和服务器
-
DatagramSocket
是UDP Socket,用于发送和接收UDP数据报。 -
DatagramPacket
是UDP Socket发送和接收的数据报。
2. DatagramSocket
DatagramSocket是Java网络编程中用于实现UDP协议的类。它是基于Socket类的子类,用于发送和接收UDP数据报。
DatagramSocket 的构造方法:
方法 | 说明 |
---|---|
DatagramSocket() | 创建一个UDP数据报套接字的socket,绑定本机任意一个随机端口(一般用户客户端) |
DatagramSocket(int port) | 创建一个UDP数据套接字的socket,绑定指定的port端口(一般用于服务端) |
DatagramSocket的常用方法如下:
方法 | 说明 |
---|---|
void receive(DatagramPacket p) | 从此套接字接收数据报,如果没有接收到数据报,会阻塞等待 |
void send(DatagramPacket p) | 从此套接字发送数据包 |
void close() | 关闭数据报套接字 |
3. DatagramPacket
DatagramPacket是Java网络编程中用于封装和解析UDP数据报(Datagram)的类。它用于在DatagramSocket中发送和接收UDP数据报
DatagramPacket的构造方法:
方法 | 说明 |
---|---|
DatagramPacket(byte[] buf, int length) | 构造一个DatagramPacket以用来接收数据报,接收的数据保存在 字节数组(第一个参数buf)中,接收指定长度(第二个参数 length) |
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) | 构造一个DatagramPacket以用来发送数据报,发送的数据为字节 数组(第一个参数buf)中,从0到指定长度(第二个参数 length)。address指定目的主机的IP和端口号 |
DatagramPacket的常用方法:
方法 | 说明 |
---|---|
InetAddress getAddress() | 从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取 接收端主机IP地址 |
int getPort() | 从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主机端口号 |
byte[] getData() | 获取数据报中的数据 |
4. InetSocketAddress
InetSocketAddress是Java网络编程中用于表示IP地址和端口号的类。它是SocketAddress类的子类,用于在网络通信中指定主机的地址和端口。
简单介绍一下InetSocketAddress的构造方法:
InetSocketAddress(InetAddress addr,int port) | 创建一个Socket地址,包含IP地址和端口号 |
---|
5. 实现UDP版的回显服务器
回显服务器(Echo Server)是一种简单的网络服务器应用,它接收客户端发送的数据,并将接收到的数据原样返回给客户端。
客户端代码:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;
public class UdpEchoClient {
private DatagramSocket socket = null;
private String serverIp;
private int serverPort;
public UdpEchoClient(String serverIp, int serverPort) throws SocketException {
socket = new DatagramSocket(serverPort);
this.serverIp = serverIp;
this.serverPort = serverPort;
}
public void start() throws IOException {
System.out.println("客户端上线!");
Scanner scanner = new Scanner(System.in);
while (true) {
// 读取用户输入的内容
System.out.println("-> ");
String request = scanner.next();
// 构造 UDP请求,并发送给服务器
DatagramPacket reqPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,
InetAddress.getByName(this.serverIp), this.serverPort);
socket.send(reqPacket);
// 从服务器读取响应
DatagramPacket respPacket = new DatagramPacket(new byte[4096], 4096);
socket.receive(respPacket);
String resp = new String(respPacket.getData(), 0, respPacket.getLength());
}
}
public static void main(String[] args) throws IOException {
UdpEchoClient echoClient = new UdpEchoClient("127.0.0.1", 6666);
echoClient.start();
}
}
服务器代码:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UdpEchoServer {
private DatagramSocket socket = null;
// port 为服务器要绑定的端口
public UdpEchoServer(int port) throws SocketException {
socket = new DatagramSocket(port);
}
/**
* 服务器启动方法
*/
public void start() throws IOException {
System.out.println("服务器启动!");
while (true) {
// 读取请求并解析
DatagramPacket reqPacket = new DatagramPacket(new byte[4096], 4096);
socket.receive(reqPacket);
// 解析请求
String req = new String(reqPacket.getData(), 0, reqPacket.getLength());
// 计算响应
String resp = process(req);
// 将响应返回给客户端
DatagramPacket respPacket = new DatagramPacket(resp.getBytes(), resp.getBytes().length,
reqPacket.getSocketAddress());
socket.send(respPacket);
// 打印日志
System.out.printf("[%s:%d] req: %s;resp: %s\n", reqPacket.getSocketAddress().toString(),
reqPacket.getPort(), req, resp);
}
}
/**
* 根据请求计算响应
* 因为是 回显服务器,直接返回即可
*
* @param req
*/
private String process(String req) {
return req;
}
public static void main(String[] args) throws IOException {
UdpEchoServer echoServer = new UdpEchoServer(6666);
echoServer.start();
}
}
运行流程:
运行结果:
另外服务器是给多个客户端提供服务器的,IDEA默认是无法启动多个客户端的,因此手动设置