当前位置: 首页 > 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先修…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)

macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...

Canal环境搭建并实现和ES数据同步

作者:田超凡 日期:2025年6月7日 Canal安装,启动端口11111、8082: 安装canal-deployer服务端: https://github.com/alibaba/canal/releases/1.1.7/canal.deployer-1.1.7.tar.gz cd /opt/homebrew/etc mkdir canal…...

2025-05-08-deepseek本地化部署

title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek:小白也能轻松搞定! 如何给本地部署的 DeepSeek 投喂数据,让他更懂你 [实验目的]:理解系统架构与原…...