第7章套接字选项

一般通过以下函数设置套接字选项:getsockopt和setsockopt函数;fcntl函数;ioctl函数

 
    
  1. #include <sys/types.h> /* See NOTES */
  2. #include <sys/socket.h>
  3. int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
  4. int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
sockfd指向一套接字描述符,level指定系统解释选项代码,optval是一个指向某个变量的指针,对于setsockopt是一个值参数,对于getsockopt是一个值-结果.

通用套接字选项
SO_KEEPALIVE套接字选项
给TCP套接字设置了keep-alive选项后,2个小时内在该套接字的任何一方都没有数据交换,TCP就自动给对端发送一个存活探测分节.它将导致以下3种情况
(1)对端发送了期待的ACK,应用进程得不到通知(因为一切正常),如果2小时后依旧没有任何动静,TCP就又发送一个探测分节
(2)对端以RST响应,告知本端TCP:对端已经挂了,而且重新启动.该套接字的错误设置为ECONNRESET,套接字本身则被关闭.
(3)对端对保持存活探测分节没有任何响应,TCP将继续发送,直到xx秒就放弃,套接字被设置为ETIMEOUT,套接字本身被关闭.如果套接字收到的是一个icmp错误作为响应,那就返回相应的错误,套接字也被关闭,错误如果是host unreachable,说明对端主机可能没有崩溃,只是不可达.errno被设置为EHOSTUNREACH,原因是网络故障

SO_LINGER套接字选项
这个是对于close函数的操作,一般close立刻返回,默认如果有数据残留在套接字发送缓冲区,系统将尝试把数据发送到对端.
struct linger结构将改变这个默认设置
struct linger{
int l-onoff;
int l_linger;
}
(1)l_onoff只要为0,就是默认设置
(2)l_onoff非0但linger为0,当close后,将丢弃保存在该套接字发送缓冲区的任何数据,并且发送RST给对方,而且一般没有四分组连接终止序列.这样一来可以避免tcp的time_wait状态
(3)如果l_onoff为非0值且l_linger也为非0值,那么套接字关闭时,内核将拖延一段时间.这就是说如果套接字缓冲区还有数据,进程将被死命,直到数据被发送完,且收到ack或者时间超时.,应用进程检查close的返回值非常重要,如果是时间到了.那就返回EWOULDBLOCK错误,而且套接字缓冲区的数据都被丢弃
836125-20160810005634246-600837433.png
 
836125-20160810005636184-648054830.png
 
836125-20160810005639231-1537521457.png
  836125-20160810005641168-312483629.png
 

836125-20160810005643559-2050549954.png

TCP_NODELAY套接字选项
开启该选项将禁止TCP的Nagle算法,Nagle算法的作用是在某一个时刻减少广域网的小分组的数目,比如某个给定的连接有待确定的数据,那么原本应该作为用户写操作的响应在该连接立刻发送小分组的行为就不会发生了,直到数据被确认为止
836125-20160810005646184-1109454352.png
一般Nagle算法常常跟其他TCP算法联合使用:ACK延迟算法, ACK延迟算法使得TCP在接收到数据后不立刻发送ACK,而是等待一小段时间,然后才发送ACK,
TCP期待在这一小段时间内自身有数据发送回对端,被延迟的Ack就可以被这些数据捎带,从而省掉一个TCP分节。
这样对于telnet客户来说是可以的,因为他们的服务器一般都回显客户端发来的每个字节,这样对客户端字符的ack完全可以在服务端回显字符捎带返回
弊端:然而对于其服务器不在回显内容以便携带ACK的客户来说,ack延迟算法存在问题,这些客户可能觉察到明显的延迟,因为客户TCP要等到服务器的ack延迟定时超时才继续给服务端发送数据。这些客户端需要禁止Nagle算法。TCP_NODELAY就起到这个作用。
另外一类不适合使用Nagle算法跟TCP的ack延迟算法的客户是以小片数据发送。不适用于write-write-read这种方式。http://www.blogjava.net/killme2008/archive/2011/06/30/353441.html
解决方式:
(1)首选使用writev而不是两次调用write,对于本例,单个writev调用最终导致调用tcp输出功能一次而不是两次,结果只是产生一个tcp分节
 (2)把前4个字节跟后396个自己的数据复制到单个缓冲区中,然后对该缓冲区电泳一次write
(3)设置TCP_NODELAY套接字选项,继续调用write两次,这是最不可取的方法,而且有损于网络


 



 
 









转载于:https://www.cnblogs.com/zengyiwen/p/5755217.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值