Socket通信讲解及C/S结构实现UDP协议通信

news/2024/11/23 17:03:11/

Sokcet


一. Socket套接字

1.1 什么是套接字


所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制,是支持TCP/IP协议的路通信的基本操作单元

1.2 套接字主要类型


TCP流套接字

流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复送,并按顺序接收。流套接字之所以能够实现可靠的数据服务,原因在于其使用了传输控制协议,即TCP协议。即传输层TCP通信满足如下条件:

  • 有连接可靠传输
  • 面向字节流,即可以利用IO流分开进行多次收发
  • 有接受的缓冲区和传输缓冲区,没有传输大小限制

UDP数据报套接字

数据报套接字提供一种无连接的服务。该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。数据报套接字使用UDP协议进行数据的传输。由于数据报套接字不能保证数据传输的可靠性,对于有可能出现的数据丢失情况,需要在程序中做相应的处理。即传输层UDP通信满足如下条件:

  • 无连接不可靠传输
  • 面向数据报,即发送的内容必须一次性收发
  • 有接受的缓冲区,但没有发送的缓冲区,一次性最多传输64k大小

原始套接字

原始套接字与标准套接字(标准套接字指的是前面介绍的流套接字和数据报套接字)的区别在于:原始套接字可以读写内核没有处理的IP数据包,而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。因此,如果要访问其他协议发送的数据必须使用原始套接。

二. UDP常见API

2.1 DatagramSocket

DatagramSocket 用来构造传输UDP协议的类,表格介绍如何构造类对象

构造方法含义
DatagramSocket(int port)创建一个UDP数据报套接字Socket,绑定到指定的端口

表格介绍DatagramSocket 常用的传输和接受数据包方法

方法含义
void receive(DatagramPacket p)套接字接收数据报
void send(DatagramPacket p)套接字发送数据报包
void close()关闭套接字

2.2 DatagramPacket


DatagramPacket 用来构造传输数据包的类,表格介绍如何构造类对象

构造方法含义
DatagramPacket(byte[] buffer, int length)构造数据包接受数据,parm1:接受的内容,parm2:指定接受的长度
DatagramPacket(byte[] buffer, int offset, int length,SocketAddress address)构造数据包发送数据,parm1:发送内容,parm2:从字符组下标哪里开始发送,parm3:发送的长度、parm4:封装目的IP和端口对象

表格介绍DatagramPacket 常用的方法

方法含义
InetAddress getAddress()从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址
int getPort()从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主机端口号
byte[] getData()获取数据报中的数据

2.3 SocketAddress


在上述DatagramPacket对象发送数据包时,需要构造SocketAddress 来封装IP和端口,我们常使用SocketAddress 的子类InetSocketAddress来构建对象

构造方法含义
InetSocketAddress(InetAddress address, int port)创建一个Socket地址,包含IP地址和端口号

三. C/S结构测试


3.1 TCP通信


TCP网络协议通信可查看这篇文章:
利用TCP网络编程实现客户端和服务端简单交互

3.2 UDP通信


下面讲解如何利用Socket实现C/S结构的UDP协议通信,如下图为传输过程
在这里插入图片描述

服务端Server

