帮助文档
专业提供香港服务器、香港云服务器、香港高防服务器租用、香港云主机、台湾服务器、美国服务器、美国云服务器vps租用、韩国高防服务器租用、新加坡服务器、日本服务器租用 一站式全球网络解决方案提供商!专业运营维护IDC数据中心,提供高质量的服务器托管,服务器机房租用,服务器机柜租用,IDC机房机柜租用等服务,稳定、安全、高性能的云端计算服务,实时满足您的多样性业务需求。 香港大带宽稳定可靠,高级工程师提供基于服务器硬件、操作系统、网络、应用环境、安全的免费技术支持。
服务器资讯 / 香港服务器租用 / 香港VPS租用 / 香港云服务器 / 美国服务器租用 / 台湾服务器租用 / 日本服务器租用 / 官方公告 / 帮助文档
UDP Socket API 的讲解,以及回显服务器客户端的实现
发布时间:2024-03-07 03:43:10   分类:帮助文档
UDP Socket API 的讲解,以及回显服务器客户端的实现






文章目录
UDPDatagramSocktet APIDatagramPacket API
UDP 客户端服务器实现



UDP
先来认识一下 UDP 的 socket api,两个核心的类:DatagramSocket、DatagramPacket.
DatagramSocktet API
是一个 socket 对象。

什么是 socket?
操作系统,使用文件这样的概念,来管理一些软硬件资源。网卡,操作系统也是使用 文件 的方式来管理网卡的。表示网卡的这类文件,称为 Socket 文件。Java 中的 socket 对象,就对应 系统里的 socket 文件。

因此,想要进行网络通信,必须得先有 socket 对象。
DatagramSocket构造方法:
方法签名方法说明DatagramSocket()创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口 (一般用于客户端)DatagramSocket(int port)创建一个UDP数据报套接字的Socket,绑定到本机指定的端口 (一般用于服务端)
DatagramSocket() 在客户端这边使用,客户端使用哪个端口,是系统自动分配的。

一个客户端的主机,上面运行的程序很多,天知道你手动指定的端口是不是被别的程序占用了。因此,让系统自动分配一个端口是更明智的选择.

DatagramSocket(int port) 在服务器这边使用,服务器使用哪个端口,是手动指定的。

对于服务器来说,需要有一个固定的端口号,方便其他客户端找到。

DatagramSocket 方法:
方法签名方法说明void receive(DatagramPacket p)从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待)void send(DatagramPacket p)从此套接字发送数据报包(不会阻塞等待,直接发送)void close()关闭此数据报套接字
DatagramPacket API
表示了一个 UDP 发送和接收的数据报。
代表了系统中设定的 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()获取数据报中的数据
UDP 客户端服务器实现
接下来手动写 UDP 客户端服务器
实现一个最简单的回显服务器 (Echo Server).

回显服务器:顾名思义,就是客户端发啥,服务器就返回啥。

我们知道,一个服务器可以供多个客户端同时使用,因此我们最先想到的是利用多线程来实现 UDP. 但事实上 UDP 服务器不需要多线程,是因为UDP是无连接的,每个数据包都是独立的,服务器只需要监听一个端口,接收数据包并处理即可。
核心思路:
服务器:
接收客户端发送过来是请求 ( 收到的请求是一个 DatagramPacket 类 ),并解析出请求内容 ( 转换成 String 类)。根据请求做出响应把响应返回给客户端 客户端
从控制台读取用户输入的内容.构造请求对象,并发给服务器.接收服务器给出的响应,并解析出响应内容.将响应内容打印出来. 客户端服务器相互关联:通过 ip 和 端口号.
ip:每个服务器都有自己的 ip 地址,客户端需要通过 ip 找到服务器。(127.0.0.1 就表示自己的电脑)端口号:每个服务器有很多个端口,端口号就是用于客户端到底是访问服务器的哪个端口。
实现 UDP 会用到的方法:

getSocketAddress() :就是 getAddress() 和 getPort() 的结合体. [address:port]


InetAddress.getByName(“主机名”):如果传入的是主机名,则该方法会尝试解析该主机名,如果解析成功,则返回对应的 IP 地址;如果解析失败,则抛出 UnknownHostException 异常.


getData():获取数据报中的数据.

客户端代码:
import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class UdpEchoClient {

private DatagramSocket socket = null;
private String serverIp ;
private int serverPort;

public UdpEchoClient(String ip, int port) throws SocketException {
serverIp = ip;
serverPort = port;
// 这个 new 操作,就不再指定端口了,让系统自动分配一个空闲端口
socket = new DatagramSocket();
}

public void start () throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.println("客户端启动!");
while (true) {
// 1. 从控制台读取用户输入的内容
System.out.print("->");
String request = scanner.nextLine();
// 2. 构造请求对象,并发给服务器
DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), 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 {
UdpEchoClient client = new UdpEchoClient("127.0.0.1",9090);
client.start();
}
}

/*
客户端启动!
->hello
hello
*/

服务器代码:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

//回显服务器
//客户端发的请求是啥,服务器返回的响应就是啥
public class UdpEchoServer {

private DatagramSocket socket = null;

public UdpEchoServer(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 = process(request);
// 3.把响应写回给客户端
// 此时需要告知网卡,要发的内容是啥,要发给谁
DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length, requestPacket.getSocketAddress());
socket.send(responsePacket);
//记录日记,方便观察程序执行效果
System.out.printf("[%s:%d] req: %s , resp: %s\n", responsePacket.getAddress().toString(), responsePacket.getPort(),request, response);
}
}

//根据请求计算响应,由于是回显程序,响应内容和请求完全一样
private String process(String request) {
return request;
}

public static void main(String[] args) throws IOException {
UdpEchoServer server = new UdpEchoServer(9090); //设定服务器的端口号为 9090
server.start();
}
}

/*
服务器启动!
[/127.0.0.1:54015] req: hello , resp: hello
*/

问题1:我电脑上的 udp 服务器,别人可以访问吗??

答:不可以,因为我当前的电脑上没有 “外网IP”。解决办法就是买一个有外网的云服务器 😆

问题2:socket 对象用完后需要关闭吗??

答:需要,我们要知道为什么要关闭 socket 对象。最主要的就是释放系统中的 socket 文件,从而释放文件描述符。
但是上述代码中我们为什么没去关闭 socket 对象呢?
因为对于咱们这个服务器来说,DatagramSocket 不关闭,问题不大。整个程序中只有一个 socket 对象,不是频繁创建的,生命周期是跟随整个进程的。但是如果是有多个 socket 对象, 且 socket 对象生命周期更短需要频繁创建释放。一定要记得去 close 。





香港云服务器租用推荐
服务器租用资讯
·广东云服务有限公司怎么样
·广东云服务器怎么样
·广东锐讯网络有限公司怎么样
·广东佛山的蜗牛怎么那么大
·广东单位电话主机号怎么填写
·管家婆 花生壳怎么用
·官网域名过期要怎么办
·官网邮箱一般怎么命名
·官网网站被篡改怎么办
服务器租用推荐
·美国服务器租用
·台湾服务器租用
·香港云服务器租用
·香港裸金属服务器
·香港高防服务器租用
·香港服务器租用特价