Chinaunix首页 | 论坛 | 博客
  • 博客访问: 118419
  • 博文数量: 41
  • 博客积分: 2564
  • 博客等级: 少校
  • 技术积分: 455
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-20 19:17
文章分类

全部博文(41)

文章存档

2009年(41)

我的朋友

分类: LINUX

2009-04-13 18:00:43

1 正常建立连接:

·服务器端调用accept,客户端调用connect,客户端发送SYN包;

·服务器收到SYN包,回复ACK,并发送一个SYN包;

·客户端收到SYN包,从connect返回,发送SYN包的ACK。此时从客户端角度看,连接已建立,即进入  ESTABLISHED状态;

·服务器端收到ACK,此时从服务器角度来看,连接建立,进入ESTABLISH状态,然后从accept返  回;

由此可见,客户端进入ESTABLISHED状态要早于服务器端,即客户端在收到“三次握手”的第二个数据包以后就进入ESTABLISHED状态,而服务器要收到第三个数据包。

1.1 服务器端调用accept前,客户端终止连接

·服务器端休眠,客户端调用connect,客户端发送SYN包;

·接下来两个过程同正常情况;

·服务器端收到ACK,此时服务器端进入ESTABLISHED状态,但进程依然在睡眠,没有调用  accept;

·客户端发送一个RST包终止连接;

·唤醒服务器端,调用accept;


对于不同的系统,处理方式不一样。在POSIX标准的处理方式是,从accept返回,返回值为负表示出错,同时errno为ECONNABORTED。


2 通信过程中杀死服务端进程

·客户端与服务器正常通信一段时间后,使用kill杀死服务器端进程;

·和正常退出程序一样,被杀死的服务进程打开的文件描述符将被关闭,这将导致一个FIN发往客户  端;

·客户端发送FIN包的ACK,表示此TCP连接的服务器一端一关闭(即服务器不会产生更多数据,但是  有可能还在接收数据);

·此TCP连接服务器端进入FIN_WAIT2状态,客户端进入CLOSE_WAIT状态;

·此时若客户端继续向服务器端写写入数据,则服务器端会返回一个RST包。若读取数据,则会返回  0,表示收到FIN包(遇到EOF);

·若客户端向服务器端写入数据,然后立即读取,有两种情况,如果RST在执行读取动作前到达,则会返回错误,errno为ECONNREST,否则返回0;

另外,说一下SIGPIPE。如果向一个收到了RST包的socket写入数据,则将会产生一个SIGPIPE信号,此信号的默认操作是终止进程。在进行网路编程的时候要考虑进去。


3 通信过程中服务器崩溃

这里说的崩溃是指突然断电、网络连接突然断开或突然重启等意外情况,服务器正常关机和重启等情况不算。

这种情况比较简单,由于服务器崩溃,因此没有进行socket的关闭操作,即没有发送FIN包。这个时候,客户端并不知道服务器端已经崩溃,如果它向服务器发送数据,则协议栈底层将一直重发数据,直到一定时间后,产生ETIMEDOUT错误。如果中间的路由器提前发现服务器已经崩溃,则会向客户端发送ICMP包,指示“目标不可达”,此时客户端将产生EHOSTUNREACH或ENETUNREACH错误。

注意,这种情况仅在,服务器崩溃后客户端向服务器端写入数据才会发生,如果服务器崩溃后客户端没有发送数据,而是阻塞在读操作中,则将会一直阻塞。为了避免这种情况,可以使用SO_KEEPALIVE选项对socket进行设置。

3.1 服务器崩溃以后重启

在这种情况下,如果服务器重启以后,客户端的写操作还没有返回超时,则数据到达服务器端以后,服务器将产生一个RTS包。后续的步骤参考1、2。


4 关闭服务器

这里的关闭指的是服务器管理员在通信进行中,使用关机命令关闭服务器。

在这种情况下,操作系统会先发SIGTERM给所有进程,然后一段时间后,会向还在运行中的进程发送SIGKILL终止进程。如果服务进程不截获SIGTERM信号,然后在信号处理函数中关闭连接,则将又有SIGKILL来处理,步骤参考2。


相关内容见,unp1第三版。

连载:

阅读(1219) | 评论(1) | 转发(0) |
0

上一篇:消除递归的方法

下一篇:I/O复用

给主人留下些什么吧!~~

chinaunix网友2009-09-13 23:13:59

1,2我比较认同,但3“为什么”我不敢苟同:UDP也是有源目的地址也端口的,只要协议实现正确,应该不至于会“将P1和P2”的数据合并到一块吧,至于为什么要这样做,我也还不太清楚