Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显
Socket 套接字(TCP和UDP),以及TCP的回显
- Socket 套接字
- 数据报套接字UDP
- TCP流套接字编程
- TCP的长短连接
- 实现一个简单回显服务器
Socket 套接字
我们软件工作者,着重编写的是应用层的代码,但是发送这个数据,我们就需要将应用层传输到传输层,也就意味着我们需要调用应用层的API,统称为 Socket API。
套接字的分类:
- 流套接字:使用传输层TCP协议
特点:- 有连接:使用 TCP 通信的双方,需要时刻保存对方的相关消息
- 可靠传输:尽可能的将数据传输过去,如果没有传输过去,自己也知道没有传输,然后通过设定可以重新传输
- 面向字节流:以字节为传输的基本单位,读写方式更为灵活
- 全双工:一条路径,双向通信
- 数据报套接字:使用传输层UDP协议
特点:- 有连接:使用 UDP 通信的双方,不需要时刻保存对方的相关消息
- 不可靠传输:只关注是否传输了数据,至于是否传输成功,并不专注
- 面向数据报:以一个UDP数据报为基本单位
- 全双工:一条路径,双向通信
- 原始套接字:原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据。
所有特点自己定义
什么是全双工和半双工?
全双工:一条路径,双向通信
半双工:一条路径,单向通信
网络传输数据的基本单位:报(Datagram)、包(Packet)、段(Segment)、帧(Frame)
Socket 对象,相当于系统中Socket文件,这个文件并非对应到硬盘上的某个数据存储区域,而是对应到网卡这个硬件设备
- 往这个Socket·对象中写数据,相当于通过网卡发送消息
- 从这个Socket·对象中读数据,相当于通过网卡接收消息
这个图不是我画,摘抄了网上现有的)

数据报套接字UDP
java中使用UDP协议通信,主要基于 DatagramSocket 类来创建数据报套接字,并使用DatagramPacket 作为发送或接收的UDP数据报 。DatagramSocket 是UDP Socket,用于发送和接收UDP数据报。
DatagramSocket API:
- DatagramSocket 构造方法

- DatagramSocket 方法:

DatagramPacket API:(DatagramPacket是UDP Socket发送和接收的数据报)
-
DatagramPacket 构造方法:

-
DatagramPacket 方法:

构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用 InetSocketAddress 来创
建
InetSocketAddress API:
- InetSocketAddress ( SocketAddress 的子类 )构造方法:

UDP服务器:
注意:
- 服务器的端口必须不变,客户端这边则不需要手动指定,系统自动分配
- socket是文件,也需要关闭
public class UdpServer { //服务器socket要绑定固定的端口 private static final int PORT = 8888; public static void main(String[] args) throws IOException { // 1.创建服务端DatagramSocket,指定端口,可以发送及接收UDP数据报 DatagramSocket socket = new DatagramSocket(PORT); //不停的接收客户端udp数据报 while (true){ // 2.创建数据报,用于接收客户端发送的数据 byte[] bytes = new byte[1024];//1m=1024kb, 1kb=1024byte, UDP最多64k(包含UDP首部8byte) DatagramPacket packet = new DatagramPacket(bytes, bytes.length); System.out.println("---------------------------------------------------"); System.out.println("等待接收UDP数据报..."); // 3.等待接收客户端发送的UDP数据报,该方法在接收到数据报之前会一直阻塞,接收到数据报以后,DatagramPacket对象,包含数据(bytes)和客户端ip、端口号 socket.receive(packet); System.out.printf("客户端IP:%s%n", packet.getAddress().getHostAddress()); System.out.printf("客户端端口号:%s%n", packet.getPort()); System.out.printf("客户端发送的原生数据为:%s%n", Arrays.toString(packet.getData())); System.out.printf("客户端发送的文本数据为:%s%n", new String(packet.getData())); } }
}
一旦服务器一起动,调用start方法,就会立即执行到,receive这里,但是如果此时还有没有客户端发来的数据,receive就会阻塞等待,一直持续到有数据发过来。
细节:网卡这里收到数据,就会进行分用,解析UDP这一层 看到端口号,然后将数据放入接收缓冲区,然后将数据到了参数中的DatagramSocket 对象中
UDP客户端:
public class UdpClient { // 服务端socket地址,包含域名或IP,及端口号 private static final SocketAddress ADDRESS = new InetSocketAddress("localhost", 8888); public static void main(String[] args) throws IOException { // 4.创建客户端DatagramSocket,开启随机端口就行,可以发送及接收UDP数据报 DatagramSocket socket = new DatagramSocket(); // 5-1.准备要发送的数据 byte[] bytes = "hello world!".getBytes(); // 5-2.组装要发送的UDP数据报,包含数据,及发送的服务端信息(服务器IP+端口号) DatagramPacket packet = new DatagramPacket(bytes, bytes.length, ADDRESS); // 6.发送UDP数据报 socket.send(packet); }
}

