SigPipe Linger Nagle(转载)

SigPipe:

在linux下写socket的程序的时候,如果尝试send到一个disconnected socket上,就会让底层抛出一个SIGPIPE信号。
这个信号的缺省处理方法是退出进程,大多数时候这都不是我们期望的。因此我们需要重载这个信号的处理方法。调用以下代码,即可安全的屏蔽SIGPIPE:
static int
disableSIGPIPE(void)
{
    struct sigaction act, oact;
    act.sa_handler = SIG_IGN;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    act.sa_flags |= SA_RESTART;
    if (sigaction(SIGPIPE, &act, &oact) < 0) {
        ERROR_PRINT_SYSCALL("disable::sigaction");
        return FAILED;
    }
    return SUCCESSFUL;
}


Linger:

当连接中断时,需要延迟关闭(linger)以保证所有数据都被传输,所以需要打开SO_LINGER这个选项
linger的结构在/usr/include/linux/socket.h中定义:

struct linger
{
  int l_onoff;  /* Linger active */
  int l_linger; /* How long to linger */
};


 *  如果l_onoff为0,则延迟关闭特性就被取消。如果非零,则允许套接口延迟关闭。
 *  l_linger字段则指明延迟关闭的时间

int
DisableLinger(void){
struct linger ling = {0, 0};
if (setsockopt(sockFd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)) < 0) {
        ERROR_PRINT_SYSCALL("TCPSocket::disableLinger::setsockopt");
        return FAILED;
    }
    return SUCCESSFUL;
}

Nagle算法

根据创建者John Nagle命名。该算法用于对缓冲区内的一定数量的消息进行自动连接。该处理过程(称为Nagling),通过减少必须发送的封包的数量,提高了网络应用 程序系统的效率。Nagle算法,由Ford Aerospace And Communications Corporation Congestion Control in IP/TCP internetworks(IETF RFC 896)(1984)定义,最初是用于缓冲Ford的私有TCP/IP网络拥塞情况,不过被广泛传播开来。

Nagle的文档定义了一种他称之为小封包问题的解决方法。当某个应用程序每次只产生一字节的数据,就会导致网络由于这样的小封包而过载(该情况通 常被称为“发送端SB窗口并发症”),从而产生该问题。一个源自键盘的单一字符-1字节的数据-可能导致一个41字节的封包被传送,该封包包含了1字节的 有用数据和40字节的头部数据。这种4000%过载的情况,在像APRANET这样只有很轻负载的网络中是可以接受的,但在像Ford这样的负载很重的网 络中,可能强制重传,导致封包丢失,并且通过过度拥挤交换节点和网关降低了传播速度。更进一步,当连接被丢弃时,吞吐量可能被降低。Nagle算法-通常 的实现方法是在一个TCP程序中插入两行代码-在发送方,对标识为没有回应的数据进行缓冲(存储)(这句怪怪的,其实应该是对未发送数据按顺序进行缓冲,在发送时进行拼接)。顺序发送的数据将被保持到接收到被标识数据的回应或者一整包有价值的数据需要被发送。

虽然Nagle算法用于解决Ford网络内产生的问题,但同样的问题也出现在APRANet。通过网络,Nagling被广泛实现,包括 internet,并且产生了巨大的效用-虽然某些时候在高交互性环境如一些C/S情况下不希望进行该处理。在这种情况下,可以通过 TCP_NODELAY套接字选项关闭Nagling。

注:Nagle虽然解决了小封包问题,但也导致了较高的不可预测的延迟,同时降低了吞吐量。


int
TCPSocket::disableNagle(void)
{
    int val = 1;
    if (setsockopt(sockFd, IPPROTO_TCP, TCP_NODELAY, (const void*)&val, sizeof(val)) < 0) {
        ERROR_PRINT_SYSCALL("TCPSocket::disableNagle::setsockopt");
        return FAILED;
    }
    return SUCCESSFUL;
}

http://blog.chinaunix.net/u2/80823/showart_1280185.html
posted @ 2010-10-27 03:53  史莱姆  阅读(360)  评论(0编辑  收藏  举报