套接字选项的获取和设置

套接字有很多的选项需要设置,同时也需要获取套接字的一些状态信息,一般用getsocketopt和setsocketopt执行这些操作

getsockopt

头文件

int getsocketopt(int sockfd, int level, int optname, void *opval, socketlen_t *oplen);

getsocket函数把获取的信息存到opval和oplen中

socket:文件描述符
level:协议层次
            SOL_SOCKET 套接字层次
            IPPROTO_IP ip层次
            IPPROTO_TCP TCP层次

optname:选项的名称

返回值:
    成功:0
    失败:-1

setsockopt

头文件

int setsocketopt(int sockfd, int level, int optname, void *opval, socketlen_t oplen);

setsockopt把要设置的信息通过opval和oplen进行传送

重要的几个套接字选项:

SO_KEEPALIVE

SO_KEEPALIVE的开启代码:

int KeepAlive = 1;
setsocketopt(fd, SOL_SOCKET, SO_KEEPALIVE,(void *)&KeepAlive,sizeof(KeepAlive));

SO_KEEPALIVE的关闭代码:

int KeepAlive = 0;
setsocketopt(fd, SOL_SOCKET, SO_KEEPALIVE,(void *)&KeepAlive,sizeof(KeepAlive));

 SO_KEEPALIVE的状态获取代码:

int KeepAlive, len;
getsocketopt(fd, SOL_SOCKET, SO_KEEPALIVE,(void *)&KeepAlive,&len);

给一个套接字开启保活选项后,如果2小时内该套接字的任意一个方向都没有数据交换,则TCP就会给对端发送一个保持存活探测分节,这时一个对端必须响应的分节,它会导致以下三种情况之一:

  1. 对端以期待的ACK响应,表示对端状态正常。
  2. 对端以RST响应,表示对端已经奔溃并重新启动。返回RST后,errno被设为ECONNRESET,并且套接字被关闭
  3. 对端不回应。每隔75秒就重新发送一个新的分节,从第一个分节发出后11分15秒如果都没有回应,则关闭连接,errno被设为ETIMEOUT。如果套接字收到一个ICMP错误作为某个分节的响应,那就返回响应的错误,并关闭套接字。   注意:如果返回的ICMP错误是主机不可达,则errno被设为 EHOSTUNREACH。这种情况可能是网络故障、或者对端主机奔溃。

TCP_NODELAY

TCP_NODELAY的开启代码:

int KeepNoDelay = 1;
setsocketopt(fd, IPPROTO_TCP, TCP_NODELAY,(void *)&KeepNoDelay ,sizeof(KeepNoDelay));

TCP_NODELAY的关闭代码

​int KeepNoDelay = 0;
setsocketopt(fd, IPPROTO_TCP, TCP_NODELAY,(void *)&KeepNoDelay ,sizeof(KeepNoDelay));

 SO_KEEPALIVE的状态获取代码:

int KeepNoDelay, len;
getsocketopt(fd, IPPROTO_TCP, TCP_NODELAY,(void *)&KeepNoDelay ,&len);

Nagle算法:如果在某个连接上有待确认的数据,那么该连接上的小分组(小于MSS的分组)就不会被发送。该算法可以减少小分组的数量,从而尽可能发送大分组。

ACK延滞算法:TCP在接收到数据后不立即发送ACK,而是的等待一小段时间(50-200ms), 再发送ACK。该算法期待这一小段时间可以等到一段需要发送的数据,从而提高效率。

这两个算法一般联合使用。

开启TCP_NODELAY将关闭Nagle算法,反之开启。

 

SO_RCVBUF

设置接收缓冲区的大小

int setbuf=80000;
socklen_t len1=sizeof(setbuf);
setsockopt(listenfd,SOL_SOCKET,SO_RCVBUF,(void *)&setbuf,len1);

获取接收缓冲区的大小

getsockopt(listenfd,SOL_SOCKET,SO_RCVBUF,(void *)&buf_len,&len);

SO_SNDBUF

设置发送缓冲区的大小

int setbuf=80000;
socklen_t len1=sizeof(setbuf);
setsockopt(listenfd,SOL_SOCKET,SO_SNDBUF,(void *)&setbuf,len1);

获取发送缓冲区的大小

getsockopt(listenfd,SOL_SOCKET,SO_SNDBUF,(void *)&buf_len,&len);

 TCP的套接字接收缓冲区不可能溢出,因为不允许对端发出超过本端所通告的接收缓冲区大小的数据。如果对端无视接收缓冲区大小而发出了超过接收缓冲区大小的数据,本段TCP将丢弃这些数据。

UDP没有流量控制,当接收到的数据超过接收缓冲区的大小,这些数据将被丢弃。

对于TCP而言,接收缓冲区的大小需要在connect函数(客户端)或者accept函数(服务端)被调用前设置。

给已连接的套接字设定接收缓冲区的大小可能不会起作用。

发送缓冲区和接收缓冲区的大小应该至少是MSS值的四倍(一般都是偶数倍),典型的MSS值为512或1460

缓冲区的大小设定为带宽延迟积(带宽*RTT)时,效率最高

你可能感兴趣的:(计算机网络)