linux网络编程(二)TCP通讯状态

linux网络编程(二)TCP通讯状态

  • TCP状态转换
  • 为什么需要等待2MSL?
  • 端口复用

TCP状态转换

在这里插入图片描述
tcp协议连接开始会经过三次握手,客户端和服务器开始都会处于CLOSED状态
第一次握手:客户端会先发送SYN请求给服务器,客户端处于SYN_SET状态,
第二次握手:服务器接收到SYN后,发给客户端ACK回答和SYN请求,服务器从LISTEN变成SYN_RCVD
第三次握手:客户端接收到ACK和SYN请求后,发送给服务器ACK回应,客户端从SYN_SET变成ESTABLISHED状态,服务器接收到ACK回应后,也变为ESTABLISHED状态

tcp协议关闭会经过四次握手,假设客户端为主动关闭,服务器为被动关闭
第一次握手:客户端发送FIN请求,状态变为FIN_WAIT_1
第二次握手:服务器接收到FIN请求,同时发送ACK应答,状态为CLOSE_WAIT,客户端收到ACK应答后,变为FIN_WAIT_2状态,此时处于半关闭的状态
第三次握手:服务器发送FIN请求,状态为LACK_ACK
第四次握手:客户端接收到FIN请求后,发送ACK应答,状态变为TIME_WAIT,等待2MSL之后关闭

  • CLOSED:表示初始状态。
  • LISTEN:该状态表示服务器端的某个SOCKET处于监听状态,可以接受连接。
  • SYN_SENT:这个状态与SYN_RCVD遥相呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,随即进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。
  • SYN_RCVD: 该状态表示接收到SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂。此种状态时,当收到客户端的ACK报文后,会进入到ESTABLISHED状态。
  • ESTABLISHED:表示连接已经建立。
  • FIN_WAIT_1: FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。区别是:FIN_WAIT_1状态是当socket在ESTABLISHED状态时,想主动关闭连接,向对方发送了FIN报文,此时该socket进入到FIN_WAIT_1状态。
    FIN_WAIT_2状态是当对方回应ACK后,该socket进入到FIN_WAIT_2状态,正常情况下,对方应马上回应ACK报文,所以FIN_WAIT_1状态一般较难见到,而FIN_WAIT_2状态可用netstat看到。
  • FIN_WAIT_2:主动关闭链接的一方,发出FIN收到ACK以后进入该状态。称之为半连接或半关闭状态。该状态下的socket只能接收数据,不能发。
  • TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,等2MSL后即可回到CLOSED可用状态。如果FIN_WAIT_1状态下,收到对方同时带
    FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
  • CLOSING: 这种状态较特殊,属于一种较罕见的状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。
  • CLOSE_WAIT: 此种状态表示在等待关闭。当对方关闭一个SOCKET后发送FIN报文给自己,系统会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,察看是否还有数据发送给对方,如果没有可以close这个SOCKET,发送FIN报文给对方,即关闭连接。所以在CLOSE_WAIT状态下,需要关闭连接。
  • LAST_ACK: 该状态是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,即可以进入到CLOSED可用状态。

为什么需要等待2MSL?

当客户端也就是主动关闭的一端,接收到服务器也就是被动关闭的一端的FIN请求时,需要回应ACK回应,但是客户端并不能保证ACK回应服务器一定能收到,就添加了一个保护机制,在2MSL时间内,如果服务器没有收到ACK回应,服务器会再一次发送FIN请求,知道能收到客户端收到ACK回应。服务器在2MSL之内一直没有收到的话,客户端将做超时处理,关闭失败。
作用

  • 让4次握手关闭流程更加可靠,4次握手的最后一个ACK是是由主动关闭方发送出去的,若这个ACK丢失,被动关闭方会再次发一个FIN过来。若主动关闭方能够保持一个2MSL的TIME_WAIT状态,则有更大的机会让丢失的ACK被再次发送出去。
  • 防止lost duplicate对后续新建正常链接的传输造成破坏。lost uplicate在实际的网络中非常常见,经常是由于路由器产生故障,路径无法收敛,导致一个packet在路由器A,B,C之间做类似死循环的跳转。IP头部有个TTL,限制了一个包在网络中的最大跳数,因此这个包有两种命运,要么最后TTL变为0,在网络中消失;要么TTL在变为0之前路由器路径收敛,它凭借剩余的TTL跳数终于到达目的地。但非常可惜的是TCP通过超时重传机制在早些时候发送了一个跟它一模一样的包,并先于它达到了目的地,因此它的命运也就注定被TCP协议栈抛弃。

