网络基础-基于TCP协议的Socket通讯

一、Socket通讯基于TCP协议流程图
        UDP 的 Socket 编程相对简单些不在介绍。

二、 服务端程序启动

        服务端程序要先跑起来,然后等待客户端的连接和数据。

        服务端程序首先调用 socket() 函数,创建网络协议为 IPv4,以及传输协议为 TCP 的 Socket ,接着调用 bind() 函数,给这个 Socket 绑定一个 IP 地址和端口。

绑定这两个的目的是什么?

  • 绑定端口的目的:当内核收到 TCP 报文,通过 TCP 头里面的端口号,来找到我们的应用程序,然后把数据传递给我们。
  • 绑定 IP 地址的目的:一台机器是可以有多个网卡的,每个网卡都有对应的 IP 地址,当绑定一个网卡时,内核在收到该网卡上的包,才会发给我们;

        绑定完 IP 地址和端口后,就可以调用 listen() 函数进行监听,如果我们要判定服务器中一个网络程序有没有启动,可以通过 netstate 命令查看对应的端口号是否有被监听。

        服务端进入了监听状态后,通过调用 accept() 函数,来从内核获取客户端的连接,如果没有客户端连接,则会阻塞等待客户端连接的到来。

三、那客户端是怎么发起连接的呢?


        客户端在创建好 Socket 后,调用 connect() 函数发起连接,该函数的参数要指明服务端的 IP 地址和端口号,然后万众期待的 TCP 三次握手就开始了。

在  TCP 连接的过程中,服务器的内核实际上为每个 Socket 维护了两个队列:

  • 一个是还没完全建立连接的队列,称为 TCP 半连接队列,这个队列都是没有完成三次握手的连接,此时服务端处于 syn_rcvd 的状态;
  • 一个是一件建立连接的队列,称为 TCP 全连接队列,这个队列都是完成了三次握手的连接,此时服务端处于 established 状态;

当 TCP 全连接队列不为空后,服务端的 accept() 函数,就会从内核中的 TCP 全连接队列里拿出一个已经完成连接的  Socket 返回应用程序,后续数据传输都用这个 Socket。

注意,监听的 Socket 和真正用来传数据的 Socket 是两个:

  • 一个叫作监听 Socket;
  • 一个叫作已连接 Socket;

连接建立后,客户端和服务端就开始相互传输数据了,双方都可以通过 send() 和 rect() 函数来读写数据。

四、socket中send() 和 rect() 函数。

发送数据端

        要通过TCP连接发送出去的数据都先拷贝到send buffer,可能是从用户空间进程的app buffer拷入的,也可能是从内核的kernel buffer拷入的,拷入的过程是通过send()函数完成的,由于也可以使用write()函数写入数据,所以也把这个过程称为写数据,相应的send buffer也就有了别称write buffer。不过send()函数比write()函数更有效率。

最终数据是通过网卡流出去的,所以send buffer中的数据需要拷贝到网卡中。由于一端是内存,一端是网卡设备,可以直接使用DMA的方式进行拷贝,无需CPU的参与。也就是说,send buffer中的数据通过DMA的方式拷贝到网卡中并通过网络传输给TCP连接的另一端:接收端。

接数据收端

        当通过TCP连接接收数据时,数据肯定是先通过网卡流入的,然后同样通过DMA的方式拷贝到recv buffer中,再通过recv()函数将数据从recv buffer拷入到用户空间进程的app buffer中。

五、客户端主动关闭

我们看看客户端主动调用了 close,会发生什么?

客户端调用 close,表明客户端没有数据需要发送了,则此时会向服务端发送 FIN 报文,进入 FIN_WAIT_1 状态;

服务端接收到了 FIN 报文,TCP 协议栈会为 FIN 包插入一个文件结束符 EOF 到接收缓冲区中,应用程序可以通过 read 调用来感知这个 FIN 包。这个 EOF 会被放在已排队等候的其他已接收的数据之后,这就意味着服务端需要处理这种异常情况,因为 EOF 表示在该连接上再无额外数据到达。此时,服务端进入 CLOSE_WAIT 状态;

