600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > Java【网络编程1】使用 UDP 的 Socket API 实现客户端服务器通信(保姆级教学 附代码)

Java【网络编程1】使用 UDP 的 Socket API 实现客户端服务器通信(保姆级教学 附代码)

时间:2023-08-22 02:25:47

相关推荐

Java【网络编程1】使用 UDP 的 Socket API 实现客户端服务器通信(保姆级教学  附代码)

文章目录

前言一、认识 Socket(套接字), TCP 协议和 UDP 协议1, 什么是 Socket(套接字)2, 浅谈 TCP 协议和 UDP 协议的区别和特点 二、基于 UDP 协议的 Socket API1, DatagramSocket 类2, DatagramPacket 类 三、逐行代码解析网络编程1, 逐行解析客户端1.1, 核心成员方法 start() 2, 逐行解析服务器2.1, 核心成员方法 start() 四、完整代码1,客户端2, 服务器 总结

前言

📕各位读者好, 我是小陈, 这是我的个人主页

📗小陈还在持续努力学习编程, 努力通过博客输出所学知识

📘如果本篇对你有帮助, 烦请点赞关注支持一波, 感激不尽

📙 希望我的专栏能够帮助到你:

JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等

Java数据结构: 顺序表, 链表, 堆, 二叉树, 二叉搜索树, 哈希表等

JavaEE初阶: 多线程, 网络编程, TCP/IP协议, HTTP协议, Tomcat, Servlet, Linux, JVM等(正在持续更新)

上篇文章介绍了网络原理中 TCP/IP 五层网络模型, 以及数据在网络上使如何传输的基本知识

本篇将介绍网络编程中 : 基于 UDP 协议的 Socket 套接字的相关知识

提示:是正在努力进步的小菜鸟一只,如有大佬发现文章欠佳之处欢迎批评指点~ 废话不多说,直接上干货!

一、认识 Socket(套接字), TCP 协议和 UDP 协议

上篇提到, 我们程序员进行网络编程主要是在 TCP/UDP 五层网络模型中的应用层, 而数据在网络上传输, 需要进行封装和分用, 其中应用层需要调用传输层提供的 API , 这一组 API 就被称作 Socket API

1, 什么是 Socket(套接字)

📌概念 : Socket 套接字是由系统提供于网络通信的技术, 是基于 TCP/IP 协议的网络通信的基本操作党员, 基于 Socket 套接字的网络程序开发就是网络编程

👉要进行网络通信, 需要有一个 socket 对象, 一个socket 对象对应着一个socket 文件, 这个文件在网卡上而不是硬盘上, 所以有了 sokcet 对象才能通过操作内存来操作网卡

在 socket 文件中写数据相当于通过网卡发送数据, 在 socket 文件中读数据相当于通过网卡接收数据

Socket API 分为两类 : 基于 TCP 协议的 API , 和基于 UDP 协议的 API, 下面先认识一下 TCP 协议和 UDP 协议的区别和特点

2, 浅谈 TCP 协议和 UDP 协议的区别和特点

这里只做简单介绍, 这两个协议后续会单独详细介绍

二、基于 UDP 协议的 Socket API

UDP 的 Sokcet API 相对更简单易学, 本文先介绍这部分内容, TCP 的 Sokcet API 下篇文章介绍

❗️❗️❗️基于 UDP 协议的 Socket API 中, 要分清楚以下两个类 :

这个两个类的关系就相当于 : DatagramSocket 是取餐和送餐的外卖小哥, 而 DatagramSocket 就是外卖 (Datagram 就是数据报的意思, packet 是小包裹的意思)

记清楚啊 ! 别搞混了 ! ! 下面分别介绍这两个类的构造方法和成员方法, 待会写代码要用

1, DatagramSocket 类

👉DatagramSocket类的构造方法 :

👉DatagramSocket类的成员方法 :

表示Socket的这个类小总结 :

有两个构造方法, 一个是给服务器提供的, 一个是给客户端提供的

有三个成员方法, 分别是接收数据报, 发送数据报, 关闭套接字

2, DatagramPacket 类

👉DatagramPacket类的构造方法 :

👉DatagramPacket类的成员方法 :

表示Packet的这个类的小总结 :

有两个构造方法, 一个用于接收数据包, 一个用于发送数据报

有四个成员方法, 分别是获取 IP 地址, 获取端口号, 获取数据, 获取数据长度

看到这可能有点蒙了, 这都是啥啊, 太多了太乱了

别急, 有个大概的印象即可, 接下来逐行解析如何从 0 到 1 地进行客户端和服务器之间地网络编程, 代码敲完之后再消化吸收

三、逐行代码解析网络编程

