您的位置:首页 > 理论基础 > 计算机网络

网络编程--套接字选项(一)

2015-04-10 10:45 148 查看
获取和设置套接字选项

在进行网络编程时,经常需要查看或设置套接字的某些特性,例如设置地址复用,读写数据的超时时间,对读缓冲区的大小进行调整等操作。获取套接字选项的设置情况的函数是getsockopt(),设置套接字选项的函数为setsockopt().这两个函数在调整网络的性能和功能方面起着重要的作用。

1. getsockopt和setsockopt函数的介绍

getsockopt和setsockopt函数原型如下所示:

#include<sys/types.h>
#include<sys/socket.h>
int getsockopt(int s,int level,int optname,void *optval,socklen_t *optlen);
int setsockopt(int s,int level,int optname,const void *optval, socklen_t optlen);


getsockopt和setsockopt的函数定义如下所述:

s: 将要获取或设置的套接字描述符,可以通过socket函数获得。

level:选项所在的协议层。支持的层次有支持的层次有SOL_SOCKET(通用套接字选项)、IPPROTO_TCP(TCP选项),IPPROTO_IP(IP选项)。为了操作套接字层的选项,应该将该层的值设置为SOL_SOCKET.

optname: 选项名。 套接字层用的比较多的选项如SO_RCVBUF(表示接收缓冲区的大小),SO_SNDBUF(表示发送缓冲区的大小)。

optval:操作的内存缓冲区。对于getsockopt函数,指向用于获取返回选项值的缓冲区。对于setsockopt函数,指向设置的参数缓冲区。

optlen: 第四个参数的长度。对于getsockopt函数而言,是一个指向socket_t类型的指针,当用于传入的参数时,表示传入optval的实际长度;当用于传出参数时,表示用于保存optval的最大长度。对于setsockopt函数,optlen表示第四个参数的实际长度。

2. 套接字选项

按照参数选项级别level值的不同,套接字选项大致可以分为一下3类:

通用套接字选项:参数level的值为SOL_SOCKET,用于获取或者设置通用的一些参数,例如接收和发送的缓冲区大小,地址重用(这个设置在服务器程序中经常使用,关于通用套接字的用法,可以参考UNP 7.5小节)等。通用套接字选项是协议无关的。

IP选项: 参数level的值为IPPROTO_IP,用于设置或者获取IP层的参数。选项名为IP_HDRINCL表示在数据中包含IP头部数据,IP_TOS表示服务类型,IP_TTL表示存活时间等。

TCP选项:参数level的值为IPPRPTP_TCP,用于获得或者设置TCP 协议层的一些参数。例如选项名TCP_MAXRT对最大重传时间进行操作,选项名TCP_MAXSEG对最大分片大小进行操作,选项名TCP_KEEPALIVE对保持连接时间进行操作。

3. 代码示例

系统提供的socket缓冲区大小为8K,你可以将之设置为64K,尤其在传输实时视频时。

socket发送数据时候先把数据发送到socket缓冲区中,之后接受函数再从缓冲区中取数据,如果发送端特别快的时候,缓冲区很快就被填满 (socket默认的是1024×8=8192字节),这时候我们应该根据情况设置缓冲区的大小,可以通过setsockopt函数实现

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <assert.h>

int main(int argc,char **argv)
{
int err = -1;        /* 返回值 */
int s = -1;            /* socket描述符 */
int snd_size = 0;   /* 发送缓冲区大小 */
int rcv_size = 0;    /* 接收缓冲区大小 */
socklen_t optlen;    /* 选项值长度 */

/*
* 建立一个TCP套接字
*/
s = socket(PF_INET,SOCK_STREAM,0);
if( s == -1){
printf("建立套接字错误\n");
return -1;
}

/*
* 先读取缓冲区设置的情况
* 获得原始发送缓冲区大小
*/
optlen = sizeof(snd_size);
err = getsockopt(s, SOL_SOCKET, SO_SNDBUF,&snd_size, &optlen);
if(err<0){
printf("获取发送缓冲区大小错误\n");
}
/*
* 打印原始缓冲区设置情况
*/

/*
* 获得原始接收缓冲区大小
*/
optlen = sizeof(rcv_size);
err = getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen);
if(err<0){
printf("获取接收缓冲区大小错误\n");
}

printf(" 发送缓冲区原始大小为: %d 字节\n",snd_size);
printf(" 接收缓冲区原始大小为: %d 字节\n",rcv_size);

/*
* 设置发送缓冲区大小
*/
snd_size = 10*1024;    /* 发送缓冲区大小为8K */
optlen = sizeof(snd_size);
err = setsockopt(s, SOL_SOCKET, SO_SNDBUF, &snd_size, optlen);
if(err<0){
printf("设置发送缓冲区大小错误\n");
}

/*
* 设置接收缓冲区大小
*/
rcv_size = 10*1024;    /* 接收缓冲区大小为8K */
optlen = sizeof(rcv_size);
err = setsockopt(s,SOL_SOCKET,SO_RCVBUF, (char *)&rcv_size, optlen);
if(err<0){
printf("设置接收缓冲区大小错误\n");
}

/*
* 检查上述缓冲区设置的情况
* 获得修改后发送缓冲区大小
*/
optlen = sizeof(snd_size);
err = getsockopt(s, SOL_SOCKET, SO_SNDBUF,&snd_size, &optlen);
if(err<0){
printf("获取发送缓冲区大小错误\n");
}

/*
* 获得修改后接收缓冲区大小
*/
optlen = sizeof(rcv_size);
err = getsockopt(s, SOL_SOCKET, SO_RCVBUF,(char *)&rcv_size, &optlen);
if(err<0){
printf("获取接收缓冲区大小错误\n");
}

/*
* 打印结果
*/
printf(" 发送缓冲区大小为: %d 字节\n",snd_size);
printf(" 接收缓冲区大小为: %d 字节\n",rcv_size);

close(s);
return 0;

}


运行后的结果如下所示:



从结果 看出ubuntu系统默认的发送缓冲区大小:16384字节,接收缓冲区87380字节

但是有个问题我设置的接收和发送缓冲区大小为:10*1024=10240字节,但是实际用getoptsock得到却是20480字节加了一倍。改成其他大小也是都是加倍。

这是由linux内核的算法决定的。

参考链接:

/article/2322061.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: