当前位置: 首页 > news >正文

Socket本质、实战演示两个进程建立TCP连接通信的过程

文章目录

    • Socket是什么
      • 引入面试题, 使你更深刻的理解四元组
    • Socket网络通信大体流程
    • 实战演示TCP连接建立过程
      • 需要用到的linux 查看网络的一些命令
      • 测试的程序
      • 一些准备工作
      • 启动服务端, 并没有调用accept
      • 启动客户端
      • 开启服务accept

Socket是什么

通俗来说,Socket是套接字,是一种编程接口,类似于电话插口,通过Socket可以进行网络通信, 但是这种很不容易让人理解.

其实本质来说Socket就是四原组,包括 客户端ip: 客户端端口 + 服务端ip: 服务端端口, 其实就是一个对应关系, 通过这个四原组就可以唯一的确定一个数据包来自哪里,要发送到哪里.
从而可以使得不同服务器上的不同进程进行网络通信, 而数据不会乱掉, 这就是Socket.

Socket是TCP协议层的, 是内核级别的, 这个怎么理解?
在我们使用Socket编程时,服务需要执行accept()方法进行监听, 但是即使我们不执行这个方法, 也会进行三次握手,直接建立tcp连接, 内核会直接帮我们做这件事情, 这个后面有程序验证.
在这里插入图片描述

引入面试题, 使你更深刻的理解四元组

现在有一个客户端,IP地址用AIP代替, 还有一个服务端, IP地址是CIP
而通信其实是两个进程间的通信,我们知道服务端进程在启动的时候需要绑定监听一个端口, 比如是XPORT.
而客户端在发起建立连接的时候其实也会随机起一个端口, 比如是BPORT, 那双方建立连接的时候就会有一个四元组. 这个对应关系既在客户端存在,也在服务端存在
在这里插入图片描述

  • 问题一: 服务端在建立连接后是否需要为客户端随机分配一个端口
    不需要的, 因为当建立连接后, 不论是客户端还是服务端, 内核都会为这个连接分配资源, 在资源中都存储了这个对应关系(四元组), 所以不论是对于客户端还是服务端, 只要这个对应关系有, 这个对应关系是一个唯一标识, 就没有必要再分配一个端口号了.双方就可以进行通信.

  • 问题二: 同一个客户端, 能不能启多个不同的进程去连接同一个服务端的某一个进程
    是可以的, 比如客户端启了三个进程,占用的端口分别是BPORT,CPORT,DPORT, 那其实就会形成三个不同的四原组. 这三个都是唯一的, 自然不会影响.在这里插入图片描述

  • 问题三: 一个服务端的某个进程, 连接了很多不同的客户端, 那是怎么区分每个数据包是来自哪个客户端呢
    其实在每个数据包中, 都会有这个对应关系, 也就是这个四元组, 这样就很容器区分了

  • 问题四:默认linux机器能使用的端口是65535个, 那假如一个客户端起了很多的进程, 连接的都是同一个服务器的80端口, 把65535个端口都用了, 那现在这个客户端能不能再使用端口去连接相同服务器的其他端口 或者 不同服务器的其他端口
    都是可以的, 因为客户端可以重复使用这些端口, 只要生成的四元组是唯一的, 比如以下, 某个客户端的B,C,D端口已经连接了某个服务端的X端口, 现在又用客户端的B,C,D端口连接了服务端的Y端口, 这六组对应关系都是唯一的, 就能够确定数据来源哪, 发送到哪, 那自然是没问题的
    在这里插入图片描述

  • 问题五: 那客户端可以使用相同的端口,但是服务端一个进程已经用了80端口, 再起一个程序去占用80端口就会报异常, 这是为什么呢
    因为服务端是ServerSocket, ServerSocket还有些特殊, 需要先开启监听Listen, 开启监听后等待客户端的连接,
    那假如服务端有两个程序A,B都使用了80端口开启监听等待连接, 此时有个客户端想要和A程序通信, 发起三次握手中第一次连接请求, 直接发给了80端口, 此时能分清是要和哪个程序建立连接吗? 此时是分不清的.

  • 再举个生活中的通俗例子, 你有一个电话号码, 可以用这个电话号码打给市场监督管理局, 这个市场监督管理局的电话一定是唯一的, 不然你就会分不清, 但是你可以用同样的电话号码打给住建局, 那你其实就是客户端, 可以用相同的号码, 而公家单位市场监管局,住建键局这些,他们是服务端, 电话号码都是唯一的, 不能使用相同的.

