??xml version="1.0" encoding="utf-8" standalone="yes"?> int setsockopt( s(套接?: 指向一个打开的套接口描述?
SOCKET s,
int level,
int optname,
const char* optval,
int optlen
);
level:(U别)Q?#160;指定选项代码的类型?
SOL_SOCKET: 基本套接?#160;
IPPROTO_IP: IPv4套接?#160;
IPPROTO_IPV6: IPv6套接?#160;
IPPROTO_TCP: TCP套接?#160;
optname(选项?Q?#160;选项名称
optval(选项?: 是一个指向变量的指针 cdQ整形,套接口结构, 其他l构cd:linger{}, timeval{ }
optlen(选项长度) Qoptval 的大?#160;
q回|标志打开或关闭某个特征的二进刉项
[/code:1:59df4ce128]
========================================================================
SOL_SOCKET
------------------------------------------------------------------------
SO_BROADCAST 允许发送广播数?#160;int
适用?#160;UDP socket。其意义是允?#160;UDP socket 「广播」(broadcastQ讯息到|\上?
SO_DEBUG 允许调试 int
SO_DONTROUTE 不查找\?#160;int
SO_ERROR 获得套接字错?#160;int
SO_KEEPALIVE 保持q接 int
对方主机是否崩溃,避免Q服务器Q永q阻塞于TCPq接的输入?#160;讄该选项后,如果2时内在此套接口的Q一方向都没有数据交换,TCPp动给Ҏ 发一个保持存zL分?keepalive probe)。这是一个对方必d应的TCP分节.它会D以下三种情况Q?#160;Ҏ接收一切正常:以期望的ACK响应?时后,TCP发出另一个探分节?#160;Ҏ已崩溃且已重新启动:以RST响应。套接口的待处理错误被置为ECONNRESETQ套?#160;口本w则被关闭?#160;Ҏ无Q何响应:源自berkeley的TCP发送另?个探分节,盔R75U一个,试图得到 一个响应。在发出W一个探分?1分钟15U后若仍无响应就攑ּ。套接口的待处理?#160;误被|ؓETIMEOUTQ套接口本n则被关闭。如ICMP错误?#8220;host unreachable(L?#160;可达)”Q说明对方主机ƈ没有崩溃Q但是不可达Q这U情况下待处理错误被|ؓ EHOSTUNREACH?#160;
SO_DONTLINGER 若ؓ真,则SO_LINGER选项被禁止?
SO_LINGER 延迟关闭q接 struct linger
上面q两个选项影响close行ؓ
选项 间隔 关闭方式 {待关闭与否
SO_DONTLINGER 不关?#160;优雅 ?
SO_LINGER ?#160;强制 ?
SO_LINGER 非零 优雅 ?
若设|了SO_LINGERQ亦即lingerl构中的l_onoff域设为非Ӟ参见2.4Q?.1.7?.1.21各节Q,q设|了零超旉隔,则closesocket()不被d立即执行Q不论是否有排队数据未发送或未被认。这U关闭方式称?#8220;强制”?#8220;失效”关闭Q因为套接口的虚电\立即被复位,且丢׃未发送的数据。在q端的recv()调用以WSAECONNRESET出错?
若设|了SO_LINGERq确定了非零的超旉隔,则closesocket()调用dq程Q直到所剩数据发送完毕或时。这U关闭称?#8220;优雅?#8221;关闭。请注意如果套接口置为非d且SO_LINGER设ؓ非零时Q则closesocket()调用以WSAEWOULDBLOCK错误q回?
若在一个流cd接口上设|了SO_DONTLINGERQ也是说将lingerl构的l_onoff域设为零Q参?.4Q?.1.7Q?.1.21节)Q则closesocket()调用立即q回。但是,如果可能Q排队的数据在套接口关闭前发送。请注意Q在q种情况下WINDOWS套接口实现将在一D不定的时间内保留套接口以及其他资源,q对于想用所以套接口的应用程序来说有一定媄响?
SO_OOBINLINE 带外数据攑օ正常数据?在普通数据流中接收带外数?#160;int
SO_RCVBUF 接收~冲区大?#160;int
讄接收~冲区的保留大小
?#160;SO_MAX_MSG_SIZE 或TCP滑动H口无关Q如果一般发送的包很大很频繁Q那么用这个选项
SO_SNDBUF 发送缓冲区大小 int
讄发送缓冲区的保留大?
?#160;SO_MAX_MSG_SIZE 或TCP滑动H口无关Q如果一般发送的包很大很频繁Q那么用这个选项
每个套接口都有一个发送缓冲区和一个接收缓冲区?#160;接收~冲TCP和UDP用来接收到的数据一直保存到由应用进E来诅R?#160;TCPQTCP通告另一端的H口大小?#160;TCP套接口接收缓冲区不可能溢出,因ؓҎ不允许发q所通告H口大小的数据?#160;q就是TCP的流量控Ӟ如果Ҏ无视H口大小而发Z过宙口大小的数据,则接 收方TCP丢弃它?#160;UDPQ当接收到的数据报装不进套接口接收缓冲区Ӟ此数据报p丢弃。UDP是没?#160;量控制的;快的发送者可以很Ҏ地就Ҏ慢的接收者,D接收方的UDP丢弃数据报?
SO_RCVLOWAT 接收~冲Z?#160;int
SO_SNDLOWAT 发送缓冲区下限 int
每个套接口都有一个接收低潮限度和一个发送低潮限度。它们是函数selectt使用的, 接收低潮限度是让selectq回“可读”而在套接口接收缓冲区中必L的数据总量?#160;——对于一个TCP或UDP套接口,此值缺省ؓ1。发送低潮限度是让selectq回“可写” 而在套接口发送缓冲区中必L的可用空间。对于TCP套接口,此值常~省?048?#160;对于UDP使用低潮限度Q?#160;׃其发送缓冲区中可用空间的字节数是从不变化的,只要 UDP套接口发送缓冲区大小大于套接口的低潮限度Q这LUDP套接口就L可写的?#160;UDP没有发送缓冲区Q只有发送缓冲区的大?
SO_RCVTIMEO 接收时 struct timeval
SO_SNDTIMEO 发送超?#160;struct timeval
SO_REUSERADDR 允许重用本地地址和端?#160;int
充许l定已被使用的地址Q或端口PQ可以参考bind的man
SO_EXCLUSIVEADDRUSE
独占模式使用端口,是不充许和其它E序使用SO_REUSEADDR׃n的用某一端口?
在确定多重绑定用谁的时候,Ҏ一条原则是谁的指定最明确则将包递交l谁Q而且没有权限之分Q也是说低U权限的用户是可以重l定在高U权限如服务启动的端口上?q是非常重大的一个安全隐?
如果不想让自q序被监听Q那么用这个选项
SO_TYPE 获得套接字类?#160;int
SO_BSDCOMPAT 与BSDpȝ兼容 int
==========================================================================
IPPROTO_IP
--------------------------------------------------------------------------
IP_HDRINCL 在数据包中包含IP首部 int
q个选项常用于黑客技术中Q隐藏自qIP地址
IP_OPTINOS IP首部选项 int
IP_TOS 服务cd
IP_TTL 生存旉 int
以下IPV4选项用于l播
IPv4 选项 数据cd ?#160;q?
IP_ADD_MEMBERSHIP struct ip_mreq 加入到组播组?
IP_ROP_MEMBERSHIP struct ip_mreq 从组播组中退?
IP_MULTICAST_IF struct ip_mreq 指定提交l播报文的接?
IP_MULTICAST_TTL u_char 指定提交l播报文的TTL
IP_MULTICAST_LOOP u_char 使组播报文环路有效或无效
在头文g中定义了ip_mreql构Q?
[code:1:63724de67f]
struct ip_mreq {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};
[/code:1:63724de67f]
若进E要加入C个组播组中,用soket的setsockopt()函数发送该选项。该选项cd是ip_mreql构Q它的第一个字Dimr_multiaddr指定了组播组的地址Q第二个字段imr_interface指定了接口的IPv4地址?
IP_DROP_MEMBERSHIP
该选项用来从某个组播组中退出。数据结构ip_mreq的用方法与上面相同?
IP_MULTICAST_IF
该选项可以修改|络接口Q在l构ip_mreq中定义新的接口?
IP_MULTICAST_TTL
讄l播报文的数据包的TTLQ生存时_。默认值是1Q表C数据包只能在本地的子网中传送?
IP_MULTICAST_LOOP
l播l中的成员自׃会收到它向本l发送的报文。这个选项用于选择是否Ȁz这U状态?br>
无双 回复于:2003-05-08
21:21:52
IPPRO_TCP
--------------------------------------------------------------------------
TCP_MAXSEG TCP最大数据段的大?#160;int
获取或设|TCPq接的最大分节大?MSS)。返回值是我们的TCP发送给另一端的最?#160;数据量,它常常就是由另一端用SYN分节通告的MSSQ除非我们的TCP选择使用一个比 Ҏ通告的MSS些的倹{如果此值在套接口连接之前取得,则返回gؓ未从?#183;—端 收到Mss选项的情况下所用的~省倹{小于此q回值的信可能真正用在连接上Q因 如说使用旉戳选项的话Q它在每个分节上占用12字节的TCP选项定w。我们的TcP?#160;发送的每个分节的最大数据量也可在连接存zL内改变,但前提是TCP要支持\径MTU 发现功能。如果到Ҏ的\径改变了Q此值可上下调整?
TCP_NODELAY 不用Nagle法 int
指定TCP开始发送保持存zL分节前以秒为单位的q接I闲旉。缺省D必Mؓ7200U,?时。此选项仅在SO_KEPALIVEE套接口选项打开时才有效?
TCP_NODELAY ?#160;TCP_CORKQ?
q两个选项都对|络q接的行为具有重要的作用。许多UNIXpȝ都实CTCP_NODELAY选项Q但是,TCP_CORK则是Linuxpȝ所独有的而且相对较新Q它首先在内核版?.4上得以实现。此外,其他UNIXpȝ版本也有功能cM的选项Q值得注意的是Q在某种由BSDz的系l上的TCP_NOPUSH选项其实是TCP_CORK的一部分具体实现?
TCP_NODELAY和TCP_CORK基本上控制了包的“Nagle?#8221;QNagle化在q里的含义是采用Nagle法把较的包组装ؓ更大的。John Nagle是Nagle法的发明hQ后者就是用他的名字来命名的Q他?984q首ơ用q种Ҏ来尝试解决福Ҏ车公司的|络拥塞问题Q欲了解详情请参看IETF RFC 896Q。他解决的问题就是所谓的silly window syndrome Q中文称“愚蠢H口症候群”Q具体含义是Q因为普遍终端应用程序每产生一ơ击键操作就会发送一个包Q而典型情况下一个包会拥有一个字节的数据载荷以及40个字节长的包_于是产生4000%的过载,很轻易地p令网l发生拥??#160;Nagle化后来成了一U标准ƈ且立卛_因特|上得以实现。它现在已经成ؓ~省配置了,但在我们看来Q有些场合下把这一选项x也是合乎需要的?
现在让我们假设某个应用程序发Z一个请求,希望发送小块数据。我们可以选择立即发送数据或者等待生更多的数据然后再一ơ发送两U策略。如果我们马上发送数据,那么交互性的以及客户/服务器型的应用程序将极大地受益。例如,当我们正在发送一个较短的hq且{候较大的响应Ӟ相关q蝲与传输的数据总量相比׃比较低,而且Q如果请求立卛_出那么响应时间也会快一些。以上操作可以通过讄套接字的TCP_NODELAY选项来完成,q样q用了Nagle法?
另外一U情况则需要我们等到数据量辑ֈ最大时才通过|络一ơ发送全部数据,q种数据传输方式有益于大量数据的通信性能Q典型的应用是文g服务器。应用Nagle法在这U情况下׃产生问题。但是,如果你正在发送大量数据,你可以设|TCP_CORK选项用Nagle化,其方式正好同TCP_NODELAY相反QTCP_CORK ?#160;TCP_NODELAY 是互相排斥的Q。下面就让我们仔l分析下其工作原理?
假设应用E序使用sendfile()函数来{Ud量数据。应用协议通常要求发送某些信息来预先解释数据Q这些信息其实就是报头内宏V典型情况下报头很小Q而且套接字上讄了TCP_NODELAY。有报头的包被立即传输Q在某些情况下(取决于内部的包计数器Q,因ؓq个包成功地被对Ҏ到后需要请求对方确认。这P大量数据的传输就会被推迟而且产生了不必要的网l流量交换?
但是Q如果我们在套接字上讄了TCP_CORKQ可以比Mؓ在管道上插入“塞子”Q选项Q具有报头的包就会填补大量的数据Q所有的数据都根据大自动地通过包传输出厅R当数据传输完成Ӟ最好取消TCP_CORK 选项讄l连?#8220;拔去塞子”以便M部分的都能发送出厅R这?#8220;塞住”|络q接同等重要?
总而言之,如果你肯定能一起发送多个数据集合(例如HTTP响应的头和正文)Q那么我们徏议你讄TCP_CORK选项Q这样在q些数据之间不存在gq。能极大地有益于WWW、FTP以及文g服务器的性能Q同时也化了你的工作。示例代码如下:
intfd, on = 1;
…
/* 此处是创建套接字{操作,Z幅的考虑省略*/
…
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)); /* 拔去塞子 */
不幸的是Q许多常用的E序q没有考虑C上问题。例如,Eric Allman~写的sendmail没有对其套接字讄M选项?
Apache HTTPD是因特网上最行的Web服务器,它的所有套接字都讄了TCP_NODELAY选项Q而且其性能也深受大多数用户的满意。这是ؓ什么呢Q答案就在于实现的差别之上。由BSD衍生的TCP/IP协议栈(值得注意的是FreeBSDQ在q种状况下的操作׃同。当在TCP_NODELAY 模式下提交大量小数据块传输时Q大量信息将按照一ơwrite()函数调用发送一块数据的方式发送出厅R然而,因ؓ负责h交付认的记数器是面向字节而非面向包(在Linux上)的,所以引入gq的概率降低了很多。结果仅仅和全部数据的大有关系。?#160;Linux 在第一包到达之后就要求认QFreeBSD则在q行如此操作之前会等待好几百个包?
在Linuxpȝ上,TCP_NODELAY的效果同习惯于BSD TCP/IP协议栈的开发者所期望的效果有很大不同Q而且在Linux上的Apache性能表现也会更差些。其他在Linux上频J采用TCP_NODELAY的应用程序也有同L问题?
TCP_DEFER_ACCEPT
我们首先考虑的第1个选项是TCP_DEFER_ACCEPTQ这是Linuxpȝ上的叫法Q其他一些操作系l上也有同样的选项但用不同的名字Q。ؓ了理解TCP_DEFER_ACCEPT选项的具体思想Q我们有必要大致阐述一下典型的HTTP客户/服务器交互过E。请回想下TCP是如何与传输数据的目标徏立连接的。在|络上,在分ȝ单元之间传输的信息称为IP包(或IP 数据报)。一个包L一个携带服务信息的包头Q包头用于内部协议的处理Qƈ且它也可以携带数据负载。服务信息的典型例子是一套所谓的标志Q它把包标记代表TCP/IP协议栈内的特D含义,例如收到包的成功认{等。通常Q在l过“标记”的包里携带负载是完全可能的,但有Ӟ内部逻辑qTCP/IP协议栈发出只有包头的IP包。这些包l常会引发讨厌的|络延迟而且q增加了pȝ的负载,l果D|络性能在整体上降低?
现在服务器创Z一个套接字同时{待q接。TCP/IP式的q接q程是所?#8220;3ơ握?#8221;。首先,客户E序发送一个设|SYN标志而且不带数据负蝲的TCP包(一个SYN包)。服务器则以发出带SYN/ACK标志的数据包Q一个SYN/ACK包)作ؓ刚才收到包的认响应。客户随后发送一个ACK包确认收CW?个包从而结束连接过E。在收到客户发来的这个SYN/ACK包之后,服务器会唤醒一个接收进E等待数据到达。当3ơ握手完成后Q客L序即开始把“有用?#8221;的数据发送给服务器。通常Q一个HTTPh的量是很的而且完全可以装到一个包里。但是,在以上的情况下,臛_?个包用来进行双向传输,q样增加了可观的gq时间。此外,你还得注意到Q在“有用?#8221;数据被发送之前,接收方已l开始在{待信息了?
Z减轻q些问题所带来的媄响,LinuxQ以及其他的一些操作系l)在其TCP实现中包括了TCP_DEFER_ACCEPT选项。它们设|在侦听套接字的服务器方Q该选项命o内核不等待最后的ACK包而且在第1个真正有数据的包到达才初始化侦听q程。在发送SYN/ACK包之后,服务器就会等待客L序发送含数据的IP包。现在,只需要在|络上传?个包了,而且q显著降低了q接建立的gq,对HTTP通信而言其如此?
q一选项在好些操作系l上都有相应的对{物。例如,在FreeBSD上,同样的行为可以用以下代码实现Q?
/* 为明晰v见,此处略去无关代码 */
struct accept_filter_arg af = { "dataready", "" };
setsockopt(s, SOL_SOCKET, SO_ACCEPTFILTER, &af, sizeof(af));
q个特征在FreeBSD上叫?#8220;接受qo?#8221;Q而且h多种用法。不q,在几乎所有的情况下其效果与TCP_DEFER_ACCEPT是一LQ服务器不等待最后的ACK包而仅仅等待携带数据负载的包。要了解该选项及其寚w性能Web服务器的重要意义的更多信息请参考Apache文档上的有关内容?
HTTP客户/服务器交互而言Q有可能需要改变客L序的行ؓ。客L序ؓ什么要发送这U?#8220;无用?#8221;ACK包呢Q这是因为,TCP协议栈无法知道ACK包的状态。如果采用FTP而非HTTPQ那么客L序直到接收了FTP服务器提C的数据包之后才发送数据。在q种情况下,延迟的ACK导致客?服务器交互出现gq。ؓ了确定ACK是否必要Q客L序必ȝ道应用程序协议及其当前状态。这P修改客户行ؓ成为必要了?
对Linux客户E序来说Q我们还可以采用另一个选项Q它也被叫做TCP_DEFER_ACCEPT。我们知道,套接字分成两U类型,侦听套接字和q接套接字,所以它们也各自h相应的TCP选项集合。因此,l常同时采用的这两类选项却具有同L名字也是完全可能的。在q接套接字上讄该选项以后Q客户在收到一个SYN/ACK包之后就不再发送ACK包,而是{待用户E序的下一个发送数据请求;因此Q服务器发送的包也q应减了?
TCP_QUICKACK
L因发送无用包而引发gq的另一个方法是使用TCP_QUICKACK选项。这一选项?#160;TCP_DEFER_ACCEPT不同Q它不但能用作管理连接徏立过E而且在正常数据传输过E期间也可以使用。另外,它能在客?服务器连接的M一方设|。如果知道数据不久即发送,那么推迟ACK包的发送就会派上用场,而且最好在那个携带数据的数据包上设|ACK 标志以便把网l负载减到最。当发送方肯定数据被立即发送(多个包)ӞTCP_QUICKACK选项可以讄?。对处于“q接”状态下的套接字该选项的缺省值是1Q首ơ用以后内核将把该选项立即复位?Q这是个一ơ性的选项Q?
在某些情形下Q发出ACK包则非常有用。ACK包将认数据块的接收Q而且Q当下一块被处理时不至于引入延迟。这U数据传输模式对交互q程是相当典型的Q因为此cL况下用户的输入时L法预。在Linuxpȝ上这是~省的套接字行ؓ?
在上q情况下Q客L序在向服务器发送HTTPhQ而预先就知道h包很短所以在q接建立之后应该立卛_送,q可谓HTTP的典型工作方式。既然没有必要发送一个纯_的ACK包,所以设|TCP_QUICKACK?以提高性能是完全可能的。在服务器方Q这两种选项都只能在侦听套接字上讄一ơ。所有的套接字,也就是被接受呼叫间接创徏的套接字则会l承原有套接字的所有选项?
通过TCP_CORK、TCP_DEFER_ACCEPT和TCP_QUICKACK选项的组合,参与每一HTTP交互的数据包数量被降低到最的可接受水qIҎTCP协议的要求和安全斚w的考虑Q。结果不仅是获得更快的数据传输和h处理速度而且q客户/服务器双向gq实C最化?