卷一主要以TCP echo服务为例,对UNIX网络socket编程做了讲解。
基本TCP socket编程
使用socket, connect, bind, listen, accpet, fork, exec, close等基本函数搭建一个并发服务器。
然后讨论了多种异常情况,包括:
accept返回前终止
服务器进程终止
服务器会向客户TCP发送FIN,客户在socket会读取到EOF服务器崩溃
这时服务器不会发送FIN,客户TCP会不断尝试重传直到超时。可以使用SO_KEEPALIVE和超时机制探测服务器状态服务器崩溃后重启
客户TCP向服务器发送数据时,服务器由于不存在这个TCP连接,会向客户发送RST
IO复用
讲解了select和poll函数实现IO复用
套接字选项
重点选项:
SO_REUSEADDR
所有服务器套接字都应该使用这个选项,用以部分解决TIME_WAIT的问题SO_LINGER
用以决定close后缓冲区中残留数据的处理方式。l-onoff
设为非0,且l_linger
为0时,close将导致缓冲区中的数据被扔到并向对端发送RST,也可以避免TIME_WAITSO_KEEPALIVE
TCP保活机制
基本UDP socket编程
UDP编程与TCP编程类似,但是由于UDP没有状态,不需要建立连接。
对UDP而言,可以直接使用recvfrom和sendto发送数据。也可以先connect,只不过这个connect并不真正建立连接,只是检查目标是否可达。另外,已连接的UDP可以使用read/write函数读写数据。
Unix域 socket编程
使用unix域socket的理由之一是,通过unix域socket可以传递描述符。
使用socketpair创建unix域socket,其他函数类似。
C/S设计范式
卷一的最后给出了一系列C/S设计范式,并对其性能进行了对比。
TCP迭代服务器
TCP并发服务器,每个客户一个子进程
通过fork为每个客户分配一个子进程,但是由于进程创建开销较大,这种服务器效率并不高TCP并发服务器,预先fork子进程,子进程accept,无锁保护
预先fork子进程,子进程阻塞在accept上由内核进行schedule。由于惊群(TCP连接时,多个子进程被唤醒争夺accept),如果子进程过多,则会比较影响效率TCP并发服务器,预先fork子进程,子进程使用文件上锁/线程上锁
通过用户级的锁降低冲突TCP并发服务器,主进程传递socket描述符到子进程
TCP并发服务器,使用线程替代进程