下面我们写一个最简单的客户端服务器网络通信模型 : 客户端给服务器发送什么请求, 服务器就给客户发送什么响应(这是最简单但是毫无意义的回显服务器, 只是方便熟悉 UDP Socket 的 API 使用)

客户端和服务器各自为一个进程在运行, 双方互不干涉(当然我们现在要写的客户端服务器程序是在同一台主机上的)

一定是服务器先启动, 一直等待客户端发来请求, 所以按照时间顺序, 代码逻辑应该如下所示 :

有了这个思路, 下面正式开始使用上述 API 进行网络编程

1, 逐行解析客户端

创建一个类 UDPEchoClient 作为客户端

👉成员属性 :

1️⃣首先定义一个 Scoket 对象来接收和发送数据报

2️⃣客户端发送的请求数据报, 需要指定服务器的 IP 地址和端口号, 所以需要定义 serverIP 和 serverPort

public class UDPEchoClient {private DatagramSocket socket = null;// 1,socket对象private String serverIP = null;// 2,服务器IP地址private int serverPort = 0;// 3,服务器端口号}

👉构造方法 :

在构造方法中对上述三个成员属性进行初始化

public class UDPEchoClient {// 成员属性private DatagramSocket socket = null;// 1,socket对象private String serverIP = null;// 2,服务器IP地址private int serverPort = 0;// 3,服务器端口号// 构造方法public UDPEchoClient(String serverIP, int serverPort) throws SocketException {socket = new DatagramSocket();this.serverIP = serverIP;this.serverPort = serverPort;}}

👉main 方法 :

1️⃣构造 udpEchoClient 对象, 由于服务器在本机, IP 地址为"127.0.0.1", 端口号随意指定 [1024, 65535] 之间的任意一个

2️⃣调用 UDPEchoClient 类的核心成员方法 start(), 这个方法实现了客户端的核心逻辑

public class UDPEchoClient {// 成员属性private DatagramSocket socket = null;// 1,socket对象private String serverIP = null;// 2,服务器IP地址private int serverPort = 0;// 3,服务器端口号// 构造方法public UDPEchoClient(String serverIP, int serverPort) throws SocketException {socket = new DatagramSocket();this.serverIP = serverIP;this.serverPort = serverPort;}// main 方法public static void main(String[] args) throws IOException {UDPEchoClient udpEchoClient = new UDPEchoClient("127.0.0.1", 9999);udpEchoClient.start();}}

1.1, 核心成员方法 start()

1️⃣构造一个 Scanner 对象, 从控制台输入字符串, 这个字符串当作请求的内容

2️⃣核心逻辑在一个 while(true) 循环中, 实现多次发送请求

public void start() throws IOException {Scanner in = new Scanner(System.in);while(true) {}}

图解如下

⚠️⚠️⚠️注意 :

上述代码中, 要分清 : socket.send(DatagramPacket p)用于发送数据报, socket.receive(DatagramPacket p)用于接收数据报,

而参数都是 DatagramPacket 类型, 所以在发送和接收之前, 需要 new 出来数据报对象呀, 但是用于发送和接受的数据报的构造方法是不同的, 请结合上图中黄色部分再做区分

另外, start()中第三步相当于是把数据报中的数据(btye[])解析成字符串, 方便我们观察

2, 逐行解析服务器

创建一个类 UDPEchoServer 作为服务器

👉成员属性 :

服务器不需要指定客户端的 IP 地址和端口号, 所以构造方法只需要定义一个 socket 对象即可

public class UDPEchoServer {// 成员属性private DatagramSocket socket = null;// socket 对象}

👉构造方法 :

用于实例化服务器的 socket 对象, 别忘了服务器使用的 socket 需要绑定本机的端口号

public class UDPEchoServer {// 成员属性private DatagramSocket socket = null;// socket 对象// 构造方法public UDPEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}}

👉main 方法 :

1️⃣用于实例化 UDPEchoServer 对象, 端口号为刚才客户端指定的端口号

2️⃣调用 UDPEchoServer 类的核心成员方法 start(), 这个方法实现了服务器的核心逻辑

public class UDPEchoServer {// 成员属性private DatagramSocket socket = null;// socket 对象// 构造方法public UDPEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}// main方法public static void main(String[] args) throws IOException {UDPEchoServer server = new UDPEchoServer(9999);server.start();}}

2.1, 核心成员方法 start()

服务器启动之后, 等待客户端发来消息, 实际上一台服务器会服务多个客户端, 所以核心代码写在 while(true) 循环中, 这样才能够处理完一个客户端发来的请求之后继续处理

public void start() throws IOException {while(true) {}}

图解如下 :

写完客户端之后再写服务器就相对熟悉了, 都是一个套路 :在发送或者接收数据报之前, 要先 new 出 DatagramPacket 对象, 只是需要注意构造方法的使用

需要补充的是, 在第一步中, 发送完数据报之后, 把数据报解析成了字符串方便处理(并不一定所有的服务器程序都需要这么做, 在当前这个程序下处理成字符串更方便而已)

而 process 方法用于处理请求, 真实的服务器的这一步会根据业务逻辑把代码写的非常完善, 而我们实现的仅仅是最简单的回显服务器, 所以我们的 process 方法只需要 return 即可

👇客户端运行效果截图 : 注意一定要先运行服务器

客户端输出的是请求(字符串) + 响应(字符串)

👇服务器运行效果截图

服务器输出的是本机IP地址, 客户端端口号(系统自动分配的), 请求(String), 响应(String)

四、完整代码

1,客户端

import javax.imageio.stream.ImageInputStream;import java.io.IOException;import .*;import java.util.Scanner;public class UDPEchoClient {// 成员属性: 1,socket对象 2,服务器IP地址 3,服务器端口号private DatagramSocket socket = null;private String serverIP = null;private int serverPort = 0;// 构造方法public UDPEchoClient(String serverIP, int serverPort) throws SocketException {socket = new DatagramSocket();this.serverIP = serverIP;this.serverPort = serverPort;}public void start() throws IOException {Scanner in = new Scanner(System.in);while(true) {// 1,从控制台输入数据, 构造成 DatagramPacket , 把这个请求发给服务器String requestString = in.next();DatagramPacket requestPacket = new DatagramPacket(requestString.getBytes(), requestString.getBytes().length, InetAddress.getByName(serverIP), serverPort);socket.send(requestPacket);// 2,接收服务器返回的响应DatagramPacket responsePacket = new DatagramPacket(new byte[9999], 9999);socket.receive(responsePacket);// 3,转换成字符串String responseString = new String(responsePacket.getData(), 0, responsePacket.getLength());// 打印客户端请求 + 服务器响应System.out.println(requestString + " + " + responseString);}}public static void main(String[] args) throws IOException {UDPEchoClient udpEchoClient = new UDPEchoClient("127.0.0.1", 9999);udpEchoClient.start();}}

2, 服务器

import java.io.IOException;import .DatagramPacket;import .DatagramSocket;import .InetAddress;import .SocketException;import java.util.Scanner;public class UDPEchoServer {// 成员属性: 定义一个Socket对象private DatagramSocket socket = null;// 构造方法public UDPEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}public void start() throws IOException {while(true) {// 1,从客户端读取请求数据DatagramPacket requestPacket = new DatagramPacket(new byte[9999], 9999);socket.receive(requestPacket);String requestString = new String(requestPacket.getData(), 0, requestPacket.getLength());// 2,处理请求String responseString = process(requestString);// 3,把响应发送给客户端DatagramPacket responsePacket = new DatagramPacket(responseString.getBytes(), responseString.getBytes().length, requestPacket.getAddress(), requestPacket.getPort());socket.send(responsePacket);// 打印客户端IP地址 + 客户端端口号 + 客户端请求服务器相应System.out.println(requestPacket.getAddress().toString() + " + " + requestPacket.getPort() + " + "+ requestString + " + " + responseString);}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {UDPEchoServer server = new UDPEchoServer(9999);server.start();}}

总结

以上就是本篇的全部内容, 主要介绍了 : 基于 UDP 协议的 Socket API , 以及利用这些 API 写了一个最简单但无意义的客户端服务器网络通信程序

有一点需要说明 : 这个程序中没有调用 sockt.close() 是因为这客户端服务器的生命周期很长, 并没有频繁的销毁和创建,

如果我们的客户端和服务器停止运行了, 那么我们的main方法也结束了, 整个 Java 进程就结束了, 所以没必要显式的调用 close

方法

再回顾一下, 基于 UDP 协议的 Socket API 主要有两个类:

👉表示 Socket 的这个类, DatagramSocket :

有两个构造方法, 一个是给服务器提供的, 一个是给客户端提供的

有三个成员方法, 分别是接收数据报, 发送数据报, 关闭套接字

👉表示 Packet 的这个类, DatagramPacket :

有两个构造方法, 一个用于接收数据包, 一个用于发送数据报

有四个成员方法, 分别是获取 IP 地址, 获取端口号, 获取数据, 获取数据长度

下篇分享基于 TCP 协议的 Socket API, 关于 TCP 和 UDP 协议会在后续的文章详细介绍

如果本篇对你有帮助,请点赞收藏支持一下,小手一抖就是对作者莫大的鼓励啦😋😋😋~

上山总比下山辛苦

下篇文章见

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。