端口复用

在server的TCP连接没有完全断开之前不允许重新监听是不合理的
在server代码的socket()和bind()调用之间插入如下代码:

int opt = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

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

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

相关文章

gethostbyname() 函数说明

转载&#xff1a;http://www.cnblogs.com/cxz2009/archive/2010/11/19/1881611.html gethostbyname()函数说明——用域名或主机名获取IP地址 包含头文件 #include <netdb.h> #include <sys/socket.h> 函数原型 struct hostent *gethostbyna…

linux网络编程(三)select、poll和epoll

linux网络编程&#xff08;三&#xff09;select、poll和epoll一、为什么会有多路I/O转接服务器&#xff1f;二、select三、poll三、epoll一、为什么会有多路I/O转接服务器&#xff1f; 为什么会有多路I/O转接服务器呢&#xff1f;在学这个之前&#xff0c;我们同使用的是多线…

Linux socket编程(一) 对套接字操作的封装

转载:http://www.cnblogs.com/-Lei/archive/2012/09/04/2670942.html 以前写的&#xff0c;现在回顾一下&#xff1a; 下面是对socket操作的封装&#xff0c;因为在Linux下写中文到了windows里面会乱码&#xff0c;所以注释用英文来写&#xff0c;有空再查下解决方法吧 socket.…

数据结构(二)栈

栈一、栈顺序栈线性栈(不带头结点)线性栈(带头结点)共享栈一、栈 栈是只允许在一端进行插入或删除操作的线性表。 栈顶&#xff1a;线性表允许进行插入删除的那一端 栈底&#xff1a;固定的&#xff0c;不允许进行插入和删除的那一端 空栈&#xff1a;不含如何元素的空表 顺序…

如何在linux上安装sqlite数据库

如何在linux上安装sqlite数据库一、下载二、解压三、配置&#xff08;configure&#xff09;四、编译和安装五、执行sqlite3程序六、测试代码一、下载 首先要先下载sqlite3源码包 链接&#xff1a;https://pan.baidu.com/s/1_70342ZLlPjLlqGzpy5IHw 提取码&#xff1a;84ne …

数据结构(三)队列

数据结构&#xff08;三&#xff09;队列队列队列&#xff08;顺序存储&#xff09;循环队列&#xff08;顺序存储&#xff09;队列&#xff08;链式存储&#xff09;队列 队列是一种受限制的线性表&#xff0c;只允许表的一端插入&#xff0c;在表的另一端删除 队列&#xf…

Linux fcntl函数详解

转载&#xff1a;http://www.cnblogs.com/xuyh/p/3273082.html 功能描述&#xff1a;根据文件描述词来操作文件的特性。 文件控制函数 fcntl -- file control 头文件&#xff1a; #include <unistd.h> #include <fcntl.h> 函数原型&#xff1a; …

vs2019使用sqlite数据库远程连接linux

vs2019使用sqlite数据库远程连接linux一、sqlite3添加到目录二、添加依赖库三、测试一、sqlite3添加到目录 将两个sqlite3头文件放入目录中 二、添加依赖库 打开项目属性 添加完成 三、测试 #include <stdio.h> #include <sqlite3.h>int main(int argc, cha…

linux网络编程(四)线程池

linux网络编程&#xff08;四&#xff09;线程池为什么会有线程池&#xff1f;实现简单的线程池为什么会有线程池&#xff1f; 大多数的服务器可能都有这样一种情况&#xff0c;就是会在单位时间内接收到大量客户端请求&#xff0c;我们可以采取接受到客户端请求创建一个线程的…

