几种TCP连接中出现RST的情况比较详细.docx
- 文档编号:29757408
- 上传时间:2023-07-26
- 格式:DOCX
- 页数:14
- 大小:240.32KB
几种TCP连接中出现RST的情况比较详细.docx
《几种TCP连接中出现RST的情况比较详细.docx》由会员分享,可在线阅读,更多相关《几种TCP连接中出现RST的情况比较详细.docx(14页珍藏版)》请在冰豆网上搜索。
几种TCP连接中出现RST的情况比较详细
几种TCP连接中出现RST的情况(比较详细)
收藏人:
2013-07-02 | 阅:
4725 转:
16
|
|
几种TCP连接中出现RST的情况
17人收藏此文章, 发表于1个月前(2013-05-0411:
40),已有314次阅读,共个评论
目录:
[ ]
应该没有人会质疑,现在是一个网络时代了。
应该不少程序员在编程中需要考虑多机、局域网、广域网的各种问题。
所以网络知识也是避免不了学习的。
而且笔者一直觉得TCP/IP网络知识在一个程序员知识体系中必需占有一席之地的。
在TCP协议中RST表示复位,用来异常的关闭连接,在TCP的设计中它是不可或缺的。
发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓存区的包发送RST包。
而接收端收到RST包后,也不必发送ACK包来确认。
其实在网络编程过程中,各种RST错误其实是比较难排查和找到原因的。
下面我列出几种会出现RST的情况。
1端口未打开
服务器程序端口未打开而客户端来连接。
这种情况是最为常见和好理解的一种了。
去telnet一个未打开的TCP的端口可能会出现这种错误。
这个和操作系统的实现有关。
在某些情况下,操作系统也会完全不理会这些发到未打开端口请求。
比如在下面这种情况下,主机241向主机114发送一个SYN请求,表示想要连接主机114的40000端口,但是主机114上根本没有打开40000这个端口,于是就向主机241发送了一个RST。
这种情况很常见。
特别是服务器程序coredump之后重启之前连续出现RST的情况会经常发生。
当然在某些操作系统的主机上,未必是这样的表现。
比如向一台WINDOWS7的主机发送一个连接不存在的端口的请求,这台主机就不会回应。
2请求超时
曾经遇到过这样一个情况:
一个客户端连接服务器,connect返回-1并且error=EINPROGRESS。
直接telnet发现网络连接没有问题。
ping没有出现丢包。
用抓包工具查看,客户端是在收到服务器发出的SYN之后就莫名其妙的发送了RST。
比如像下面这样:
有89、27两台主机。
主机89向主机27发送了一个SYN,表示希望连接8888端口,主机27回应了主机89一个SYN表示可以连接。
但是主机27却很不友好,莫名其妙的发送了一个RST表示我不想连接你了。
后来经过排查发现,在主机89上的程序在建立了socket之后,用setsockopt的SO_RCVTIMEO选项设置了recv的超时时间为100ms。
而我们看上面的抓包结果表示,从主机89发出SYN到接收SYN的时间多达110ms。
(从15:
01:
到15:
01:
,小数点之后的单位是微秒)。
因此主机89上的程序认为接收超时,所以发送了RST拒绝进一步发送数据。
3提前关闭
关于TCP,我想我们在教科书里都读到过一句话,'TCP是一种可靠的连接'。
而这可靠有这样一种含义,那就是操作系统接收到的来自TCP连接中的每一个字节,我都会让应用程序接收到。
如果应用程序不接收怎么办?
你猜对了,RST。
看两段程序:
01
//
02
03
int main(int argc, char**argv)
04
{
05
int listen_fd,real_fd;
06
struct sockaddr_inlisten_addr,client_addr;
07
socklen_tlen= sizeof(struct sockaddr_in);
08
listen_fd=socket(AF_INET,SOCK_STREAM,0);
09
if(listen_fd==-1)
10
{
11
perror("socketfailed ");
12
return -1;
13
}
14
bzero(&listen_addr,sizeof(listen_addr));
15
=AF_INET;
16
=htonl(INADDR_ANY);
17
=htons(SERV_PORT);
18
bind(listen_fd,(struct sockaddr*)&listen_addr,len);
19
listen(listen_fd,WAIT_COUNT);
20
while
(1)
21
{
22
real_fd=accept(listen_fd,(struct sockaddr*)&client_addr,&len);
23
if(real_fd==-1)
24
{
25
perror("accpetfail ");
26
return -1;
27
}
28
if(fork()==0)
29
{
30
close(listen_fd);
31
char pcContent[4096];
32
read(real_fd,pcContent,4096);
33
close(real_fd);
34
exit(0);
35
}
36
close(real_fd);
37
}
38
return 0;
39
}
这一段是server的最简单的代码。
逻辑很简单,监听一个TCP端口然后当有客户端来连接的时候fork一个子进程来处理。
注意看的是这一段fork里面的处理:
1
char pcContent[4096];
2
read(real_fd,pcContent,4096);
3
close(real_fd);
每次只是读socket的前4096个字节,然后就关闭掉连接。
然后再看一下client的代码:
01
//
02
int main(int argc, char**argv)
03
{
04
int send_sk;
05
struct sockaddr_ins_addr;
06
socklen_tlen= sizeof(s_addr);
07
send_sk=socket(AF_INET,SOCK_STREAM,0);
08
if(send_sk==-1)
09
{
10
perror("socketfailed ");
11
return -1;
12
}
13
bzero(&s_addr, sizeof(s_addr));
14
=AF_INET;
15
16
inet_pton(AF_INET,SER_IP,&;
17
=htons(SER_PORT);
18
if(connect(send_sk,(struct sockaddr*)&s_addr,len)==-1)
19
{
20
perror("connectfail ");
21
return -1;
22
}
23
char pcContent[5000]={0};
24
write(send_sk,pcContent,5000);
25
sleep
(1);
26
close(send_sk);
27
}
这段代码更简单,就是打开一个socket然后连接一个服务器并发送5000个字节。
刚才我们看服务器的代码,每次只接收4096个字节,那么就是说客户端发送的剩下的4个字节服务端的应用程序没有接收到,服务器端的socket就被关闭掉,这种情况下会发生什么状况呢,还是抓包看一看。
前三行就是TCP的3次握手,从第四行开始看,客户端的49660端口向服务器的9877端口发送了5000个字节的数据,然后服务器端发送了一个ACK进行了确认,紧接着服务器向客户端发送了一个RST断开了连接。
和我们的预期一致。
4在一个已关闭的socket上收到数据
如果某个socket已经关闭,但依然收到数据也会产生RST。
代码如下:
客户端:
01
int main(int argc, char**argv)
02
{
03
int send_sk;
04
struct sockaddr_ins_addr;
05
socklen_tlen= sizeof(s_addr);
06
send_sk=socket(AF_INET,SOCK_STREAM,0);
07
if(send_sk==-1)
08
{
09
perror("socketfailed ");
10
return -1;
11
}
12
bzero(&s_addr, sizeof(s_addr));
13
=AF_INET;
14
15
inet_pton(AF_INET,SER_IP,&;
16
=htons(SER_PORT);
17
if(connect(send_sk,(struct sockaddr*)&s_addr,len)==-1)
18
{
19
perror("connectfail ");
20
return -1;
21
}
22
char pcContent[4096]={0};
23
write(send_sk,pcContent,4096);
24
sleep
(1);
25
write(send_sk,pcContent,4096);
26
close(send_sk);
27
}
服务端:
01
int main(int argc, char**argv)
02
{
03
int listen_fd,real_fd;
04
struct sockaddr_inlisten_addr,client_addr;
05
socklen_tlen= sizeof(struct sockaddr_in);
06
listen_fd=socket(AF_INET,SOCK_STREAM,0);
07
if(listen_fd==-1)
08
{
09
perror("socketfailed ");
10
return -1;
11
}
12
bzero(&listen_addr,sizeof(listen_addr));
13
=AF_INET;
14
=htonl(INADDR_ANY);
15
=htons(SERV_PORT);
16
bind(listen_fd,(struct sockaddr*)&listen_addr,len);
17
listen(listen_fd,WAIT_COUNT);
18
while
(1)
19
{
20
real_fd=accept(listen_fd,(struct sockaddr*)&client_addr,&len);
21
if(real_fd==-1)
22
{
23
perror("accpetfail ");
24
return -1;
25
}
26
if(fork()==0)
27
{
28
close(listen_fd);
29
char pcContent[4096];
30
read(real_fd,pcContent,4096);
31
close(real_fd);
32
exit(0);
33
}
34
close(real_fd);
35
}
36
return 0;
37
}
客户端在服务端已经关闭掉socket之后,仍然在发送数据。
这时服务端会产生RST。
总结
总结,本文讲了几种TCP连接中出现RST的情况。
实际上肯定还有无数种的RST发生,我以后会慢慢收集把更多的例子加入这篇文章。
参考文献:
1从TCP协议的原理来谈谈RST攻击 TCP客户-服务器程序例子
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- TCP 连接 出现 RST 情况 比较 详细