博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
tcp连接超时, 那么可能会出现两次握手后, 客户端发RST包
阅读量:4141 次
发布时间:2019-05-25

本文共 4103 字,大约阅读时间需要 13 分钟。

        先看服务端:

 

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(){ int sockSrv = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addrSrv; addrSrv.sin_family = AF_INET; addrSrv.sin_addr.s_addr = INADDR_ANY; addrSrv.sin_port = htons(8765); bind(sockSrv, (const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in)); listen(sockSrv, 5); struct sockaddr_in addrClient; int len = sizeof(struct sockaddr_in); int sockConn = accept(sockSrv, (struct sockaddr *)&addrClient, (socklen_t*)&len); while(1) { char szRecvBuf[50001] = {0}; int iRet = recv(sockConn, szRecvBuf, sizeof(szRecvBuf) - 1, 0); printf("iRet is %d\n", iRet); getchar(); close(sockConn); } while(1); close(sockSrv); return 0;}

       启动它。

 

 

       再来看一个带超时时间的connect函数的客户端程序:

 

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[]) // 注意输入参数, 带上ip和port, 带上超时参数{ int sockClient = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addrSrv; addrSrv.sin_addr.s_addr = inet_addr(argv[1]); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(atoi(argv[2])); fcntl(sockClient, F_SETFL, fcntl(sockClient, F_GETFL, 0)|O_NONBLOCK); int iRet = connect(sockClient, ( const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in)); printf("connect iRet is %d, errmsg:%s\n", iRet, strerror(errno)); // 返回-1不一定是异常 if (iRet != 0) { if(errno != EINPROGRESS) { printf("connect error:%s\n",strerror(errno)); } else { int nTime = atoi(argv[3]); // 微秒 struct timeval tm = {0, nTime}; fd_set wset, rset; FD_ZERO(&wset); FD_ZERO(&rset); FD_SET(sockClient, &wset); FD_SET(sockClient, &rset); int n = select(sockClient + 1, &rset, &wset, NULL, &tm); if(n < 0) { printf("select error, n is %d\n", n); } else if(n == 0) { printf("connect time out\n"); } else if (n == 1) { if(FD_ISSET(sockClient, &wset)) { printf("connect ok!\n"); fcntl(sockClient, F_SETFL, fcntl(sockClient, F_GETFL, 0) & ~O_NONBLOCK); } else { printf("unknow error:%s\n", strerror(errno)); } } else { printf("oh, not care now, n is %d\n", n); } } } printf("I am here!\n"); //getchar(); close(sockClient); return 0;}

        服务端在10.100.70.140机器上, 且正在监听8765端口, 我们来看看客户端的log和握手过程(connect函数的超时为1微秒):

 

 

xxxxxx$ ./client 10.100.70.140 8765 1connect iRet is -1, errmsg:Operation now in progressconnect time outI am here!

 

 

xxxxxx$ sudo tcpdump -iany port 23456 -Xnlps0tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes21:43:40.898224 IP 10.100.70.139.51256 > 10.100.70.140.aequus: Flags [S], seq 948273802, win 14280, options [mss 1428,sackOK,TS val 1560139469 ecr 0,nop,wscale 8], length 0        0x0000:  4500 003c 5447 4000 4006 4496 0a64 468b  E..
10.100.70.139.51256: Flags [S.], seq 802450158, ack 948273803, win 14160, options [mss 1428,sackOK,TS val 1560138227 ecr 1560139469,nop,wscale 8], length 0 0x0000: 4500 003c 0000 4000 4006 98dd 0a64 468c E..<..@.@....dF. 0x0010: 0a64 468b 5ba0 c838 2fd4 6aee 3885 828b .dF.[..8/.j.8... 0x0020: a012 3750 9277 0000 0204 0594 0402 080a ..7P.w.......... 0x0030: 5cfd d1f3 5cfd d6cd 0103 0308 0000 0000 \...\........... 0x0040: 0000 0000 0000 0000 0000 0000 ............21:43:40.898450 IP 10.100.70.139.51256 > 10.100.70.140.aequus: Flags [R], seq 948273803, win 0, length 0 0x0000: 4500 0028 04e5 4000 4006 940c 0a64 468b E..(..@.@....dF. 0x0010: 0a64 468c c838 5ba0 3885 828b 0000 0000 .dF..8[.8....... 0x0020: 5004 0000 2f18 0000 0000 0000 0000 0000 P.../........... 0x0030: 0000 0000 0000 0000 ........

       看到RST了。

 

 

       分析下, syn/ack包是在1微秒之后到达的, 所以客户端的select会超时, 代码走入超时逻辑, 等syn/ack到达时, 客户端代码中的超时逻辑中, 执行了close socket的操作。 于是可以这么认为, 经历两次握手后, 客户端调用close socket,  此时发送了RST.

       OK,  不多说。

 

转载地址:http://gjwti.baihongyu.com/

你可能感兴趣的文章
【C#】利用Conditional属性完成编译忽略
查看>>
VUe+webpack构建单页router应用(一)
查看>>
(python版)《剑指Offer》JZ01:二维数组中的查找
查看>>
Spring MVC中使用Thymeleaf模板引擎
查看>>
PHP 7 的五大新特性
查看>>
深入了解php底层机制
查看>>
PHP中的stdClass 【转】
查看>>
XHProf-php轻量级的性能分析工具
查看>>
OpenCV gpu模块样例注释:video_reader.cpp
查看>>
就在昨天,全球 42 亿 IPv4 地址宣告耗尽!
查看>>
Mysql复制表以及复制数据库
查看>>
Linux分区方案
查看>>
如何使用 systemd 中的定时器
查看>>
git命令速查表
查看>>
linux进程监控和自动重启的简单实现
查看>>
OpenFeign学习(三):OpenFeign配置生成代理对象
查看>>
OpenFeign学习(四):OpenFeign的方法同步请求执行
查看>>
OpenFeign学习(六):OpenFign进行表单提交参数或传输文件
查看>>
Ribbon 学习(二):Spring Cloud Ribbon 加载配置原理
查看>>
Ribbon 学习(三):RestTemplate 请求负载流程解析
查看>>