Socket网络通信大体流程

接下来大致理一下不同机器上两个应用程序通过Socket通信流程

  1. 服务端开启监听, 在内核中生成一个LISTEN并绑定端口
  2. 客户端开启连接后, 两个机器内核开始进行三次握手, 建立连接
  3. 建立连接之后会给其分配资源, 比如说分配buffer, 未来我们读写数据就是和这个buffer交互
    还会在内核中保存这个四元祖, 也就是这个映射关系
  4. 为对应程序分配TCP文件描述符 , 将来应用程序就可以通过这个文件描述符找到对应的四元组, 从而找到buffer,进行数据的读写.
    在这里插入图片描述

实战演示TCP连接建立过程

需要用到的linux 查看网络的一些命令

lsof -p 进程id  --------- 查看某个进程的文件描述符,包括tcp这些
netstat -natp -------  可以查看一个tcp连接建立的过程
tcpdump ------   可以对tcp连接进行抓包

测试的程序

客户端 -> ServerClientTest

public class ServerClientTest {public static void main(String[] args) {try {Socket client = new Socket("192.168.68.2", 9090);client.setTcpNoDelay(true);client.setSendBufferSize(20);OutputStream outputStream = client.getOutputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));while(true){String line = reader.readLine();if(line != null){byte[] bytes = line.getBytes();for (byte b : bytes) {outputStream.write(b);  //注意这里面没有调用flush}}}} catch (IOException e) {e.printStackTrace();}}}

服务端 -> ServerSocketTest

public class ServerSocketTest {public static void main(String[] args) {ServerSocket server = null;try {server = new ServerSocket();server.bind(new InetSocketAddress(9090));} catch (IOException e) {e.printStackTrace();}System.out.println("server up use 9090");while(true){try {//阻塞,暂时不执行accept,分水岭System.in.read();//真正开启监听Socket client = server.accept();System.out.println("client port: "+client.getPort());new Thread(() -> {while(true){try {InputStream in = client.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(in));char[] data = new char[1024];int num = reader.read(data);if(num>0){System.out.println("client read some data :"+new String(data));}else if(num==0){System.out.println("client read data nothing......");}else{System.out.println("client read data error......");}} catch (IOException e) {e.printStackTrace();}}}).start();} catch (IOException e) {e.printStackTrace();}finally {try {server.close();} catch (IOException e) {e.printStackTrace();}}}}
}

需要注意,在 服务端启动程序后,如果不进行任何输入, 程序会阻塞在这里, 不会调用accept()方法

在这里插入图片描述

一些准备工作

对9090这个端口进行抓包
在这里插入图片描述
查看当前机器的所有的TCP连接,并没有9090端口的
在这里插入图片描述

启动服务端, 并没有调用accept

在这里插入图片描述
启动服务端,但是还没有调用accept, 内核会主动注册一个LISTEN,绑定端口号
有了这个LISTEN之后, 客户端就可以连进来了
在这里插入图片描述
同时使用jps 命令查看刚刚启动的服务端的进程id是3907
使用lsof -p 3907, 看看这个进程的文件描述符情况,可以看到有一个监听状态的文件描述符
在这里插入图片描述

启动客户端

在这里插入图片描述

注意此时,服务端还没有调用accept方法,启动服务端后没有做任何操作, 还阻塞在这行代码
在这里插入图片描述

使用tcpdump查看抓包, 发现已经经过三次握手
在这里插入图片描述
使用netstat查看所有的TCP以及连接状态, 发现9090端口已经和一个客户端建立了连接, 但是这个Socket还没有分配给任何程序去使用
但是内核里面已经有它了
在这里插入图片描述

开启服务accept

这里随便输入了一个回车, 跳过了 System.in.read(); 这行代码
在这里插入图片描述
程序里面真正有了一个tcp的文件描述符
在这里插入图片描述
内核中的socket也真正分配给了对应程序去使用

在这里插入图片描述
至此, 两个进程建立TCP连接通信的过程已经完毕.

到这里, 你应该真正能明白Socket最主要就是四元组, 明白Socket是TCP协议层的, 是内核级别的.

今天的分享就到这里了,有问题可以在评论区留言,均会及时回复呀.
我是bling,未来不会太差,只要我们不要太懒就行, 咱们下期见.
在这里插入图片描述

相关文章:

Socket本质、实战演示两个进程建立TCP连接通信的过程

文章目录 Socket是什么引入面试题, 使你更深刻的理解四元组 Socket网络通信大体流程实战演示TCP连接建立过程需要用到的linux 查看网络的一些命令测试的程序一些准备工作启动服务端, 并没有调用accept启动客户端开启服务accept Socket是什么 通俗来说,Socket是套接字,是一种编…...

java学习路程之篇四、进阶知识、石头迷阵游戏、绘制界面、打乱石头方块、移动业务、游戏判定胜利、统计步数、重新游戏

文章目录 1、绘制界面2、打乱石头方块3、移动业务4、游戏判定胜利5、统计步数6、重新游戏7、完整代码 1、绘制界面 2、打乱石头方块 3、移动业务 4、游戏判定胜利 5、统计步数 6、重新游戏 7、完整代码 java之石头迷阵单击游戏、继承、接口、窗体、事件、组件、按钮、图片...

Git全栈体系(三)

第六章 GitHub 操作 一、创建远程仓库 二、远程仓库操作 命令名称作用git remote -v查看当前所有远程地址别名git remote add 别名 远程地址起别名git push 别名 分支推送本地分支上的内容到远程仓库git clone 远程地址将远程仓库的内容克隆到本地git pull 远程库地址别名 远…...

JMeter发送get请求并分析返回结果

在实际工作的过程中,我们通常需要模拟接口,来进行接口测试,我们可以通过JMeter、postman等多种工具来进行接口测试,但是工具的如何使用对于我们来说并不是最重要的部分,最重要的是设计接口测试用例的思路与分析结果的能…...

HTML笔记(1)

介绍 浏览器中内置了HTML的解析引擎,通过解析标记语言来展现网页;HTML标签都是预定义好的;Java工程师:后台代码的编写,和数据库打交道,把数据给网页前端的工程师;网页前端工程师:写H…...

重新审视MHA与Transformer

本文将基于PyTorch源码重新审视MultiheadAttention与Transformer。事实上,早在一年前博主就已经分别介绍了两者:各种注意力机制的PyTorch实现、从零开始手写一个Transformer,但当时的实现大部分是基于d2l教程的,这次将基于PyTorch…...

Docker 全栈体系(七)

Docker 体系(高级篇) 五、Docker-compose容器编排 1. 是什么 Compose 是 Docker 公司推出的一个工具软件,可以管理多个 Docker 容器组成一个应用。你需要定义一个 YAML 格式的配置文件docker-compose.yml,写好多个容器之间的调…...

【编程范式】聊聊什么是数据类型和范式的本质

什么是编程范式 范式其实就是做事的方式,编程范式可以理解为如何编程,按照什么样的模式或者风格进行编程。 编程范式包含哪些 泛型编程函数式编程面向对象编程编程本质和逻辑编程 虽然有不同的编程范式,但是对于目的来说都是为了解决同一…...

2023-08-01 python根据x轴、y轴坐标(数组)在坐标轴里画出曲线图,python 会调用鼎鼎大名的matlib,用来分析dac 数据

一、python 源码如下 import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt#x[0 ,1,2,3,5,6,10] #y[0,0,3,4,5,7,8]# { 0 , 1 , 0x0003 },// 0 # { 0XFFFF * 1 / 10 , 3006 , 0x0a6b },// 1 # { 0XFFFF * 2 / 10 , 599…...

小研究 - 主动式微服务细粒度弹性缩放算法研究(四)

微服务架构已成为云数据中心的基本服务架构。但目前关于微服务系统弹性缩放的研究大多是基于服务或实例级别的水平缩放,忽略了能够充分利用单台服务器资源的细粒度垂直缩放,从而导致资源浪费。为此,本文设计了主动式微服务细粒度弹性缩放算法…...

机器学习深度学习——softmax回归的简洁实现

👨‍🎓作者简介:一位即将上大四,正专攻机器学习的保研er 🌌上期文章:机器学习&&深度学习——softmax回归从零开始实现 📚订阅专栏:机器学习&&深度学习 希望文章对你…...

CPU利用率过高解决思路

文章目录 问题场景问题定位问题解决 本文参考: Linux服务器之CPU过高解决思路_linux cpu温度过高_Jeremy_Lee123的博客-CSDN博客 Java程序员必备:jstack命令解析 - 掘金 (juejin.cn) 重点问题!CPU利用率过高排查思路|原创 (qq.…...

Redis(三)—— Redis基本的事务操作、Redis实现乐观锁

一、Redis基本的事务操作 首先声明: redis的单条命令是保证原子性的(回想一下setnx k1 v1 k5 v5命令如果k1已经存在,那么k5也会设置失败)但是redis的事务不保证原子性!见下面“1.2 某条命令有错怎么办?”…...

SQLI_LABS攻击

目录 Less1 首先来爆字段 联合注入 判断注入点 爆数据库名 爆破表名 information_schema information_schmea.tables group_concat() 爆破列名 information_schema.columns 爆值 SQLMAP Less-2 -4 Less -5 布尔 数据库 表名 字段名 爆破值 SQLMAP Less-6 …...

如何查看 Chrome 网站有没有前端 JavaScript 报错?

您可以按照以下步骤在Chrome中查看网站是否存在前端JavaScript报错: 步骤1:打开Chrome浏览器并访问网站 首先,打开Chrome浏览器并访问您想要检查JavaScript报错的网站。 步骤2:打开开发者工具 在Chrome浏览器中,按…...

JS前端读取本地上传的File文件对象内容(包括Base64、text、JSON、Blob、ArrayBuffer等类型文件)

读取base64图片File file2Base64Image(file, cb) {const reader new FileReader();reader.readAsDataURL(file);reader.onload function (e) {cb && cb(e.target.result);//即为base64结果}; }, 读取text、JSON文件File readText(file, { onloadend } {}) {const re…...

【项目方案】OpenAI流式请求实现方案

文章目录 实现目的效果比对非stream模式stream模式实现方案方案思路总体描述前端方案对比event-source-polyfill代码示例前端实现遇到的问题与解决方法后端参考资料时序图关键代码示例后端实现时遇到的问题与解决方法实现目的 stream是OpenAI API中的一个参数,用于控制请求的…...

华为数通HCIP-IP组播基础

点到点业务:比如FTP,WEB业务,此类业务主要特点是不同的用户有不同的需求,比如用户A需要下载资料A,用户B需要下载资料B。此类业务一般由单播承载,服务器对于不同用户发送不同的点到点数据流。 ospf、isis…...

STM32 SPI学习

SPI 串行外设设备接口(Serial Peripheral Interface),是一种高速的,全双工,同步的通信总线。 SCK时钟信号由主机发出。 SPI接口主要应用在存储芯片。 SPI相关引脚:MOSI(输出数据线&#xff…...

分布式缓存与数据库的一致性记录

用户更新数据库,需要再去更新redis缓存,否则会造成缓存与数据库数据不一致 一致性的两种方法 1). 双写模式 更新完数据库之后,更新redis缓存数据 问题: 因为请求时间的问题,造成缓存数据不是最新的 数据。 原因:A先修…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…...