TCP客户/服务器程序

POSIX信号处理

  1. 信号有时候也称为软件中断,信号通常是异步的
  2. 信号发送:
  • 由一个进程发给另一个进程
  • 内核发送给某个进程
  1. 处理信号:
  • 通过一个信号处理函数来应对特定信号,这种行为称为捕获信号
  • 将信号设置为SIG_IGN忽略,SIGKILL/SIGSTOP不能被捕获也不能被忽略
  • 将信号设置为SIG_DFL来启动默认处置
  1. 建立信号处置的POSIX方法就是调用sigaction
  2. 有些信号在信号处理函数被调用时阻塞,任何阻塞的信号都是不能递交给进程,将信号掩码设置为空集,则在信号函数运行期间,不阻塞额外的信号
  3. 如果SA_RESTART设置,相应的信号中断的系统调用将有内核自动重启
  4. unix信号默认不排队,信号在被阻塞期间产生多次,解阻塞之后通常只递交一次

处理SIGCHLD信号

  1. 进程终止则该进程的子进程处于僵死状态,处理僵死进程的目的是维护子进程的状态信息将僵死进程的父进程PPID重置为1(被内核领养)
  2. 信号处理函数捕获SIGCHLD信号,调用wait或者waitpidSignal(SIGCHLD, sig_chld);
  3. 当接收到SIGCHLD信号时,父进程阻塞与accept调用,内核会使accept返回一个EINTR错误(被中断的系统调用),父进程不处理这类错误,中止。标准库函中的signal函数不会使内核自动重启被中断的系统调用,SA_RESTRAT没有被设置
  4. 慢系统调用:当阻塞于某个慢系统调用时,进程捕获某个信号且相应的信号处理函数返回时有可能会返回一个EINTR错误。对accept的for循环添加条件if(errno==EINTR); continue;
  5. 当connect被中断时不自动重启,必须调用select等待连接完成

wait和waitpid函数

1
2
3
4
5
6
#include <sys/wait.h>
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid, int *statloc, int options);
//pid参数允许我们指定想要等待的子进程的PID,值为-1表示等待第一个终止的子进程
//options指定附加项,如指定选项是WNHANG告诉内核没有已终止的子进程时不要阻塞函数
//调用成功返回进程ID,出错返回0或者-1
  1. 两个函数均返回两个值:已终止子进程的PID和statloc指针返回的进程终止状态
  2. 如果调用wait的进程没有子进程终止,并且有一个或多个子进程在执行,则wait一直阻塞直到有子进程终止为止
  3. 客户终止时调用exit,所有打开的描述符都由内核自动关闭,五个连接在同时时刻终止,Unix信号不排队,很可能会产生四个僵死进程。使用waitpid在循环内调用获得所有已终止自己才能横的状态,指定WNOHANG选项
    while((pid=waitpid(-1, &stat, WNOHANG))>0)

SIGPIPE信号

  1. 当一个进程向某个已收到RST套接字执行写操作时,内核向进程发送一个SIGPIPE信号,该信号的默认行为是终止进程
  2. 不管是使用信号处理函数并返回还是简单的忽略该信号,写操作都会返回EPIPE错误
  3. 第一次写操作引发RST,第二次写操作时引发SIGPIPE信号

服务器主机关机

  1. Unix系统关机,init进程给所有进程发送SIGTERM信号,等待一段时间,然后给所有仍在运行的进程发送SIGKILL信号,服务器子进程终止时,所有打开的描述符都被关闭

数据格式

  1. 不同的实现以不同的格式存储二进制数
  2. 不同的实现在存储相同的C数据类型上存在差异,32位和64位系统
  3. 不同的实现给结构打包的方式存在差异,取决于个数据类型所用的位数和机器的对其限制
  4. 解决以上数据格式的方法:
  • 将所有传输数据作为字符串来传输
  • 显示定义所支持的二进制格式
WhitneyLu wechat
Contact me by scanning my public WeChat QR code
0%