zoukankan      html  css  js  c++  java
  • 网络编程--套接字选项(一)

    获取和设置套接字选项   

         在进行网络编程时,经常需要查看或设置套接字的某些特性,例如设置地址复用,读写数据的超时时间,对读缓冲区的大小进行调整等操作。获取套接字选项的设置情况的函数是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

  • 相关阅读:
    IO学习BufferedWriter 规格严格
    Finalization 规格严格
    linux下查看主板内存槽与内存信息 规格严格
    调试JavaScript/VB Script脚本程序(Wscript篇) 规格严格
    ORA01688:unable to extend table name。name partition NAME by NUM in tablespace NAME 规格严格
    Hidden Java 7 Features – SecondaryLoop 规格严格
    Web应用服务器监控 规格严格
    NetBeans 时事通讯(刊号 # 12 Jun 16, 2008)
    NetBeans 时事通讯(刊号 # 12 Jun 16, 2008)
    Win32 DLL的一个调试心得
  • 原文地址:https://www.cnblogs.com/hubavyn/p/4413916.html
Copyright © 2011-2022 走看看