TCP流套接字编程
ServerSocket API:
ServerSocket 是创建TCP服务端Socket的API。
- ServerSocket 构造方法:

- ServerSocket 方法:

accept:意思就是接受,本质上是三次握手后面的文章会说。
Socket API:
Socket 是客户端 Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。
不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。
- Socket 构造方法:

- host 表示服务器的 IP 地址
- port 表示服务器的端口
- Socket 方法:

- 从InputStream这里读数据,就相当于从网卡接收
- 往OutputStream这里写数据,就相当于从网卡发送
TCP的长短连接
TCP发送数据时,需要先建立连接,而什么时候关闭连接就决定是短连接还是长连接。
短连接:每次接收数据并返回响应后,都关闭连接。也就是说,短连接只能一次收发。
- 连接客户端和服务器
- 对于客户端来说。要发送一个请求,然后接收一个响应
- 对于服务器来说。会收到一个请求,然后返回一个响应
- 然后关闭连接
长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接。也就是说,长连接可以
多次收发数据
- 连接客户端和服务器
- 可以客户端一直发送请求,并获取服务器的响应
- 可以服务器一直发送请求,并获取客户端的响应
- 没有一方主动停止,不关闭
长连接和短连接的区别:
- 建立连接、关闭连接的耗时:短连接每次请求、响应都需要建立连接,关闭连接;而长连接只需要第一次建立连接,之后的请求、响应都可以直接传输。相对来说建立连接,关闭连接也是要耗时的,长连接效率更高。
- 主动发送请求不同:短连接一般是客户端主动向服务端发送请求;而长连接可以是客户端主动发送请求,也可以是服务端主动发。
- 两者的使用场景有不同:短连接适用于客户端请求频率不高的场景,如浏览网页等。长连接适用于客户端与服务端通信频繁的场景,如聊天室,实时游戏等。
实现一个简单回显服务器
public class TcpEchoServer {//serverSocket 就是外场拉客的小哥(类似集合),只有一个//clientSocket 内场服务的人(),会给每个客服分配一个private ServerSocket serverSocket=null;//1public TcpEchoServer(int port) throws IOException {serverSocket=new ServerSocket(port);}public void start() throws IOException {ExecutorService executorService= Executors.newCachedThreadPool();System.out.println("服务器启动");while (true){Socket clientSocket=serverSocket.accept();//如果直接调用,该方法会影响这个循环的二次执行.导致accept不及时了//创建新的线程,用新的线程来调用processConnetion//每次来一个新的客户端都搞一个新的线程即可
/* Thread t=new Thread(()->{try {processConnection(clientSocket);} catch (IOException e) {throw new RuntimeException(e);}});t.start();*///创建一个线程池,从池子中拿取线程executorService.submit(new Runnable() {@Overridepublic void run() {try {processConnection(clientSocket);} catch (IOException e) {throw new RuntimeException(e);}}});}}//通过这个方法处理一个链接//读取请求//根据请求计算响应//把响应返回给客户端private void processConnection(Socket clientSocket) throws IOException {System.out.printf("[%s:%d] 客户端上线!\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());try(InputStream inputStream=clientSocket.getInputStream();OutputStream outputStream=clientSocket.getOutputStream()) {//没有这两个也可以,但是代价就是得一个字节一个字节的处理,找到那个是结束符//将字节流包装成了字符流Scanner scanner=new Scanner(inputStream);PrintWriter printWriter=new PrintWriter(outputStream);while (true){//3//读取请求if (!scanner.hasNext()){//读取的流到了结尾了System.out.printf("[%s:%d] 客户端下线",clientSocket.getInetAddress().toString(),clientSocket.getPort());break;}//直接使用scanner读取一段字符串String request=scanner.next();//往后读,一直读到空白符,空格,换行,翻页符....都算空白符//5//根据请求计算响应String response=process(request);//把响应返回给客户端printWriter.println(response);//刷新缓冲区printWriter.flush();System.out.printf("[%s:%d] req:%s; resp:%s\n",clientSocket.getInetAddress().toString(),clientSocket.getPort(),request,response);}} catch (IOException e) {throw new RuntimeException(e);}finally {clientSocket.close();}}private String process(String request) {return request;}public static void main(String[] args) throws IOException {TcpEchoServer tcpEchoServer=new TcpEchoServer(9090);tcpEchoServer.start();}}

补充一点:
硬件的读写速度:
- 内存 > 硬盘 > 网卡
读写硬盘和网卡口可以视为 IO 操作。
- printWriter.println(response);----》写网卡
因为网卡读写速度慢,如果平凡的写入,读出对于效率太慢了。为了提高IO操作的效率,此时就需要引入一个内存构成的缓冲区。等缓冲区达到一定数量,就统一写入网卡中。
缓存(cache)!=缓冲区(buffer)
- 缓存:只能读
- 缓冲区:可以读也可以写。
相关文章:
Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显
Socket 套接字(TCP和UDP),以及TCP的回显 Socket 套接字数据报套接字UDPTCP流套接字编程TCP的长短连接实现一个简单回显服务器 Socket 套接字 我们软件工作者,着重编写的是应用层的代码,但是发送这个数据,我…...
C++ - 多态语法 - 虚函数使用介绍
多态简单介绍 多态就是多种形态,是不同的对象去完成同一个动作所产生的结果可能有多种。这种多种的形态我们称之为多态。 比如:我们在买票的时候的时候,可能有成人全价,儿童半价,军人免票等等。对于成人,儿…...
php获取客户端ip地址及ip所在国家、省份、城市、县区
摘要 获取客户端ip地址,然后使用这个ip地址获取所在的国家、省份、城市,可以在网站中实现IP属地,发布地等功能。 本文的获取IP地址信息均采自网络上免费的IP查询网站,通过其API或者网页HTML解析出的ip地址信息。 代码 <?p…...
Error: Port Library failed to initialize: -86
最近遇到一个很奇怪的错误,这里记录一下,以备以后再次遇到 Error: Port Library failed to initialize: -86 Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit.背景是,就是一普…...
SOME/IP 支持两种序列化方式:TLV 和 TV
SOME/IP 是一种基于 IP 的可扩展面向服务的中间件协议,它可以在车载以太网中实现 ECU 之间的高效通信和互操作性。 SOME/IP 的序列化方式是指将数据结构或对象按照一定的规则转换成字节序列的过程,以便在网络中传输和解析。 SOME/IP 支持两种序列化方式:TLV 和 TV。 TLV是…...
Unity之3D物理导航系统
一 介绍 Unity自带寻路(导航)系统是unity官方自带的一种寻路系统。我们可以通过它来制作简单的寻路,比如可以制作点击某个位置,让角色自动的绕开障碍走到目标点的效果,比如可以制作敌人AI,让它可以通过NavMesh绕开障碍追击我方单…...
9.4黄金行情是否反转?今日多空如何布局?
近期有哪些消息面影响黄金走势?今日黄金多空该如何研判? 黄金消息面解析:周一(9月4日)亚市盘中,现货黄金震荡走高,延续上周涨势,一度刷新日内高点至1946.16美元/盎司。周三,ISM将发布服务业P…...
Win10下使用vim9
作为一个经常与文字打交道的Writer,你在学会Vim的基本操作之后,就一定会爱上Vim的。 以下是Windows10_64位(专业版)环境中安装、使用Vim9的全过程,分享一下: 一、下载、安装Vim9 去Vim官网去下载最新的Vi…...
Flink+Flink CDC版本升级的依赖问题总结
之前使用Flink1.13Flink CDC2.0同步MySQL数据,想测试一下最新的几个版本。但是各种依赖冲突的报错,经过一段时间的调试,终于解决,现在总结一下。 1、flink1.15前后jar包名称不一样 flink-streaming-java、flink-clients、flink-…...
Matlab论文插图绘制模板第112期—带阴影标记的图
之前的文章中,分享了Matlab带线标记的图: 进一步,本期分享的是带阴影标记的图。 先来看一下成品效果: 特别提示:本期内容『数据代码』已上传资源群中,加群的朋友请自行下载。有需要的朋友可以关注同名公号…...
专业运动耳机哪个牌子好、专业运动耳机推荐
在进行运动时,倾听音乐实际上是一种放松大脑、放松身体的小技巧。毕竟运动是一个耗费体力最多的活动,整个过程也往往令人感到乏味。如果有音乐作伴,你的运动就会变得更加轻松愉快。那么,哪种耳机适合运动呢?我正好对此…...
【SQL应知应会】索引 • Oracle版:B-树索引;位图索引;函数索引;单列与复合索引;分区索引
欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流 本文免费学习,自发文起3天后,会收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习,有基础也有进阶,有MySQL也有Oracle 索引 • MySQL版 前言一、Oracle索引1.索引概述及分类…...
用ChatGPT做一个Chrome扩展 | 京东云技术团队
用ChatGPT做了个Chrome Extension 最近科技圈儿最火的话题莫过于ChatGPT了。 最近又发布了GPT-4,发布会上的Demo着实吸睛。 笔记本上手画个网页原型,直接生成网页。网友直呼:前端失业了! 但我觉着啊,真就外行看热闹…...
动态库的制作与使用及 动态库加载失败解决
加载动态库时有时会出现error while loading shared libraries:libcalc.so:可以通过lld命令查看动态库的依赖关系,发现libcalc.so时not found 原因 查找的优先级是DT_RPATH->LD_LIBRARY_PATH->/etc/ld.so.cache->/lib/,/usr/lib 找不到一个优…...
404 not found nginx(dist打包后,刷新和跳转都是404 not found nginx的问题) 解决方案(打包发布在服务器)
当我们执行了yarn run build之后,生成dist文件 我们将代码放入nginx-1.24.0下面的html中 然后我们就配置conf文件下的nginx.conf 配置方面不介绍了,主要问题是因为没有加这句话 问题分析 index index.htm index.html; index 就是根目录,也就…...
《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》全文翻译
《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》- Chain-of-Thought Prompting Elicits Reasoning in Large Language Models 论文信息摘要1. 介绍2. 思维链提示3. 算术推理3.1 实验设置3.2 结果3.3 消融研究3.4 思想链的稳健性 4. 常识推理5. 符号…...
MySQL——笔试测试题
解析: 要查询各科目的最大分数,可以使用如下的SQL语句: SELECT coursename, MAX(score) FROM t_stuscore GROUP BY coursename; 这条SQL语句使用了MAX()聚合函数来获取每个科目的最大分数,并使用GROUP BY子句按照科目进行分组…...
WangEditor在Vue前端的应用
1、在Vue项目中安装WangEditor 对于Vue2: npm install wangeditor/editor-for-vue --save 或者 yarn add wangeditor/editor-for-vue 对于Vue3: npm install wangeditor/editor-for-vuenext --save 或者 yarn add wangeditor/editor-for-vuenext 2、将Wa…...
初学python的感受
目录 初学感受学习计划学习目标 初学感受 刚学python的我惊讶的发现编程语言之间竟有如此多的相似之处,因此在学python的时候相对于学C语言时要轻松的多,虽然二者也有一些不同之处,但是我想只要对二者稍微区分的话应该不会搞混的,并且在学习的过程中也可以借鉴学C语言的方法去…...
SpringSecurity中注解讲解
文章目录 1 EnableGlobalMethodSecurity1.1 PreAuthorize1.1.1 开启注解1.1.2 使用注解原生方法1.1.3 使用注解自定义方法 1.2 PostAuthorize1.3 Secured 2 其他注解2.1 PostFilter2.2 PreFilter 3 权限表达式 1 EnableGlobalMethodSecurity EnableGlobalMethodSecurity 是 Sp…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
macOS 终端智能代理检测
🧠 终端智能代理检测:自动判断是否需要设置代理访问 GitHub 在开发中,使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新,例如: fatal: unable to access https://github.com/ohmyzsh/oh…...
深入解析 ReentrantLock:原理、公平锁与非公平锁的较量
ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...
vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能
vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能 查看官网:https://vxetable.cn 效果 代码 通过 checkbox-config.isShift 启用批量选中,启用后按住快捷键和鼠标批量选取 <template><div><vxe-grid v-bind"gri…...
篇章一 论坛系统——前置知识
目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...
ABB馈线保护 REJ601 BD446NN1XG
配电网基本量程数字继电器 REJ601是一种专用馈线保护继电器,用于保护一次和二次配电网络中的公用事业和工业电力系统。该继电器在一个单元中提供了保护和监控功能的优化组合,具有同类产品中最佳的性能和可用性。 REJ601是一种专用馈线保护继电器…...