AIGC:大语言模型LLM的幻觉问题

引言 在使用ChatGPT或者其他大模型时&#xff0c;我们经常会遇到模型答非所问、知识错误、甚至自相矛盾的问题。 虽然大语言模型&#xff08;LLMs&#xff09;在各种下游任务中展示出了卓越的能力&#xff0c;在多个领域有广泛应用&#xff0c;但存在着幻觉的问题&#xff1a…

关于C++子类父类成员函数的覆盖和隐藏

转载&#xff1a;http://blog.csdn.net/worldmakewayfordream/article/details/46827161 函数的覆盖 覆盖发生的条件&#xff1a; &#xff08;1&#xff09; 基类必须是虚函数&#xff08;使用virtual 关键字来进行声明&#xff09; &#xff08;2&#xff09;发生覆盖的两个函…

数据结构(四)串的顺序存储

#include <stdio.h> #include <stdlib.h>#define MAXLEN 255 //定长顺序存储 typedef struct {char ch[MAXLEN]; //每个分量存储一个字符int length; //串的实际长度 }SString;//串的初始化 bool StrAssign(SString& T, char* chars) {int i 0, len;char* …

数据结构(四)串的动态数组存储

#include <stdio.h> #include <stdlib.h>#define MAXLEN 255 //定长顺序存储 typedef struct {char* ch; //每个分量存储一个字符int length; //串的实际长度 }SString;//串的初始化 bool StrAssign(SString& T, char* chars) {int i 0, len;T.ch (char*)m…

C++名字隐藏

转载&#xff1a;http://www.weixueyuan.net/view/6361.html 如果派生类中新增一个成员变量&#xff0c;该成员变量与基类中的成员变量同名&#xff0c;则新增的成员变量就会遮蔽从基类中继承过来的成员变量。同理&#xff0c;如果派生类中新增的成员函数与基类中的成员函数同…

c语言深入浅出(一)strcpy和memcpy的区别

c语言深入浅出&#xff08;一&#xff09;strcpy和memcpy的区别strcpy和memcpy都是c语言的库函数 strcpy:只用于字符串的复制&#xff0c;当碰到‘\0’就停止了 memcpy:用于这个内存的拷贝&#xff0c;适用于结构体、字符数组、类等 char * strcpy(char * dest, const char * s…

C++ dynamic_cast操作符

转载&#xff1a;http://www.weixueyuan.net/view/6377.html 在C中&#xff0c;编译期的类型转换有可能会在运行时出现错误&#xff0c;特别是涉及到类对象的指针或引用操作时&#xff0c;更容易产生错误。Dynamic_cast操作符则可以在运行期对可能产生问题的类型转换进行测试。…

数据结构(五)树

数据结构&#xff08;五&#xff09;树一、基本操作树是n个节点的有限集&#xff0c;它是一种递归的数据结构 一、基本操作 #include <stdio.h> #include <stdlib.h> #include <iostream>#define Elemtype charusing namespace std; typedef struct BiTNod…

C++ typeid操作符

转载&#xff1a;http://www.weixueyuan.net/view/6378.html typeid操作符用于判断表达式的类型&#xff0c;注意它和sizeof一样是一个操作符而不是函数。如果需要使用typeid操作符&#xff0c;最好加上typeinfo头文件。 给出以下定义 int a;double b;char * c;long d; 下表列…

数据结构(五)层次遍历

数据结构&#xff08;五&#xff09;层次遍历// linear_listqueue.cpp : This file contains the main function. Program execution begins and ends there. //#include <iostream> #include <stdlib.h> #include <stdio.h> #define ElemType BiTree using …

C++成员函数指针的应用

转载&#xff1a;http://www.cppblog.com/colys/archive/2009/08/18/25785.html C中&#xff0c;成员指针是最为复杂的语法结构。但在事件驱动和多线程应用中被广泛用于调用回叫函数。在多线程应用中&#xff0c;每个线程都通过指向成员函数的指针来调用该函数。在这样的应用中…