//构建UDP协议的服务端
public class UDPServer {//构建套接字DatagramSocket socket;//构建协议对象(参数表示服务器端口号)public UDPServer(int serverPort) throws SocketException {socket = new DatagramSocket(serverPort);}//开启服务器进行监听public void startListening() throws IOException {System.out.println("===============服务器开启监听===================");Scanner scanner = new Scanner(System.in);//用来回复while (true){//1.构建数据包用来接受数据DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);//2.等待接受数据(没有返回值,但是已经接收到了数据)socket.receive(receivePacket);//3.将接受的数据取出String receiveData = new String(receivePacket.getData(),0,receivePacket.getLength());//如果客户端发送来ex或exit则退出if ("ex".equals(receiveData) || "exit".equals(receiveData)){System.out.println("===============服务器退出===================");break;}//4.根据请求进行回复System.out.println("收到消息:{"+receiveData+"}");System.out.println("请输入想要回复的信息:");String answer = scanner.nextLine();byte[] answerBytes = answer.getBytes();//5.将回复封装为数据包发送回客户端//注意:这里是根据接受的数据包来获取发送方的ip和端口DatagramPacket answerPacket = new DatagramPacket(answerBytes, 0, answerBytes.length, receivePacket.getSocketAddress());socket.send(answerPacket);}}public static void main(String[] args) throws IOException {UDPServer udpServer = new UDPServer(8899);udpServer.startListening();}}

客户端Client

//构建UDP协议的客户端
public class UDPClient {//服务器端口号int serverPort;//服务器ipString serverIp;//构建套接字DatagramSocket socket;//构建协议对象(参数表示服务器端口号和服务器ip地址)public UDPClient(int serverPort, String serverIp) throws SocketException {this.serverIp = serverIp;this.serverPort = serverPort;this.socket = new DatagramSocket();}public void startSend() throws IOException {System.out.println("===============客户端开启接受===================");//1.获取输入Scanner scanner = new Scanner(System.in);while (true){System.out.println("请输入想要发送的信息:");String request = scanner.nextLine();byte[] requestBytes = request.getBytes();//2.构建数据包//InetAddress.getByName()表示根据服务器主机名称解析ip地址DatagramPacket requestPacket = new DatagramPacket(requestBytes, 0, requestBytes.length, InetAddress.getByName(serverIp), serverPort);//3.发送数据包socket.send(requestPacket);//设定退出if ("ex".equals(request) || "exit".equals(request)){System.out.println("===============客户端退出===================");break;}//4.构建数据包用来获取响应DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);socket.receive(receivePacket);//5.将获取的数据取出String receiveData = new String(receivePacket.getData(),0,receivePacket.getLength());System.out.println("收到消息:{"+receiveData+"}");}}public static void main(String[] args) throws IOException {UDPClient udpClient = new UDPClient(8899, "192.168.31.104");udpClient.startSend();}
}

服务器端运行在192.168.31.104上,利用如下代码开启监听:

java -cp NetworkSocket-1.0-SNAPSHOT.jar com.nuaa.mySocket.server.UDPServer               

客户端运行在本地,通信对话如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yKrsakMb-1685345822236)(C:\Users\29973\AppData\Roaming\Typora\typora-user-images\image-20230529153224095.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c4U7ys98-1685345822237)(C:\Users\29973\AppData\Roaming\Typora\typora-user-images\image-20230529153244166.png)]


http://www.ppmy.cn/news/102581.html

相关文章

公网使用 SSH远程连接安卓手机 Termux -Android 手机服务器

文章目录 1.安装ssh2.安装cpolar内网穿透3.远程ssh连接配置4.公网远程连接5.固定远程连接地址 转载自cpolar极点云的文章:公网SSH远程连接Termux – 电脑使用安卓Termux 「无需公网IP」 使用安卓机跑东西的时候,屏幕太小,有时候操作不习惯。不…

59.网络训练中的超参调整策略—学习率调整1

学习率可以说是模型训练最为重要的超参数。 通常情况下,一个或者一组优秀的学习率既能加速模型的训练,又能得到一个较优甚至最优的精度。过大或者过小的学习率会直接影响到模型的收敛。当模型训练到一定程度的时候,损失将不再减少,这时候模型的一阶梯度接近零,对应Hessian…

Linux之lamp

lamp 一.概念 LAMP架构是目前成熟的企业网站应用模式之一,指的是协同工作的一整套系统和相关软件,能够提供动态Web站点服务及其应用开发环境。LAMP是一个缩写词,具体包括Linux操作系统、Apache网站服务器、MySQL数据库服务器、PHP&#xff…

解决Ubuntu系统/usr/lib/xorg/Xorg占用显卡内存问题

问题描述: 服务器新安装的Ubuntu系统,开机默认/usr/lib/xorg/Xorg线程会占用显卡内存,占用内存大小为4Mb,虽然占用量不大,但是对于强迫症患者来说实在太不友好! 解决方法:将xorg的线程移动到集…

渗透测试工具Burpsuite

学习文档 https://portswigger.net/burp/documentation/desktop/getting-started/download-and-install Burp Suite是一款流行的集成式Web应用程序安全测试工具套件,广泛应用于渗透测试、安全审计、黑盒测试和漏洞研究等Web安全领域。它由PortSwigger公司开发&…

MySQL学习笔记-2

一张表最多能存多少数据? MySQL本身并没有对单表最大记录数进行限制,这个数值取决于你的操作系统对单个文件的限制本身。阿里巴巴《Java开发手册》提出单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。 事实上,…

Javascript Object和Map之间的转换

简单的区分Map和Object Map是ES6退出的一个类型,特点:任何值都可作为属性名 Object特点:属性名只能是字符串(一开始我也不信,测试后才发现的) 代码图片 创建一个map类型 new Map([[key, value],[key1, value1] ])简单的介绍下面…

MyBatis-Plus 可视化代码生成器来啦,让你的开发效率大大提速!!

前言 在基于Mybatis的开发模式中,很多开发者还会选择Mybatis-Plus来辅助功能开发,以此提高开发的效率。虽然Mybatis也有代码生成的工具,但Mybatis-Plus由于在Mybatis基础上做了一些调整,因此,常规的生成工具生成的代码…