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

获取和设置套接字选项   

     在进行网络编程时,经常需要查看或设置套接字的某些特性,例如设置地址复用,读写数据的超时时间,对读缓冲区的大小进行调整等操作。获取套接字选项的设置情况的函数是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("建立套接字错误
");
        return -1;    
    }
     
    /*
     * 先读取缓冲区设置的情况
     * 获得原始发送缓冲区大小
     */
    optlen = sizeof(snd_size);
    err = getsockopt(s, SOL_SOCKET, SO_SNDBUF,&snd_size, &optlen);
    if(err<0){
        printf("获取发送缓冲区大小错误
");
    }   
    /*
     * 打印原始缓冲区设置情况
     */
 
    /*
     * 获得原始接收缓冲区大小
     */
    optlen = sizeof(rcv_size);
    err = getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen);
    if(err<0){
        printf("获取接收缓冲区大小错误
");
    }
     
   printf(" 发送缓冲区原始大小为: %d 字节
",snd_size);
   printf(" 接收缓冲区原始大小为: %d 字节
",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("设置发送缓冲区大小错误
");
    }
 
    /*
     * 设置接收缓冲区大小
     */
    rcv_size = 10*1024;    /* 接收缓冲区大小为8K */
    optlen = sizeof(rcv_size);
    err = setsockopt(s,SOL_SOCKET,SO_RCVBUF, (char *)&rcv_size, optlen);
    if(err<0){
        printf("设置接收缓冲区大小错误
");
    }
 
    /*
     * 检查上述缓冲区设置的情况
     * 获得修改后发送缓冲区大小
     */
    optlen = sizeof(snd_size);
    err = getsockopt(s, SOL_SOCKET, SO_SNDBUF,&snd_size, &optlen);
    if(err<0){
        printf("获取发送缓冲区大小错误
");
    }   
 
    /*
     * 获得修改后接收缓冲区大小
     */
    optlen = sizeof(rcv_size);
    err = getsockopt(s, SOL_SOCKET, SO_RCVBUF,(char *)&rcv_size, &optlen);
    if(err<0){
        printf("获取接收缓冲区大小错误
");
    }
 
    /*
     * 打印结果
     */
    printf(" 发送缓冲区大小为: %d 字节
",snd_size);
    printf(" 接收缓冲区大小为: %d 字节
",rcv_size);
 
    close(s);
    return 0;

} 

运行后的结果如下所示:

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

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

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

参考链接:

http://blog.csdn.net/maopig/article/details/6982457

原文地址:https://www.cnblogs.com/hubavyn/p/4413916.html