接着,当处理完数据后,自然就会读到 EOF,于是也调用 close 关闭它的套接字,这会使得会发出一个 FIN 包,之后处于 LAST_ACK 状态;

客户端接收到服务端的 FIN 包,并发送 ACK 确认包给服务端,此时客户端将进入 TIME_WAIT 状态;

服务端收到 ACK 确认包后,就进入了最后的 CLOSE 状态;

客户端进过 2MSL 时间之后,也进入 CLOSED 状态;

参考:

https://www.cnblogs.com/f-ck-need-u/p/7623252.html

硬不硬你说了算!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题

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

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

相关文章

基于XML配置bean(二)

文章目录 1.工厂中获取bean1.静态工厂1.MyStaticFactory.java2.beans.xml3.测试 2.实例工厂1.MyInstanceFactory.java2.beans.xml3.测试 3.FactoryBean(重点)1.MyFactoryBean.java2.beans.xml3.测试 2.bean配置信息重用继承抽象bean1.beans.xml2.测试 3.…

HarmonyOS实战开发-如何实现一个简单的健康生活应用

功能概述 成就页面展示用户可以获取的所有勋章,当用户满足一定的条件时,将点亮本页面对应的勋章,没有得到的成就勋章处于熄灭状态。共有六种勋章,当用户连续完成任务打卡3天、7天、30天、50天、73天、99天时,可以获得…

SpringBoot框架——8.MybatisPlus常见用法(常用注解+内置方法+分页查询)

1.MybatisPlus常用注解: 1.1 当数据库、表名和字段名和实体类完全一致时无需加注解,不一致时: TableName指定库名 TableId指定表名 TableField指定字段名 1.2 自增主键: TableId(typeIdType.AUTO) private Long id; 1.3 实体类中属…

2000-2022年各省人力资本水平数据(含原始数据+计算过程+计算结果)(无缺失)

2000-2022年各省人力资本水平数据(含原始数据计算过程计算结果) 1、时间:2000-2022年 2、来源:国家统计局 3、指标:普通高等学校在校学生数(万人)、年末常住人口(万人)、人力资本水平 4、范…

CTFshow-PWN-前置基础(pwn20)

提交ctfshow{【.got表与.got.plt是否可写(可写为1,不可写为0)】,【.got的地址】,【.got.plt的地址】 前置基础知识: .got 和 .got.plt 是 ELF(Executable and Linkable Format,可执行和可链接格式)二进制文件中的两个…

(四)qt中使用ffmpeg播放视频,可暂停恢复

一、在qt中添加ffmpeg库及头文件 INCLUDEPATH /usr/local/ffmpeg/include LIBS -L/usr/local/lib -lavutil -lavcodec -lavformat -lswscale 二、详细代码 FFempegVideoDecode 视频解码类(放入线程中) ffmpegvideodecode.h #ifndef FFMPEGVIDEODE…

Qt | 自定义事件第三节

Qt | 事件第一节Qt | 事件第二节书接上回 六、自定义事件与事件的发送 1、发送事件由以下两个函数完成 static void QCoreApplication::postEvent (QObject* receiver, QEvent* event, int priority=Qt::NormalEventPriority);

RHCE作业二

一.配置server主机要求如下: 1.server主机的主机名称为 ntp_server.example.com 2.server主机的IP为: 172.25.254.100 3.server主机的时间为1984-11-11 11:11:11 4.配置server主机的时间同步服务要求可以被所有人使用 二.设定cli…

C++高级特性:可变长模板参数和折叠表达式(八)

1、可变长参数模板 可变长参数是C类模板编程中非常重要的一个东西,也是C11引入的新特性,通过使用…来表示参数长度不固定 可以通过sizeof…(args)获取传入参数的个数数量 &&表示万能引用,需要注意的是如果不使用万能引用&#xff0…

JVM基础面试题第一篇

目录 内存区域面试与分析 1.运行时数据区是什么 2.Java虚拟机栈的作用 3.本地方法栈的作用 4.堆的作用 5.方法区作用 6.运行时常量池的作用 7.直接内存是什么 8.内存溢出和内存泄漏的区别 9.栈溢出的原因 10.方法区溢出的原因 垃圾回收器与内存分配策略-面试与分析 …

LeetCode 49.字母异位词分组

目录 题目描述 方法一 思路: 代码: 题目描述 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 示例 1: 输入: strs ["eat", &qu…

Http 请求偶发400错误

1. 背景 生产环境偶发400请求错误,发生概率万分之一,异常信息如下: 1) 从异常信息可以看到,skywalking的sw8 header解析失效导致异常信息。 2) 0x0d0x0a 作为回车换行符号,没有被正确处理&#…

