您的位置:首页 > 理论基础 > 计算机网络

Linux网络编程(三) TCP客户/服务器程序示例

2014-08-03 00:02 211 查看
下图是简单的回射服务器模型







利用fork生成一个子进程,来处理客户的数据

1.处理SIGCHLD信号

子进程终止后,如果父进程未加处理,子进程的状态就是僵死状态

设置僵死状态的目的是维护子进程的信息,以便在某个时刻父进程来获取。这些信息包括子进程的进程ID、终止状态以及资源利用信息(CPU时间、内存使用量等等)。如果一个进程终止,则该进程的所有子进程处于僵死状态,那么它的所有僵死子进程的父进程ID将被重置为1.继承这些子进程的init进程将清理它们

处理僵死进程

僵死进程占用内核中的空间,最终可导致我们耗尽进程资源。无论何时我们fork子进程都得wait它们,以防它们变成僵死进程。我们可以建立一个SIGCHLD信号的信号处理函数,在函数体中,我们调用wait,我们在listen()函数调用之后增加如下函数调用:

signal(SIGCHLD,sig_chld);

我们必须在fork第一个子进程之前完成信号处理函数的建立,且只做一次。

1: void sig_chld(int signo)
2: {
3: pid_t pid;
4: int stat;
5: pid=wait(&stat);
6: printf("child %d terminate\n",pid);
7: return;
8: }

当SIG_CHLD信号递交时,父进程阻塞于accept调用。sig_chld函数执行,其wait调用取到子进程PID和终止状态。

accept会返回一个EINTR错误

2.特殊情况

1.accept返回前连接终止

当三路握手完成从而连接建立后,客户TCP却发送了一个RST。在服务器端看来,就在该连接已由TCP排队,等着服务器进程调用accept的时候RST到达。稍后,调用accept

大多数实现会返回一个错误给服务器进程,作为accept的返回结果,返回值为ECONNABORTED

2.SIGPIPE信号

当一个进程向一个已经接收到RST的套接字执行写操作时,内核向该进程发送一个SIGPIPE信号。该信号的默认动作是终止进程,因此进程应该捕获它

不论进程是捕获了该信号并从该信号的处理函数中返回,还是简单地忽略该信号,写操作将返回EPIPE错误

3.服务器主机崩溃

当服务器主机崩溃时,客户端会进行重传机制,重传该数据12次,总共约9分钟才放弃重传。当最后客户放弃重传时,客户端返回一个错误ETIMEOUT.

如果某个中间路由器判定服务器主机不可达,从而响应以一个“目的不可达”ICMP消息,那么所返回的错误是EHOSTUNREACH或ENETUNREACH

4.服务器主机崩溃并重启

当服务器主机崩溃并重启后,它的TCP丢失了崩溃前的所有连接信息,一次服务器对于所接收到的来自客户的数据分节响应以一个RST

当客户收到RST时,导致该读操作返回ECONNRESET
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: