[网络编程】网络编程的基础使用
系列文章目录
1、 初识网络
网络编程套接字
- 系列文章目录
- 前言
- 一、TCP和UDP协议的引入
- 二、UDP网络编程
- 1.Java中的UDP
- 2.UDP回显代码案例
- 3.UDP网络编程的注意事项
- 三、TCP网络编程
- 1.TCP回显代码案例
- 2.TCP多线程使用
- 总结
前言
在学习完基础的网络知识后,完成跨主机通信的网络编程。
一、TCP和UDP协议的引入
注意:TCP协议并非TCP/IP模型。
TCP和UDP都属于传输层协议中的一种,为应用层提供服务。但是二者之间的特点和差异都很大,因此有了两套API分别应用于二者。
特点:
TCP:有连接,可靠传输,面向字节流,全双工
UDP:无连接、不可靠传输、面向数据报、全双工
其中有连接的意思是如同打电话一样,在电话接通以后才能相互通信;无连接就像发送短信,不需要“先接通”,允许直接发送。
可靠传输的意思是将要传输的数据尽可能传输给对方,不可靠传输的意思是在数据传输时不关心对方是否收到信息。
面向字节流,和文件操作中的字节流类似,读写操作十分灵活。
面向数据报:在UDP协议中,传输数据的基本单位时一个个UDP数据报,一次读写只能读写一个完整的UDP数据报。
全双工:在一条链路中能够进行双向通信;半双工:一条链路中只能进行单向通信。
二、UDP网络编程
1.Java中的UDP
在Java中,引入系统的API(称为Socket API)并进行封装,在Java中主要有两个类:DatagramSocket和DatagramPacket。
1)DatagramSocket:socke可以理解为是一种文件,socket文件可以视为对网卡的硬件设备进行的抽象化。在UDP中对于操作系统中socket概念的封装,针对该对象进行读写操作,也可以理解为对网卡硬件设备的操作。
2)DatagramPacket: 针对UDP数据报的一个抽象表示,一个DatagramPacket对象,就相当于一个UDP数据报。一次发送/接收就相当于传输了一个DatagramPacket对象。
2.UDP回显代码案例
所谓回显代码,即客户端请求什么内容,服务器就返回什么代码。回显代码中没有实现复杂的逻辑,能够最简单的反映UDP的服务器和客户端之间的互动情况。
- UDPEchoServer:在Server端,端口号是固定的,DaragramSocket 在构造方法中传入端口号。在服务器启动之后需要不断接收请求和返回请求值。
在DatagramSocket中的receive方法负责接收客户端发送过来的请求, 将接收到的数据转换成字符串request,作为后面处理请求的参数。通过方法process运行之后返回的结果需要数据报进行封装,因此在结果返回之后,新建一个数据报对象并将字符串结果转换成字节流。通过socket.send方法发送。
public class UdpEchoServer {DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}public void start() throws IOException {System.out.println("服务器启动");while (true) {DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);socket.receive(requestPacket);String request = new String(requestPacket.getData(),0,requestPacket.getLength());String response = this.process(request);DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),0,response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);System.out.printf("[%s:%d] req = %s,res = %s \n",requestPacket.getAddress(),requestPacket.getPort(),request,response);}}private String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer server = new UdpEchoServer(9090);server.start();}
}
- UDPEchoClient:在客户端,用户发起请求并接收返回的结果。对服务器发送的信息应该包括用户IP地址、用户端口号的信息。通过DatagramSocket类中的send方法发送请求。
在start()方法中,新建字符串request来保存用户所发送的请求,由于网卡的的性质需要发送数据报格式。为了解决这个问题,我们需要new一个数据报requestPacket对请求内容进行封装。同时我们需要把字符串的数据转换成字节流的数据。
INetAddress中的getByName方法中存储着服务器的IP地址以及服务器的端口号。
在发送请求之后等待数据接收状态下,receive()方法进入阻塞状态。
在接收到数据之后,将字节流数据转换成字符串的形式,用response接收。
public class UdpEchoClient {private DatagramSocket socket = null;private String serverIp;private int serverPort;public UdpEchoClient(String serverIp, int serverPort) throws SocketException {this.socket = new DatagramSocket();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();DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),0,request.getBytes().length,InetAddress.getByName(serverIp),serverPort);socket.send(requestPacket);DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);String response = new String(responsePacket.getData(),0, responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient client = new UdpEchoClient("127.0.0.1",9090);client.start();}
}
最终,我们成功完成了UDP中基础的数据请求与通信。
3.UDP网络编程的注意事项
- 在上面的UDP编程中,主要可以分为以下几个步骤(如下图所示)
- 进程的运行顺序是先启动服务器,再启动客户端。
- 在代码编写过程中,都没有涉及到close操作的原因:DatagreamSocket作为这个进程的对象和服务器程序的生命周期是一样的。如果在某个程序中,socket对象的生命周期和进程不一样,需要提前释放的话就需要进行close操作。
三、TCP网络编程
在TCP中的socket api中与UDP不同的是,在TCP中ServerSocket类是专门给服务器使用的。 Socket类是专门作用于客户端和服务器之间进行通信使用的。
由于TCP属于有连接和可靠传输,他们之间必须时刻保持通信状态。在ServerSocket中有accept方法接收客户端发来的请求。
1.TCP回显代码案例
我们知道TCP是面向字节流的,因此在TCP中的操作是以流对象进行操作的。
- 在Socket类中,通过两个方法:getInputStream和getOutpurStream 进行操作的。
- 在服务器中,start方法中通过accept同意客户端连接。接下来调用processConnection
- 使用Scanner读取InputStream流中的数据内容。
- 使用Scanner的好处是对于客户端传输进来的字节流,Scanner会自动将这些数据转换成String。
- 在方法start中,循环保持与客户端之间的通信。通过scanner.hasNext()方法判断是否还有输入,当客户端关闭了连接之后,服务器的输入流会收到一个EOF信号,从而判断出没有输入了,最终结束循环。
- 将回显的结果以response的结果以二进制的形式写入outputStream中。
- 最后,处理完client的请求之后,客户端下线之后,回收client对象,当下次重新有新的客户端时重新启用。
public void start() throws IOException {System.out.println("服务器启动!");//accept可以阻塞等待Socket socketClient = serverSocket.accept();processConnection(socketClient);}private void processConnection(Socket socketClient) throws IOException {System.out.printf("[%s:%d] 客户端上线\n", socketClient.getInetAddress(),socketClient.getPort());try(InputStream inputStream = socketClient.getInputStream();OutputStream outputStream = socketClient.getOutputStream()) {Scanner scanner = new Scanner(inputStream);while (true) {if (!scanner.hasNext()) {System.out.printf("[%s:%d] 客户端下线\n", socketClient.getInetAddress(),socketClient.getPort());break;}//接收客户端发送过来的请求String request = scanner.next();//处理请求String response = process(request);//把响应写回客户端outputStream.write(response.getBytes(),0,response.getBytes().length);//服务器打印日志System.out.printf("[%s:%d] req = %s resp = %s",socketClient.getInetAddress(),socketClient.getPort(),request,response);}} catch (IOException e) {throw new RuntimeException(e);}finally {socketClient.close();}}
在客户端方面,通过scannerNetWork读取inputStream中的数据。将请求的内容以二进制的形式写入outputStream中。当服务器关闭后,scannerNetWork传入服务器的EOF信号,代表着双方连接中断,因此可以退出循环结束进程。
public void start() {System.out.println("客户端启动!");Scanner scanner = new Scanner(System.in);try(InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {Scanner scannerNetWork = new Scanner(inputStream);while (true) {System.out.println("输入要发送的数据");//1.读取数据String request = scanner.next();//2.将request作为请求发送到服务器中,通过\n标识请求内容request += "\n";outputStream.write(request.getBytes());//3.读取服务器返回的响应if (!scannerNetWork.hasNext()){break;}String response = scannerNetWork.next();System.out.println(response);}} catch (IOException e) {e.printStackTrace();}}
2.TCP多线程使用
在上面的TCP回显代码中,并不能使用于多线程的形势下。在服务器中,应当有线程池之类的多线程状态中,同时处理多个客户端发送过来的请求。
因此需要对服务器实现多线程解决问题。通过线程池的方式,while循环中不断接收客户端发来的连接请求,并将任务交予线程池解决。
public void start() throws IOException {System.out.println("服务器启动!");ExecutorService pool = Executors.newCachedThreadPool();//accept可以阻塞等待while (true) {Socket socketClient = serverSocket.accept();pool.submit(new Runnable() {@Overridepublic void run() {try{processConnection(socketClient);} catch (IOException e) {throw new RuntimeException(e);}}});}}
总结
在本文中主要讲解了TCP和UDP两个协议之间的区别;同时对UDP网络编程进行了最基础的创建。
源码☞本文源码
相关文章:

[网络编程】网络编程的基础使用
系列文章目录 1、 初识网络 网络编程套接字 系列文章目录前言一、TCP和UDP协议的引入二、UDP网络编程1.Java中的UDP2.UDP回显代码案例3.UDP网络编程的注意事项 三、TCP网络编程1.TCP回显代码案例2.TCP多线程使用 总结 前言 在学习完基础的网络知识后,完成跨主机通…...

Postman中的Cookie和会话管理:掌握API测试的关键环节
Postman中的Cookie和会话管理:掌握API测试的关键环节 在API测试过程中,正确处理Cookie和会话管理对于模拟用户登录、维持会话状态以及测试需要用户认证的API至关重要。Postman提供了多种功能来帮助测试人员管理Cookie和会话,确保测试的准确性…...

python脚本,识别pdf数据,转换成表格形式
可以使用Python库来识别PDF文件并将其转换为表格形式。下面是一个示例脚本,使用了tabula-py库来进行PDF数据提取和转换操作。 首先,安装tabula-py库。可以使用以下命令来安装: pip install tabula-py然后,使用以下代码来实现PDF…...

Linux环境安装KubeSphere容器云平台并实现远程访问Web UI 界面
文章目录 前言1. 部署KubeSphere2. 本地测试访问3. Linux 安装Cpolar4. 配置KubeSphere公网访问地址5. 公网远程访问KubeSphere6. 固定KubeSphere公网地址 前言 本文主要介绍如何在Linux CentOS搭建KubeSphere并结合Cpolar内网穿透工具,实现远程访问,根…...

jumpserver web资源--远程应用发布机
1、环境 jumpserver:3.10.10 远程发布机:windows 2019 2、windows 2019准备 保证windows 正常登录,并且可以访问jumpserver 3、添加远程发布机 能正常连接就继续 可看到这里正常了 4、添加web资源 找到我们需要自动登录界面 获取相关元素选…...

Linux环境docker部署Firefox结合内网穿透远程使用浏览器测试
文章目录 前言1. 部署Firefox2. 本地访问Firefox3. Linux安装Cpolar4. 配置Firefox公网地址5. 远程访问Firefox6. 固定Firefox公网地址7. 固定地址访问Firefox 前言 本次实践部署环境为本地Linux环境,使用Docker部署Firefox浏览器后,并结合cpolar内网穿…...

人工智能与机器学习原理精解【8】
文章目录 马尔科夫过程论基础理论函数系的定义、例子和分类一、函数系的定义二、函数系的例子三、函数系的分类 什么是测度定义性质种类应用总结 计算测度的公式1. 长度(一维测度)2. 面积(二维测度)3. 体积(三维测度&a…...

关于Protobuf 输入输出中文到文件中的一系列问题
一、不含中文的常规处理 //定义 message Value {repeated uint32 uiMain 1; repeated uint32 uiSub 2; }message Simulate {repeated Value data 1; }//文件 data {uiMainAds : 36598uiMainAds : 35675uiMainAds : 36756 uiSubAds : 16924uiSubAds : 16488uiSu…...

后端笔记(1)--javaweb简介
1.JavaWeb简介 *用Java技术来解决相关web互联网领域的技术栈 1.网页:展现数据 2.数据库:存储和管理数据 3.JavaWeb程序:逻辑处理 2.mysql 1.初始化Mysql mysqld --initialized-insecure2.注册Mysql服务 mysqld -install3.启动Mysql…...

便携式气象监测系统的优势:精准高效,随行监测
在快速变化的自然环境中,气象信息的准确获取与及时分析对于农业生产、环境保护、科学研究乃至日常生活都至关重要。随着科技的飞速发展,便携式气象监测系统以其独特的优势,正逐步成为气象监测领域的新宠,引领着气象监测技术的革新…...

uniapp App判断是否安装某个app
参考文档:HTML5 API Reference 项目中需要判断是否安装了uber,这里拿uber举例 ,判断是否安装uber if (plus.runtime.isApplicationExist({pname: com.ubercab.eats, //Android平台通过pname属性(包名)查询action: ub…...

C/C++大雪纷飞代码
目录 写在前面 C语言简介 EasyX简介 大雪纷飞 运行结果 写在后面 写在前面 本期博主给大家带来了C/C实现的大雪纷飞代码,一起来看看吧! 系列推荐 序号目录直达链接1爱心代码https://want595.blog.csdn.net/article/details/1363606842李峋同款跳…...

【linux】【设备树】具有 GPIO 控制器和连接器的硬件配置的备树(Device Tree)代码讲解
具有 GPIO 控制器和连接器的硬件配置的备树(Device Tree)代码讲解 背景 -学习Linux设备树 代码 soc {soc_gpio1: gpio-controller1 {#gpio-cells = <2>;};soc_gpio2: gpio-controller2 {#gpio-cells = <2>;}; };connector: connector {#gpio-cells = <2>…...

【2025留学】德国留学真的很难毕业吗?为什么大家不来德国留学?
大家好!我是德国Viviane,一句话讲自己的背景:本科211,硕士在德国读的电子信息工程。 之前网上一句热梗:“德国留学三年将是你人生五年中最难忘的七年。”确实,德国大学的宽进严出机制,延毕、休…...

Apache Solr 最常用的命令
目录 一、Solr 安装与配置 1.1 下载与安装 1.2 启动与停止 二、Core 和 Collection 管理 2.1 创建与删除 2.2 核心操作 三、索引管理 3.1 添加与删除文档 3.2 批量操作 3.3 提交与优化 四、查询与检索 4.1 基本查询 4.2 高级查询 五、Schema 管理 5.1 字段管理 …...

经济下行,企业还在“裁员至上”?
最近小红书、B站崩溃,又延伸到某云服务厂商问题频发,让人忍不住戏谑:“这算不算裁员裁到大动脉?” 在阿道看来,各大企业的裁员动作,绕不开的依旧是“人月神话”:盲目加人带来的是成本的倍增和效…...

学习笔记之Java篇(0729)
p 数组 大纲知识点数组的概念数组的定义、四个特点数组的常见操作普通遍历、for-each遍历、java.util.Array类用法多维数组多维数组的内存结构、存储表格、Javabean和数组存储表格常见算法冒泡排序基础算法、冒泡排序优化算法、二分法查找(折半查找) 1、…...

吃肉的刷题记录4-基础知识-字符串
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 leetcode.186.反转字符串中的单词 leetcode.186.反转字符串中的单词 https://leetcode.cn/problems/reverse-words-in-a-string-ii/ 给你一个字符数组 s …...

人工智能与机器学习原理精解【7】
文章目录 凸优化基础理论加权正规方程线性回归模型加权最小二乘法加权正规方程注意使用Diagonal函数使用diagm函数总结 加权最小二乘法加权最小二乘法的定义加权最小二乘法的算法加权最小二乘法的计算加权最小二乘法的原理一、基本思想二、原理详解三、总结 加权最小二乘法的例…...

ResNet学习笔记
《Deep Residual Learning for Image Recongition》:用于图像分类的深度残差学习。 ResNet(残差网络)是在2015年由微软研究院的Kaiming He等人提出的,旨在解决深度神经网络训练过程中的梯度消失、梯度爆炸问题,并允许…...

使用chainlit快速构建类似OPEN AI一样的对话网页
快速开始 创建一个文件,例如“chainlit_chat” mkdir chainlit_chat进入 chainlit_chat文件夹下,执行命令创建python 虚拟环境空间(需要提前安装好python sdk。 Chainlit 需要python>3.8。,具体操作,由于文章长度问题就不在叙述…...

【根据字符出现频率排序】python刷题记录
R2-字符串算法 包哈希表的呀。 注意 class Solution:def frequencySort(self, s: str) -> str:dictdefaultdict(list)#字符串不能直接排序,需要转换为列表["a","b","c"]slist(s)for str in s:if not dict[str]:dict[str]1else:…...

活动报名小程序
#活动报名工具# # 活动报名小程序 ## 项目简介 一款通用的活动报名工具,包含活动展示,微信支付,订单管理,分享评价等功能。 品客聚精彩,有你才精彩!不只有线下活动还可以进行线上裂变活动。 …...

unity基础问题
1.一个列表中的UI有放大效果,用什么实现? 缩放,Layout组件可以勾选使用子级缩放,这样缩放之后也能保持间距 2.UGUI事件传递机制的冒泡机制是怎样的 事件系统从内向外遍历UI层次结构,通知父级UI元素有关该事件的信息。类…...

RedHat Enterprise Linux 7 YUM源(本地/网络源)配置详解
目录 一、挂载 二、建立本地源 三、建立网络源 四、验证可行性 一、挂载 ——将光盘挂载到 /mnt 下 当/mnt中有如图内容时,即挂载成功 若挂载光驱/dev/sr0时报错:mount: no medium found on /dev/sr0 解决措施:查看该设备状态是否全部勾选…...

关于顺序表数组下标的一些关系梳理
...

VS C++ Project(项目)的工作目录设置
如果只是简单创建一个VS CProject或者MFC Project,可能很多时候,只关心将Project放在硬盘的那个位置,与Project目录相关的的其他问题,并不引人注意,我们也不是十分在意。有时我们不得不进行工作目录方面的设置…...

STM32自定义协议串口接收解析指令程序
1、在使用串口接收自定义协议指令时,需要串口解析收到的是什么指令,举例通信报文为 上位机->单片机 名称 长度 备注 帧头 1Byte 0x5A 0x5A 帧长度 1Byte 数据包的长度0x00-0xFF 数据包 命令字 1Byte 功能标识 数据 可以为空 校验 …...

STM32——GPIO(点亮LEDLED闪烁)
一、什么是GPIO? GPIO(通用输入输出接口): 1.GPIO 功能概述 GPIO 是通用输入/输出(General Purpose I/O)的简称,既能当输入口使用,又能当输出口使用。端口,就是元器件…...

VulnHub靶机入门篇--kioptrix.level 3
1.环境准备 靶机:Kioptrix Level 3(Nat模式) 下载地址:https://download.vulnhub.com/kioptrix/KVM3.rar 攻击机:kali(192.168.26.128)(Nat模式) 2.渗透测试 信息收…...