讨论 Setsockopt选项

http://c.chinaitlab.com/cc/ccjq/200806/752042_3.html

总而言之,如果你肯定能一起发送多个数据集合(例如HTTP响应的头和正文),那么我们建议你设置TCP_CORK选项,这样在这些数据之间不存在延迟。能极大地有益于WWW、FTP以及文件服务器的性能,同时也简化了你的工作。示例代码如下:

intfd, on = 1;
    …
    /* 此处是创建套接字等操作,出于篇幅的考虑省略*/
    …
    setsockopt (fd, SOL_TCP, TCP_CORK, &on, sizeof (on)); /* cork */
    write (fd, …);
    fprintf (fd, …);
    sendfile (fd, …);
    write (fd, …);
    sendfile (fd, …);
    …
    on = 0;
    setsockopt (fd, SOL_TCP, TCP_CORK, &on, sizeof (on)); /* 拔去塞子 */

不幸的是,许多常用的程序并没有考虑到以上问题。例如,Eric Allman编写的sendmail就没有对其套接字设置任何选项。

Apache HTTPD是因特网上最流行的Web服务器,它的所有套接字就都设置了TCP_NODELAY选项,而且其性能也深受大多数用户的满意。这是为什么呢?答案就在于实现的差别之上。由BSD衍生的TCP/IP协议
(值得注意的是FreeBSD)在这种状况下的操作就不同。当在TCP_NODELAY
模式下提交大量小数据块传输时,大量信息将按照一次write()函数调用发送一块数据的方式发送出去。然而,因为负责请求交付确认的记数器是面向字节而
非面向包(在Linux上)的,所以引入延迟的概率就降低了很多。结果仅仅和全部数据的大小有关系。而 Linux
在第一包到达之后就要求确认,FreeBSD则在进行如此操作之前会等待好几百个包。

在Linux系统上,TCP_NODELAY的效果同习惯于BSD TCP/IP协议栈的开发者所期望的效果有很大不同,而且在Linux上的Apache性能表现也会更差些。其他在Linux上频繁采用TCP_NODELAY的应用程序也有同样的问题。

TCP_DEFER_ACCEPT

我们首先考虑的第1个选项是TCP_DEFER_ACCEPT(这是Linux系统上的叫法,其他一些操作系统上也有同样的选项但使用不同的名字)。为了
理解TCP_DEFER_ACCEPT选项的具体思想,我们有必要大致阐述一下典型的HTTP客户/服务器交互过程。请回想下TCP是如何与传输数据的目
标建立连接的。在网络上,在分离的单元之间传输的信息称为IP包(或IP
数据报)。一个包总有一个携带服务信息的包头,包头用于内部协议的处理,并且它也可以携带数据负载。服务信息的典型例子就是一套所谓的标志,它把包标记代
表TCP/IP协议栈内的特殊含义,例如收到包的成功确认等等。通常,在经过“标记”的包里携带负载是完全可能的,但有时,内部逻辑迫使TCP/IP协议
栈发出只有包头的IP包。这些包经常会引发讨厌的网络延迟而且还增加了系统的负载,结果导致网络性能在整体上降低。
   
现在服务器创建了一个套接字同时等待连接。TCP/IP式的连接过程就是所谓“3次握手”。首先,客户程序发送一个设置SYN标志而且不带数据负载的
TCP包(一个SYN包)。服务器则以发出带SYN/ACK标志的数据包(一个SYN/ACK包)作为刚才收到包的确认响应。客户随后发送一个ACK包确
认收到了第2个包从而结束连接过程。在收到客户发来的这个SYN/ACK包之后,服务器会唤醒一个接收进程等待数据到达。当3次握手完成后,客户程序即开
始把“有用的”的数据发送给服务器。通常,一个HTTP请求的量是很小的而且完全可以装到一个包里。但是,在以上的情况下,至少有4个包将用来进行双向传
输,这样就增加了可观的延迟时间。此外,你还得注意到,在“有用的”数据被发送之前,接收方已经开始在等待信息了。
   
为了减轻这些问题所带来的影响,Linux(以及其他的一些操作系统)在其TCP实现中包括了TCP_DEFER_ACCEPT选项。它们设置在侦听套接
字的服务器方,该选项命令内核不等待最后的ACK包而且在第1个真正有数据的包到达才初始化侦听进程。在发送SYN/ACK包之后,服务器就会等待客户程
序发送含数据的IP包。现在,只需要在网络上传送3个包了,而且还显著降低了连接建立的延迟,对HTTP通信而言尤其如此。
    这一选项在好些操作系统上都有相应的对等物。例如,在FreeBSD上,同样的行为可以用以下代码实现:

/* 为明晰起见,此处略去无关代码 */
    struct accept_filter_arg af = { "dataready", "" };
    setsockopt(s, SOL_SOCKET, SO_ACCEPTFILTER, &af, sizeof(af));

这个特征在FreeBSD上叫做“接受过滤器”,而且具有多种用法。不过,在几乎所有的情况下其效果与TCP_DEFER_ACCEPT是一样的:服务器
不等待最后的ACK包而仅仅等待携带数据负载的包。要了解该选项及其对高性能Web服务器的重要意义的更多信息请参考Apache文档上的有关内容。

