一.传输层:
1.UDP:无连接,不可靠,面向数据报,全双工.
2.TCP:有连接,可靠,面向字节流,全双工.
注意:这里的可不可靠是相对的,并且和安不安全无关.
二.UDP数据报套接字编程:
1.socket文件:表示网卡的这类文件.
2.DatagramPacket:表示一个UDP数据报.
三.代码实现:
1.回显服务器代码:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
public class EchoUDPServer {
// 服务器
private DatagramSocket socket = null;
public EchoUDPServer(int port) throws SocketException {
// 服务器端指定端口号
socket = new DatagramSocket(port);
}
public void start() throws IOException {
System.out.println("启动服务器");
// 由于服务器不会停止工作,所以使用死循环
while (true) {
// 1.读取请求,并解析
// 类似于数组的输出型参数,不过要手动输入数组类型和大小
DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
socket.receive(requestPacket);
// 客户端的数据是一个文本字符串
String request = new String(requestPacket.getData(), 0, requestPacket.getLength());
// 2.根据请求,计算机相应
String response = this.process(request);
// 3.把相应写会给客户端
// 注意第二个参数的长度
DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length,
requestPacket.getSocketAddress());
socket.send(responsePacket);
System.out.println(responsePacket.getSocketAddress() + " 接受内容:" + request + " 回复内容:" + response);
}
}
public String process(String request) {
return request;
}
public static void main(String[] args) throws IOException {
// 服务器端口号由自己指定(1025~65535),0~1024最好不要使用
EchoUDPServer server = new EchoUDPServer(1999);
//EchoUDPServer server = new DictionaryUDPServer(1999);
server.start();
}
}
2.回显客户端代码:
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class EchoUDPClient {
// 客户端
private DatagramSocket socket = null;
private String serverIp = null;
private int serverPort;
public EchoUDPClient(String serverIp, int serverPort) throws SocketException {
socket = new DatagramSocket();
this.serverIp = serverIp;
this.serverPort = serverPort;
}
public void start() throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.println("客户端启动");
while (true) {
System.out.println("->");
// 1.从控制台获取用户输入
String request = scanner.nextLine();
// 2.构造请求对象,发送给服务器
DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), 0, request.getBytes().length,
InetAddress.getByName(serverIp), serverPort);
socket.send(requestPacket);
// 3.读取服务器响应,解析响应内容
DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
socket.receive(responsePacket);
String response = new String(responsePacket.getData(), 0, responsePacket.getLength());
// 4.显示在屏幕上
System.out.println(response);
}
}
public static void main(String[] args) throws IOException {
EchoUDPClient client = new EchoUDPClient("127.0.0.1", 1999);
client.start();
}
}
3.字典服务器代码:
import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
public class DictionaryUDPServer extends EchoUDPServer{
private Map<String, String> dictionary = new HashMap<>();
public DictionaryUDPServer(int port) throws SocketException {
super(port);
dictionary.put("I", "我");
dictionary.put("love", "爱");
dictionary.put("China", "中国");
}
@Override
public String process(String request) {
return dictionary.getOrDefault(request, "没找到");
}
public static void main(String[] args) throws IOException {
EchoUDPServer server = new DictionaryUDPServer(1999);
server.start();
}
}
四.调试问题:
同时启动多个相同的代码: