《TCP/IP网络编程》阅读笔记--getsockopt和setsockopt的使用

目录

1--Socket的多种可选项

2--getsocketopt()

3--setsockopt()

4--代码实例


1--Socket的多种可选项

        Socket 拥有多种可选项,其可分为 SOL_SOCKET 层,IPPROTO_IP 层和IPPROTO_TCP 层等,一般通过 getsocketopt() 和 setsockopt() 函数进行获取和设置;

2--getsocketopt()

#include <sys/socket.h>
int getsockopt(int sock, int level, int optname, void* optval, socklen_t* optlen);
// 成功时返回 0,失败时返回 -1
// sock 用于查看选项 socket 的文件描述符
// level 表示要查看的可选项的协议层
// optname 表示要查看的可选项名
// optval 表示保存查看结果的缓冲地址值
// optlen 表示向第四个参数 optval 传递的缓冲大小,调用函数后,该变量中保存通过第四个参数返回的可选项信息的字节数

3--setsockopt()

#include <sys/socket.h>
int setsockopt(int sock, int level, int optname, const void* optval, socklen_t optlen);
// 成功时返回 0,失败时返回 -1
// sock 用于更改可选项 socket 的文件描述符
// level 表示要更改的可选项的协议层
// optname 表示要更改的可选项名
// optval 表示保存更改的选项信息的缓冲地址值
// optlen 表示向第四个参数 optval 传递的可选项信息的字节数

4--代码实例

① 基于 getsockopt() 函数,利用设置协议层为 SOL_SOCKETSO_TYPE 可选项名来查看 SOCKET 的类型:

// gcc sock_type.c -o sock_type
// ./sock_type

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>

void error_handling(char *message){
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

int main(int argc, char* argv[]){
    int tcp_sock, udp_sock;
    int sock_type;
    socklen_t optlen;
    int state;

    optlen = sizeof(sock_type);
    tcp_sock = socket(PF_INET, SOCK_STREAM, 0); // create tcp socket
    udp_sock = socket(PF_INET, SOCK_DGRAM, 0); // create udp socket
    printf("SOCK_STREAM: %d \n", SOCK_STREAM);
    printf("SOCK_DGRAM: %d \n", SOCK_DGRAM);

    state = getsockopt(tcp_sock, SOL_SOCKET, SO_TYPE, (void*)&sock_type, &optlen);
    if(state){
        error_handling("getsockopt() error!");
    }
    printf("Socket type one: %d \n", sock_type);

    state = getsockopt(udp_sock, SOL_SOCKET, SO_TYPE, (void*)&sock_type, &optlen);
    if(state){
        error_handling("getsockopt() error!");
    }
    printf("Socket type two: %d \n", sock_type);

}

② 通过可选项名为 SO_SNDBUFSO_RCVBUF 来查看和设置 I/O 缓冲:

// gcc get_buf.c -o get_buf
// ./get_buf

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>

void error_handling(char *message){
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

int main(int argc, char* argv[]){
    int sock;
    int snd_buf, rcv_buf, state;
    socklen_t len;

    sock = socket(PF_INET, SOCK_STREAM, 0);
    len = sizeof(snd_buf);
    state = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, &len);
    if(state){
       error_handling("getsockopt() error!"); 
    }

    len = sizeof(rcv_buf);
    state = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, &len);
    if(state){
       error_handling("getsockopt() error!"); 
    }

    printf("Input buffer size: %d \n", rcv_buf);
    printf("Output buffer size: %d \n", snd_buf);
    return 0;    
}

扫描二维码关注公众号,回复: 16515958 查看本文章
// gcc set_buf.c -o set_buf
// ./set_buf

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>

void error_handling(char *message){
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

int main(int argc, char* argv[]){
    int sock;
    int snd_buf = 1024*3, rcv_buf = 1024*3;
    int state;
    socklen_t len;

    sock = socket(PF_INET, SOCK_STREAM, 0);
    state = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, sizeof(snd_buf));
    if(state){
       error_handling("getsockopt() error!"); 
    }

    state = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, sizeof(rcv_buf));
    if(state){
       error_handling("getsockopt() error!"); 
    }

    len = sizeof(snd_buf);
    state = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, &len);
    if(state){
       error_handling("getsockopt() error!"); 
    }

    len = sizeof(rcv_buf);
    state = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, &len);
    if(state){
       error_handling("getsockopt() error!"); 
    }

    printf("Input buffer size: %d \n", rcv_buf);
    printf("Output buffer size: %d \n", snd_buf);
    return 0; 
}

③ 通过更改 SO_REUSEADDR 的状态来将处于 Time-wait 状态的 SOCKET 端口号重新分配给新的 SOCKET:

// gcc reuseadr_eserver.c -o reuseadr_eserver
// ./reuseadr_eserver 9190

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define TRUE 1
#define FALSE 0

void error_handling(char *message){
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

int main(int argc, char *argv[]){
    int serv_sock, clnt_sock;
    char message[30];
    int option, str_len;
    socklen_t optlen, clnt_adr_sz;
    struct sockaddr_in serv_adr, clnt_adr;

    if(argc != 2){
        printf("Usage : %s <port>\n", argv[0]);
        exit(1);
    }

    serv_sock = socket(PF_INET, SOCK_STREAM, 0);
    if(serv_sock == -1){
        error_handling("socket() error");
    }

    // set SO_REUSEADDR 
    optlen = sizeof(option);
    option = TRUE;
    setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, (void*)&option, optlen);

    memset(&serv_adr, 0, sizeof(serv_adr));
    serv_adr.sin_family = AF_INET;
    serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_adr.sin_port = htons(atoi(argv[1]));

    if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1){
        error_handling("bind() error");
    }

    if(listen(serv_sock, 5) == -1){
        error_handling("listen() error");
    }
    
    clnt_adr_sz = sizeof(clnt_adr);
    clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);

    while((str_len = read(clnt_sock, message, sizeof(message))) !=0){
        write(clnt_sock, message, str_len);
        write(1, message, str_len);
    }
    close(clnt_sock);
    close(serv_sock);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43863869/article/details/132744638