Chinaunix首页 | 论坛 | 博客
  • 博客访问: 516639
  • 博文数量: 240
  • 博客积分: 791
  • 博客等级: 军士长
  • 技术积分: 1694
  • 用 户 组: 普通用户
  • 注册时间: 2011-08-23 18:21
文章分类

全部博文(240)

文章存档

2013年(21)

2012年(219)

我的朋友

分类:

2012-07-16 10:52:20

原文地址:TCP客户/服务器异常 作者:zhjl616

1.       服务器进程终止

假定此时服务器与客户端都已启动,并已建立连接。

clip_image001

clip_image002

此时客户端阻塞与fgets调用,并键入一行数据等待下一行,此时杀死服务器子进程

clip_image003

客户端再次输入数据之后:

clip_image004

clip_image006

整个过程图解如下

4Q1(P9G@WUNG8)25SPY0_0L

客户端接收到FIN(即处于CLOSE_WAIT状态),说明服务器已经关闭了连接,但是服务器并没有告知客户端TCP服务器已经终止。于是客户端继续发送数据,服务器响应一个RST,可以抓包看到:

192.168.197.5 192.168.197.10 Src=41839,Dst=9877,.AP...,S=1333764517        

192.168.197.10        192.168.197.5 Src=9877 Dst=41839,...R..,S=2138602188  

此问题说明了:客户端不能单纯阻塞在套接字和标准输入某个特定的源的输入(比如阻塞与fgets,但是不阻塞与socket),而应该阻塞在其中任何一个源的输入上,于是引入了selectpoll,这是后话。

2.       服务器主机崩溃

首先服务器启动进程,客户端打开连接,并输入一行数据,然后让主机崩溃(虚拟机里面在点poweroff

clip_image008

可以看到整个过程大概为15分钟,这也太夸张了!!原因是客户端发送完数据之后,

一直阻塞与read(从服务器到客户端)调用,然后一直重传,直到最后超时,客户最终会发现服务器主机已崩溃或主机不可达。解决的方法就是自己写一个read函数然后设置超时,或者加一个SO_KEEPALIVE选项。

3.       服务器主机崩溃后重启

这个实验也挺有意思,首先建立好连接,和上面一样,先输入一行,然后再输一行,

这时把主机崩溃了,再重启它。

clip_image010

抓包的情况看看:

192.168.197.10         192.168.197.5          Src=9877,Dst=41848,...R..,S=3100751727

可以看到服务器此时并没有启动服务器进程,当它重启之后收到了一个请求的连接,

于是对于来自客户的数据分节响应一个RST,客户阻塞与read调用,收到了这个RST之后便返回ECONNRESET错误。

4.       服务器关机

这里指的是正常关机,因为Unix系统关机时,会发送SIGTERMSIGKILL信号,

SIGTREM可能忽略,但是SIGKILL信号不能忽略,于是服务器将由SIGKILL终止,当服务器子进程终止时,第一种情况(服务器进程终止)再次重演。

阅读(511) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~