就HTTP客户/服务器交互而言,有可能需要改变客户程序的行为。客户程序为什么要发送这种“无用的”ACK包呢?这是因为,TCP协议栈无法知道ACK
包的状态。如果采用FTP而非HTTP,那么客户程序直到接收了FTP服务器提示的数据包之后才发送数据。在这种情况下,延迟的ACK将导致客户/服务器
交互出现延迟。为了确定ACK是否必要,客户程序必须知道应用程序协议及其当前状态。这样,修改客户行为就成为必要了。
   
对Linux客户程序来说,我们还可以采用另一个选项,它也被叫做TCP_DEFER_ACCEPT。我们知道,套接字分成两种类型,侦听套接字和连接套
接字,所以它们也各自具有相应的TCP选项集合。因此,经常同时采用的这两类选项却具有同样的名字也是完全可能的。在连接套接字上设置该选项以后,客户在
收到一个SYN/ACK包之后就不再发送ACK包,而是等待用户程序的下一个发送数据请求;因此,服务器发送的包也就相应减少了。

Setsockopt选项的更多相关文章

  1. GNU 网络程序

    ______________________________________________________________________________ | 版权声明 | | 1.本文可以转载.修 ...

  2. capwap学习笔记——初识capwap(四)(转)

    2.5.7 CAPWAP传输机制 WTP和AC之间使用标准的UDP客户端/服务器模式来建立通讯. CAPWAP协议支持UDP和UDP-Lite [RFC3828]. ¢ 在IPv4上,CAPWAP控制 ...

  3. capwap学习笔记——初识capwap(四)

    2.5.7 CAPWAP传输机制 WTP和AC之间使用标准的UDP客户端/服务器模式来建立通讯. CAPWAP协议支持UDP和UDP-Lite [RFC3828]. ¢ 在IPv4上,CAPWAP控制 ...

  4. Windows7/10实现ICMP(ping命令)

    如果觉得本文如果帮到你或者你想转载都可以,只需要标注出处即可.谢谢 利用ICMP数据包.C语言实现Ping命令程序,能实现基本的Ping操作,发送ICMP回显请求报文,用于测试—个主机到只一个主机之间 ...

  5. setsockopt 设置 SO_LINGER 选项

    setsockopt 设置 SO_LINGER 选项 最近和后台的server通信 server发现在读数据的时候  客户端已经关闭连接 ,也就是 没有等服务器读完数据,客户端已经fclose了, 联 ...

  6. 套接字选项——getsockopt和setsockopt

    这两个函数仅用于套接字 #include <sys/socket.h> int getsockopt(int sock, int level, int optname, void *opt ...

  7. setsockopt 设置TCP的选项SO_LINGER

    SO_LINGER选项用来设置延迟关闭的时间,等待套接字发送缓冲区中的数据发送完成. 没有设置该选项时,在调用close()后,在发送完FIN后会立即进行一些清理工作并返回.如果设置了SO_LINGE ...

  8. 设置套接口的选项setsockopt的用法

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  9. socket选项总结(setsockopt)

    功能描述:        获取或者设置与某个套接字关联的选 项.选项可能存在于多层协议中,它们总会出现在最上面的套接字层.当操作套接字选项时,选项位于的层和选项的名称必须给出.为了操作套接字层的选项, ...

随机推荐

  1. Codeforces Round #280 (Div. 2) E. Vanya and Field 思维题

    E. Vanya and Field time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  2. php远程获取图片或文件信息(get_headers,fsocketopen,curl)

    <?php if(!function_exists("remote_filesize")){ /** * 获取远程或本地文件信息 * @param string $strUr ...

  3. 数据库中间件OneProxy and onemysql

    http://blog.itpub.net/28944233/cid-176181-list-1/ http://www.onexsoft.com/ 官网 http://pan.baidu.com/s ...

  4. 在VS 2010上搭建Windows Phone 7开发平台

      如今Windows Phone 7平台越来越火了,刚刚拿到一款新的Windows Phone,于是准备在电脑上搭建WP7的开发环境. 首先,安装VS2010,升级到SP1,并安装Windows P ...

  5. UML九种图 之 用例图和类图

    前言     近期写UML文档,看视频的时候感觉掌握的还能够,当真正写文档的时候才发现不是一件easy的事.写文档自己又翻开自己的笔记看了一遍又一遍. 以下就给大家介绍一下我画的几张图: 用例图   ...

  6. jsp下Kindeditor环境搭建

    1.环境:tomcat 2.需要外部jar包: commons-fileupload-1.2.1.jar commons-io-1.4.jar json_simple-1.1.jar 3.下载Kind ...

  7. javax.mail 遇到501 mail from address must be same as authorization user 的問題

    使用不同的兩個帳戶发送email时,第一个账户可以发送成功,但到第二个账户的时候就报出了501 mail from address must be same as authorization user ...

  8. 利用UIWebView获取userAgent需要注意的地方

    网络通信有时候需要传递参数userAgent,iOS中获取userAgent很简单. UIWebView* webView = [[UIWebView alloc] initWithFrame:CGR ...

  9. 将properties文件放在Jar包并读取

    有时候需要在一个library内部打包一个properties文件,包含一些配置信息,而不能部署在外部. 在maven工程里面,将properties文件放在src/main/resources目录下 ...

  10. D - I Think I Need a Houseboat(1.3.1)

    Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Descr ...