几种TCP连接中出现RST的情况( 比较详细).docx_第1页
几种TCP连接中出现RST的情况( 比较详细).docx_第2页
几种TCP连接中出现RST的情况( 比较详细).docx_第3页
几种TCP连接中出现RST的情况( 比较详细).docx_第4页
几种TCP连接中出现RST的情况( 比较详细).docx_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

几种TCP连接中出现RST的情况( 比较详细)收藏人:hh37552013-07-02|阅:4725转:16|来源|分享几种TCP连接中出现RST的情况17人收藏此文章,我要收藏发表于1个月前(2013-05-04 11:40) , 已有314次阅读 ,共0个评论目录:- 1 端口未打开 2 请求超时 3 提前关闭 4 在一个已关闭的socket上收到数据 总结 参考文献:应该没有人会质疑,现在是一个网络时代了。应该不少程序员在编程中需要考虑多机、局域网、广域网的各种问题。所以网络知识也是避免不了学习的。而且笔者一直觉得TCP/IP网络知识在一个程序员知识体系中必需占有一席之地的。在TCP协议中RST表示复位,用来异常的关闭连接,在TCP的设计中它是不可或缺的。发送RST包关闭连接时,不必等缓冲区的包都发出去,直接就丢弃缓存区的包发送RST包。而接收端收到RST包后,也不必发送ACK包来确认。其实在网络编程过程中,各种RST错误其实是比较难排查和找到原因的。下面我列出几种会出现RST的情况。1 端口未打开服务器程序端口未打开而客户端来连接。这种情况是最为常见和好理解的一种了。去telnet一个未打开的TCP的端口可能会出现这种错误。这个和操作系统的实现有关。在某些情况下,操作系统也会完全不理会这些发到未打开端口请求。比如在下面这种情况下,主机241向主机114发送一个SYN请求,表示想要连接主机114的40000端口,但是主机114上根本没有打开40000这个端口,于是就向主机241发送了一个RST。这种情况很常见。特别是服务器程序core dump之后重启之前连续出现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:27.799961到15:01:27.961886, 小数点之后的单位是微秒)。因此主机89上的程序认为接收超时,所以发送了RST拒绝进一步发送数据。3 提前关闭关于TCP,我想我们在教科书里都读到过一句话,TCP是一种可靠的连接。 而这可靠有这样一种含义,那就是操作系统接收到的来自TCP连接中的每一个字节,我都会让应用程序接收到。如果应用程序不接收怎么办?你猜对了,RST。看两段程序:01/server.c0203intmain(intargc,char* argv)0405intlisten_fd, real_fd;06structsockaddr_in listen_addr, client_addr;07socklen_t len =sizeof(structsockaddr_in);08listen_fd = socket(AF_INET, SOCK_STREAM, 0);09if(listen_fd = -1)1011perror(socket failed );12return-1;1314bzero(&listen_addr,sizeof(listen_addr);15listen_addr.sin_family = AF_INET;16listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);17listen_addr.sin_port = htons(SERV_PORT);18bind(listen_fd,(structsockaddr *)&listen_addr, len);19listen(listen_fd, WAIT_COUNT);20while(1)2122real_fd = accept(listen_fd, (structsockaddr*)&client_addr, &len);23if(real_fd = -1)2425perror(accpet fail );26return-1;2728if(fork() = 0)2930close(listen_fd);31charpcContent4096;32read(real_fd,pcContent,4096);33close(real_fd);34exit(0);3536close(real_fd);3738return0;39这一段是server的最简单的代码。逻辑很简单,监听一个TCP端口然后当有客户端来连接的时候fork一个子进程来处理。注意看的是这一段fork里面的处理:1charpcContent4096;2read(real_fd,pcContent,4096);3close(real_fd);每次只是读socket的前4096个字节,然后就关闭掉连接。然后再看一下client的代码:01/client.c02intmain(intargc,char* argv)0304intsend_sk;05structsockaddr_in s_addr;06socklen_t len =sizeof(s_addr);07send_sk = socket(AF_INET, SOCK_STREAM, 0);08if(send_sk = -1)0910perror(socket failed );11return-1;1213bzero(&s_addr,sizeof(s_addr);14s_addr.sin_family = AF_INET;1516inet_pton(AF_INET,SER_IP,&s_addr.sin_addr);17s_addr.sin_port = htons(SER_PORT);18if(connect(send_sk,(structsockaddr*)&s_addr,len) = -1)1920perror(connect fail );21return-1;2223charpcContent5000=0;24write(send_sk,pcContent,5000);25sleep(1);26close(send_sk);27这段代码更简单,就是打开一个socket然后连接一个服务器并发送5000个字节。刚才我们看服务器的代码,每次只接收4096个字节,那么就是说客户端发送的剩下的4个字节服务端的应用程序没有接收到,服务器端的socket就被关闭掉,这种情况下会发生什么状况呢,还是抓包看一看。前三行就是TCP的3次握手,从第四行开始看,客户端的49660端口向服务器的9877端口发送了5000个字节的数据,然后服务器端发送了一个ACK进行了确认,紧接着服务器向客户端发送了一个RST断开了连接。和我们的预期一致。4 在一个已关闭的socket上收到数据如果某个socket已经关闭,但依然收到数据也会产生RST。代码如下:客户端:01intmain(intargc,char* argv) 02 03intsend_sk; 04structsockaddr_in s_addr; 05socklen_t len =sizeof(s_addr); 06send_sk = socket(AF_INET, SOCK_STREAM, 0); 07if(send_sk = -1) 08 09perror(socket failed ); 10return-1; 11 12bzero(&s_addr,sizeof(s_addr); 13s_addr.sin_family = AF_INET; 1415inet_pton(AF_INET,SER_IP,&s_addr.sin_addr); 16s_addr.sin_port = htons(SER_PORT); 17if(connect(send_sk,(structsockaddr*)&s_addr,len) = -1) 18 19perror(connect fail ); 20return-1; 21 22charpcContent4096=0;23write(send_sk,pcContent,4096);24sleep(1);25write(send_sk,pcContent,4096);26close(send_sk);27服务端:01intmain(intargc,char* argv) 02 03intlisten_fd, real_fd; 04structsockaddr_in listen_addr, client_addr; 05socklen_t len =sizeof(structsockaddr_in); 06listen_fd = socket(AF_INET, SOCK_STREAM, 0); 07if(listen_fd = -1) 08 09perror(socket failed ); 10return-1; 11 12bzero(&listen_addr,sizeof(listen_addr); 13listen_addr.sin_family = AF_INET; 14listen_addr.sin_addr.s_addr = htonl(INADDR_ANY); 15listen_addr.sin_port = htons(SERV_PORT); 16bind(listen_fd,(structsockaddr *)&listen_addr, len); 17listen(listen_fd, WAIT_COUNT); 18while(1) 19 20real_fd = accept(listen_fd, (structsockaddr*)&client_addr, &len); 21if(real_fd = -1) 22 23perror(accpet fail ); 24return-1; 25 26if(fork() = 0) 27 28close(listen_fd); 29charpcContent4096;30read(real_fd,pcContent,4096);31close(real_fd); 32exit(0); 33 34close(real_fd); 35 36return0; 3

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论