socket 选项 详细说明

下面的两个函数主要是用于设置socket文件描述符属性的方法


getsockopt 和setsockopt这两个函数成功时返回0,失败时返回-1并设置errno ,可以使用 strerror(errno) 将错误码转换为对应的提示消息。

例子如下

/*查询和设置接收缓冲区*/
int recvbuf = 0;
int len = sizeof( recvbuf );
getsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len);
DC_INFO( "the receive buffer size before settting is %d", recvbuf );

recvbuf = size;
if(0 != setsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf) ))
{
	DC_ERROR("setsockopt SO_RCVBUF error ,errmsg = %s",strerror(errno));
	return SERVER_ERROR;
}

下面进行一些详细介绍

1.对于服务器而言,有部分socket选项只能在listen前针对监听socket设置才有效!这是因为连接socket只能由accept调用返回,而accept从listen监听队列中接受的连接至少已经完成了TCP三次握手的前两个步骤(因为listen监听队列中的连接至少已进入SYN_RCVD状态),这说明服务器已经往被接收连接上发出了TCP同步报文段。但有的socket选项却应该在TCP同步报文段中设置,比如TCP最大报文选项!对应的解决方案是:对监听socket设置这些socket选项,那么accept返回的连接socket将自动继承这些选项!


  这些选项包括SO_DEBUG,SO_DONTROUTE,SO_LINGER,SO_OOBINLINE,SO_RCVBUF,SO_RCVLOWAT,SO_SNDBUF,SO_SNDLOWAT,TCP_MAXSEG和TCP_NODELAY。而对于客户端而言,这些socket必须在connect之前设置,因为connect调用成功之后 tcp的三次握手已经完成了!

2.SO_REUSEADDR选项

tcp服务器连接的TIME_WAIT状态,可以通过设置该选项是的绑定的socket地址立即被重用!


此外还有个另外的方式,修改内核参数 /proc/sys/net/ipv4/tcp_tw_recycle 来快速回收被关闭的socket ,从而使得tcp连接国标不会进入TIME_WAIT状态,进而使得程序可以立即重用本地的socket地址!

3.SO_RCVBUF 和SO_SNDBUF

这两个选项分别表示TCP接收缓冲区和发送缓冲区的大小!


不过当我们通过setsockopt来设置tcp的接受和发送缓冲区大小的时候,系统会将其值加倍,并且不得小于某个最小值,同时也不得超过最大值!不过每个系统值可能有不同的默认值!

此外我们还可以直接修改内核参数 /proc/sys/net/ipv4/tcp_rmem 和/proc/sys/net/ipv4/tcp_wmem 来强制修改tcp接收和发送缓冲区的限制!

代码如下

int SocketServer::make_socket_buffsize(int sock,int size)
{
	/*查询和设置接收缓冲区*/
	int recvbuf = 0;
	int len = sizeof( recvbuf );
	getsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len);
    DC_INFO( "the receive buffer size before settting is %d", recvbuf );
	
	recvbuf = size;
    if(0 != setsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf) ))
	{
		DC_ERROR("setsockopt SO_RCVBUF error ,errmsg = %s",strerror(errno));
		return SERVER_ERROR;
	}
	getsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len);
    DC_INFO( "the receive buffer size after settting is %d", recvbuf );
	
	/*查询和设置发送缓冲区*/
	int sendbuf = 0;
	getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, ( socklen_t* )&len);
    DC_INFO( "the tcp send buffer size before setting is %d", sendbuf );
	
	sendbuf = size;
    if(0 != setsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof( sendbuf) ))
	{
		DC_ERROR("setsockopt SO_SNDBUF error ,errmsg = %s",strerror(errno));
		return SERVER_ERROR;
	}
	getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, ( socklen_t* )&len);
    DC_INFO( "the tcp send buffer size after setting is %d", sendbuf );
	return SERVER_OK;
}

设置之后的最大值一般就是默认一次可以读取的字节数!

4.SO_RCVLOWAT 和SO_SNDLOWAT 选项

这两个选项分别表示tcp接受和发送缓冲区的低水位标志。它们一般被I/O复用系统调用来判断socket是否可读或可写。

当tcp接收缓冲区中可读数据的总数大于低水位标记时,I/O系统调用将通知应用程序可以从对于的socket读取数据,当TCP发送缓冲区中的空闲空间大于其低水位,将通知应用程序可以往对应的socket上写数据。

默认情况下,这两个选项均为1字节!

5.SO_LINGER 

此选项指定函数close对面向连接的协议如何操作(如TCP)。内核缺省close操作是立即返回,如果有数据残留在套接口缓冲区中则系统将试着将这些数据发送给对方。

struct linger 
{
     int l_onoff; /* 0 = off, nozero = on */
     int l_linger; /* linger time */
};
有下列三种情况:
1、设置 l_onoff为0,则该选项关闭,l_linger的值被忽略,等于内核缺省情况,close调用会立即返回给调用者,如果可能将会传输任何未发送的数据;
2、设置 l_onoff为非0,l_linger为0,close系统调用立即返回,TCP将丢弃保留在套接口发送缓冲区中的任何数据并发送一个RST给对方。
3、设置 l_onoff 为非0,l_linger为非0,此时的close的行为取决两个条件:一是被关闭的socket对应的TCP发送缓冲区是否还有残留的数据;二是该socket是阻塞的还是非阻塞的。对于阻塞的socket,close将等到l_linge的时间,直到tcp模块发送完所有残留数据并得到对方的确认。如果这段时间tcp没有发送完残留的数据,那么close将返回-1,并将errno设置为EWOULDBLOCK。如果该socket是非阻塞的,close将立即返回,此时我们需要根据返回值和errno来判断残留数据是否已经发送完毕!
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值