OpenGL:图元

OpenGL的图元 点 GL_POINTS: 将顶点绘制成单个的点 线 GL_LINES:将顶点用于创建线段,2个点成为一条单独的线段。如果顶点个数是奇数,则忽略最后一个。 顶点:v0, v1, v2, v3, … , vn,线段:v0-v1, v2-v3, v4-v5, … , vn-1 - vn GL_LINE_STRIP:将顶点用于创建线段,…

谈谈Python中的分布式计算和大数据处理

谈谈Python中的分布式计算和大数据处理 Python作为一种通用、解释型的高级编程语言,因其简洁易读、强大的库支持和广泛的应用领域,近年来在分布式计算和大数据处理领域也获得了显著的关注和应用。 分布式计算是一种计算方法,它将大型问题划…

学习笔记(4月18日)vector底层模拟实现(1)

1.迭代器 vector实际上是由迭代器进行维护的,关于迭代器是什么,为什么要叫这个名字,后面的学习会逐渐了解,现在先将迭代器是作为指针即可。 vector底层有三个迭代器,用来起到容量、数组头、元素个数的作用。 同时为…

带头节点的单链表练习(写加注释花了5小时,已废)

目录 1.test.c 2.LinList.c 3.LinList.h 1.test.c 单链表的操作 #include "LinList.h" //head->a0(头节点)->a1->...->ai->...->an int main() {SLNode* head;int i;DataType x, y;ListInitiate(&head);//初始化链表for (i 1; i < 11;…

基于XML配置bean(一)

文章目录 1.获取bean的两种方式1.通过id获取bean&#xff08;前面用过&#xff09;2.通过类型获取bean&#xff08;单例时使用&#xff09;1.案例2.代码1.beans.xml2.SpringBeanTest.java3.结果 3.注意事项 2.三种基本依赖注入方式1.通过属性配置bean&#xff08;前面用过&…

DDoS攻击趋势分析及防御建议:网络安全新挑战与应对策略

在数字化日益普及的今天&#xff0c;网络安全问题日益凸显。其中&#xff0c;分布式拒绝服务&#xff08;DDoS&#xff09;攻击以其巨大的破坏力和难以防范的特性&#xff0c;发起简单、效果显著、难以追踪等特点&#xff0c;因此被黑客广泛使用&#xff0c;已经成为网络安全领…

Python(九十四)变量的作用域

❤️ 专栏简介&#xff1a;本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中&#xff0c;我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 &#xff1a;本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

CSS 设置空格原样显示 white-space:pre-wrap;

CSS 设置空格原样显示 问题描述 html 渲染内容时&#xff0c;对于 空格、回车、Tab 键的 默认处理方式是 &#xff1a; 无论存在多少个连续的空格&#xff0c;都只会保留一个。 结论 由于以上的特性&#xff0c;导致了我们无法直接渲染出原格式的文本。pre 标签 了解一下 &…