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,未来不会太差,只要我们不要太懒就行, 咱们下期见.
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/18949.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

InnoDB引擎底层逻辑讲解——架构之磁盘架构

1. System Tablespaces区域 系统表空间是change buffer(更改缓冲区)的存放区域,这是在8.0之后重新规划的,在5.x版本的时候,系统表空间还会存放innodb的数据字典undolog日志等信息,在8.0之后主要主要存放更…

Gitlab CI/CD笔记-第一天-GitOps和以前的和jenkins的集成的区别

一、GitOps-CI/CD的流程图 简单解释: 1.提交代码 2.编译构建 3.测试 4.部署 二、gitlab的实现 1、Runer 1.这个就是jenkins里的worker-slave的角色, 2.git-lab server 下发任务,Runner执行。 3.这个R…

关于样本方差为什么除以 n-1

今天上午集训摸鱼看到同学给我发的这个问题感觉挺有意思的 感性理解 这一部分的内容仅代表本蒟蒻没看严谨证明之前的个人见解,如果您想看严谨的证明,请翻到下一部分 还是先把图放上来罢省的有人不知道讲的什么东西 呃我知道这是生物竞赛的东西&#…

下载列表视频的具体操作

主要是介绍怎样获取上篇博客需要的HAR文件和请求域名

docker: Error response from daemon: No command specified.

执行 docker run -it -d -v /home/dell/workspace/workspace/test_192.168.1.202_pipeline:/home/workspace1 --name test_192.168.1.202_pipeline_10 qnx:7.1报错 问题定位:export导入的镜像需要带上command,以下命令查看command信息 docker ps --no…

十进制、八进制、二进制、十六进制

十进制 每一位都有 0~9 十个数码,逢十进一 二进制 每一位仅有 0 和 1 两个数码,逢二进一 八进制 每一位都有 0~7 八个数码,逢八进一 十六进制 每一位都有 0~9、A(10)、B(11)、C(12)、D(13)、E(14)、F(15),十六个数码&#…

牛客网Verilog刷题——VL53

牛客网Verilog刷题——VL53 题目答案 题目 设计一个单端口RAM,它有: 写接口,读接口,地址接口,时钟接口和复位;存储宽度是4位,深度128。注意rst为低电平复位。模块的接口示意图如下。 输入输出描…

【A200】Ubuntu18.04 + ROS-Melodic + 比业电子VISIOSCAN雷达 评测

大家好,我是虎哥,朋友介绍,有一款单线激光雷达,25米的检测距离,有80HZ的扫描频率,而且角度分辨率最高可以到0.1,这个参数我确实没有见过,所以立刻着手从厂家那申请到了VISIOSCAN雷达…

JVM基础篇-虚拟机栈

JVM基础篇-虚拟机栈 定义 Java Virtual Machine Stacks (Java 虚拟机栈) 每个线程运行时所需要的内存,称为虚拟机栈每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存每个线程只能有一个活动…

机房断网断电监测网关支持远程告警

RTU5028E网络故障监测终端是一款功能强大且方便实用的设备,集合了断网、断电、网线故障报警功能。它支持同时监测多达7台网络设备,可以帮助用户快速定位远程网络设备离线的原因。此外,它还具备自动重启和远程重启网络设备的功能,为…

思科模拟器配置静态路由(下一跳使用IP)

Router0配置代码:##端口配置 Router(config)#int fastEthernet 0/0 Router(config-if)#ip address 192.168.10.254 255.255.255.0 Router(config-if)#no shutdown Router(config-if)#int fastEthernet 0/1 Router(config-if)#ip address 192.168.20.1 255.255.255.2…

深度剖析数据在内存中的存储

目录 数据类型介绍 类型的基本归类 整形家族: 浮点数家族: 构造类型: 指针类型 空类型: 整形在内存中的存储 原码、反码、补码 大小端介绍 什么大端小端: 为什么有大端和小端: 练习 浮点型在内存中的储存 一个例子 浮点数存储规则 数据类型介绍 前面我们…

Windows同时安装两个版本的JDK并随时切换,以JDK6和JDK8为例,并解决相关存在的问题(亲测有效)

Windows同时安装两个版本的JDK并随时切换,以JDK6和JDK8为例,并解决相关存在的问题(亲测有效) 1.下载不同版本JDK 这里给出JDK6和JDK的百度网盘地址,具体安装过程,傻瓜式安装即可。 链接:http…

【Linux】用户相关内容

如果命令ll 出现以上信息,UID为具体的数字,代表之前UID为502的用户被删除了。 更改目录或文件所属用户和所属组 在Linux中,创建一个文件时,该文件的拥有者都是创建该文件的用户。 更改所属用户 chown 用户名 文件名/目录名 更…

VisualStudioWindows下 远程调试

前置条件 1、调试方与被调试方,以下简称调试方为A,被调试方为B。A与B双方能相互ping通 2、B需要运行RemoteDebugger服务,该程序位于C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\Remote Debugger下。 我这里是安装…

基于总线加锁和缓存锁(CPU实现原子操作的两种方式)

总线锁 总线锁就是使用处理器提供的一个 LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住,那么该处理器可以独占共享内存。 CPU和内存之间的通信被锁!! 如果多个 处 理器同 时对 …

windows下的txt文档,传到ubuntu后,每行后面出现^M,怎么处理?

问题背景:windows下pycharm生成的txt文档,传到ubuntu后,每行后面出现^M 用vim打开显示 使用cat -A filename显示如下 参考https://www.lmlphp.com/user/16697/article/item/579325/给出的几种方法 方法一、dos2unix filename。服务器没装…

配置IPv6 over IPv4手动隧道示例

组网需求 如图1所示,两台IPv6主机分别通过SwitchA和SwitchC与IPv4骨干网络连接,客户希望两台IPv6主机能通过IPv4骨干网互通。 图1 配置IPv6 over IPv4手动隧道组网图 配置思路 配置IPv6 over IPv4手动隧道的思路如下: 配置IPv4网络。配置接…

iptables防火墙、filter表控制、扩展匹配、使用iptables配置网络型防火墙、NAT原理、配置SNAT

day05 day05iptables防火墙filter表filter中的三条链环境准备iptables操作验证FORWARD链准备环境配置FORWARD链NAT配置SNAT iptables iptables有多种功能,每一种功能都用一张表来实现最常用的功能是防火墙和NAT从RHEL7开始,默认的防火墙为firewalld&a…

fiddler 手机抓包(含https) 完整流程

第一部分:下载并安装fiddler 一.使用任一浏览器搜索【fiddler下载安装】,并下载fiddler 安装包。 二.fiddler安装包下载成功后,将下载的fiddler压缩包解压到自定义文件夹【fiddler】或者解压到当前文件夹下,双击文件夹中的【fidd…