UNIX网络编程中的须要注意的问题

  • 字节流套接字上调用read或write,输入或输出的字节数可能比请求的数量少,这个现象的缘由在于内核中用于套接字的缓冲区可能已经达到了极限。此时所须要的是调用者再次调用read或write函数。这个现象在read()一个字节流套接字时很常见,可是在write()一个字节流套接字时只能在该套接字为非阻塞的前提下才出现。算法

  • connect()函数
    1)若客户没有收到SYN分节的响应,则返回ETIMEDOUT错误;
    2)若对客户的SYN响应是RST,则代表服务器在指定的端口上没有进程在等待与之链接,客户一接收到RST就立刻返回ECONNREFUSED错误;
    3)若客户发出的SYN在中间的路由器上引起了一个ICMP目的不可达错误,则间隔必定时间从新发送,若未收到响应,则返回EHOSTUNREACH或ENETUNREACH错误;
    4)若connect()失败则该套接字再也不可用,必须关闭,不能再对该套接字再次调用connect()函数。编程

  • listen()函数
    内核为任何一个给定的监听套接字维护两个队列:未完成链接队列,已完成链接队列。当一个客户SYN到达时,若这些队列是满的,TCP就忽略该分节,也就是不发送RST。服务器

  • accept()函数
    已完成链接队列中的队头项将返回给进程,或者若是该列队为空,那么进程将被投入睡眠,直到TCP在该队列中放入一项才唤醒它。网络

  • close()函数
    close()一个TCP套接字的默认行为是把该套接字标记成已关闭,而后当即返回到调用进程,该套接字描述符不能再由调用进程使用,然而TCP将尝试发送已排队等待发送到对端的任何数据,发送完毕后发生的是正常的TCP链接终止序列。异步

  • 当fork子进程时,必须捕获SIGCHLD信号。在Linux中,每一个信号都有一个预约义的默认行为,它们是下面的一种:进程忽略该信号、进程终止、进程终止并转储存储器、进程中止直到被SIGCONT信号重启。而最好的处理SIGCHLD信号的方式是在信号处理函数中调用while((pid = waitpid(-1, &status, WNOHANG)) > 0);,而不是调用wait()。函数

  • 当信号是在父进程阻塞于慢系统调用时由父进程捕获的,内核就会使系统调用返回一个EINTR错误,咱们必须判断并处理该错误,如当父进程调用accept()时,子进程发送SIGCHLD信号。code

  • 当执行kill命令杀死服务器进程时,服务器进程会向客户发送一个FIN,而客户响应一个ACK,这就是TCP链接终止工做的前半部分。当客户再向服务器发送数据时,服务器会响应一个RST,当客户再向这个响应RST的套接字执行写操做时,内核向该进程发送一个SIGPIPE信号。队列

  • 当服务器主机崩溃,即服务器忽然从网络上断开,这时向服务器发送数据,服务器对客户的数据分节根本没有响应,返回的错误将是ETIMEDOUT,若是某个中间路由器返回ICMP目的不可达信息,返回的错误将是EHOSTUNREACH或ENETUNREACH错误。进程

  • 当服务器主机崩溃后重启,即断开服务器网络,再从新启动,最后再把它接入网络,服务器会对全部收到来自客户的数据分节响应一个RST。路由

  • 当服务器主机关机时,init进程一般先给全部进程发送SIGTERM信号,等待一段固定时间,而后给全部仍在运行的进程发送SIGKILL信号,服务器上全部打开着的描述符都被关闭。

  • 检测各类TCP条件的方法

  • close()有两个限制可使用shutdown()来避免。close()仅在引用计数变为0时才关闭套接字,而使用shutdown()能够无论引用计数就激发TCP的正常链接终止序列;close()终止读写两个方向的数据传送,而shutdown()能够根据参数选择终止。

  • SO_KEEPALIVE套接字选项
    若是2小时内在该套接字的任一方向上都没有数据交换,TCP就自动给对端发送一个保持存活探测分节。
    对端可能发生的动做有3种,1)响应ACK;2)响应RST(套接字的待处理错误被置为ECONNRESET,套接字自己被关闭);3)无任何响应(共发送8个探测分节,若是根本没有对TCP的探测分节的响应,该套接字的待处理错误就被置为ETIMEDOUT,套接字自己被关闭)。

  • SO_LINGER套接字选项
    指定close()对面向链接的协议如何操做。shutdown和SO_LINGER各类状况总结以下。

  • SO_REUSEADDR套接字选项
    1)容许启动一个监听服务器并捆绑其众所周知的端口,即便之前创建的将该端口用做它们的本地端口链接仍存在;
    2)容许在同一个端口上启动同一个服务器的多个实例,只要每一个实例捆绑一个不一样的本地IP地址便可;
    3)容许单个进程捆绑同一端口到多个套接字上,只要每次捆绑指定不一样的本地IP地址便可,TCP服务器一般不使用这种方法;
    4)容许彻底重复的捆绑,一样的IP地址和端口还能够捆绑到另外一个套接字上,通常来讲本特性仅支持UDP套接字。

  • TCP_NODELAY套接字选项
    开启本选项将禁止TCP的Nagle算法,Nagle算法经常与ACK延滞算法联合使用。该算法是指发送端即便还有应该发送的数据,但若是这部分数据不多的话,则进行延迟发送的一种处理机制。具体来讲,就是公在下列任意一种条件下才能发送数据,若是两个条件都不知足,那么暂时等待一段时间之后再进行数据发送。
    1)已发送的数据都已经收到确认应答时;
    2)能够发送最大长度(MSS)的数据时。

  • UDP的connect()函数
    对于已链接UDP套接字,与默认的示链接UDP套接字相比,发生了三个变化:
    1)不能给输出操做指定目的IP地址和端口号,不使用sendto(),改用write()或send();
    2)没必要使用recvfrom()以获悉数据报的发送者,而改用read()、recv()或recvmsg();
    3)由已链接UDP套接字引起的异步错误会返回给它们所在的进程,而未链接UDP套接字不接收任何异步错误。

参考:《UNIX网络编程》。

相关文章
相关标签/搜索