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


    目录

    1--Socket的多种可选项

    2--getsocketopt()

    3--setsockopt()

    4--代码实例


    1--Socket的多种可选项

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

    2--getsocketopt()

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

    3--setsockopt()

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

    4--代码实例

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

    1. // gcc sock_type.c -o sock_type
    2. // ./sock_type
    3. #include
    4. #include
    5. #include
    6. #include
    7. void error_handling(char *message){
    8. fputs(message, stderr);
    9. fputc('\n', stderr);
    10. exit(1);
    11. }
    12. int main(int argc, char* argv[]){
    13. int tcp_sock, udp_sock;
    14. int sock_type;
    15. socklen_t optlen;
    16. int state;
    17. optlen = sizeof(sock_type);
    18. tcp_sock = socket(PF_INET, SOCK_STREAM, 0); // create tcp socket
    19. udp_sock = socket(PF_INET, SOCK_DGRAM, 0); // create udp socket
    20. printf("SOCK_STREAM: %d \n", SOCK_STREAM);
    21. printf("SOCK_DGRAM: %d \n", SOCK_DGRAM);
    22. state = getsockopt(tcp_sock, SOL_SOCKET, SO_TYPE, (void*)&sock_type, &optlen);
    23. if(state){
    24. error_handling("getsockopt() error!");
    25. }
    26. printf("Socket type one: %d \n", sock_type);
    27. state = getsockopt(udp_sock, SOL_SOCKET, SO_TYPE, (void*)&sock_type, &optlen);
    28. if(state){
    29. error_handling("getsockopt() error!");
    30. }
    31. printf("Socket type two: %d \n", sock_type);
    32. }

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

    1. // gcc get_buf.c -o get_buf
    2. // ./get_buf
    3. #include
    4. #include
    5. #include
    6. #include
    7. void error_handling(char *message){
    8. fputs(message, stderr);
    9. fputc('\n', stderr);
    10. exit(1);
    11. }
    12. int main(int argc, char* argv[]){
    13. int sock;
    14. int snd_buf, rcv_buf, state;
    15. socklen_t len;
    16. sock = socket(PF_INET, SOCK_STREAM, 0);
    17. len = sizeof(snd_buf);
    18. state = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, &len);
    19. if(state){
    20. error_handling("getsockopt() error!");
    21. }
    22. len = sizeof(rcv_buf);
    23. state = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, &len);
    24. if(state){
    25. error_handling("getsockopt() error!");
    26. }
    27. printf("Input buffer size: %d \n", rcv_buf);
    28. printf("Output buffer size: %d \n", snd_buf);
    29. return 0;
    30. }

    1. // gcc set_buf.c -o set_buf
    2. // ./set_buf
    3. #include
    4. #include
    5. #include
    6. #include
    7. void error_handling(char *message){
    8. fputs(message, stderr);
    9. fputc('\n', stderr);
    10. exit(1);
    11. }
    12. int main(int argc, char* argv[]){
    13. int sock;
    14. int snd_buf = 1024*3, rcv_buf = 1024*3;
    15. int state;
    16. socklen_t len;
    17. sock = socket(PF_INET, SOCK_STREAM, 0);
    18. state = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, sizeof(snd_buf));
    19. if(state){
    20. error_handling("getsockopt() error!");
    21. }
    22. state = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, sizeof(rcv_buf));
    23. if(state){
    24. error_handling("getsockopt() error!");
    25. }
    26. len = sizeof(snd_buf);
    27. state = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, &len);
    28. if(state){
    29. error_handling("getsockopt() error!");
    30. }
    31. len = sizeof(rcv_buf);
    32. state = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, &len);
    33. if(state){
    34. error_handling("getsockopt() error!");
    35. }
    36. printf("Input buffer size: %d \n", rcv_buf);
    37. printf("Output buffer size: %d \n", snd_buf);
    38. return 0;
    39. }

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

    1. // gcc reuseadr_eserver.c -o reuseadr_eserver
    2. // ./reuseadr_eserver 9190
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #define TRUE 1
    10. #define FALSE 0
    11. void error_handling(char *message){
    12. fputs(message, stderr);
    13. fputc('\n', stderr);
    14. exit(1);
    15. }
    16. int main(int argc, char *argv[]){
    17. int serv_sock, clnt_sock;
    18. char message[30];
    19. int option, str_len;
    20. socklen_t optlen, clnt_adr_sz;
    21. struct sockaddr_in serv_adr, clnt_adr;
    22. if(argc != 2){
    23. printf("Usage : %s \n", argv[0]);
    24. exit(1);
    25. }
    26. serv_sock = socket(PF_INET, SOCK_STREAM, 0);
    27. if(serv_sock == -1){
    28. error_handling("socket() error");
    29. }
    30. // set SO_REUSEADDR
    31. optlen = sizeof(option);
    32. option = TRUE;
    33. setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, (void*)&option, optlen);
    34. memset(&serv_adr, 0, sizeof(serv_adr));
    35. serv_adr.sin_family = AF_INET;
    36. serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
    37. serv_adr.sin_port = htons(atoi(argv[1]));
    38. if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1){
    39. error_handling("bind() error");
    40. }
    41. if(listen(serv_sock, 5) == -1){
    42. error_handling("listen() error");
    43. }
    44. clnt_adr_sz = sizeof(clnt_adr);
    45. clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);
    46. while((str_len = read(clnt_sock, message, sizeof(message))) !=0){
    47. write(clnt_sock, message, str_len);
    48. write(1, message, str_len);
    49. }
    50. close(clnt_sock);
    51. close(serv_sock);
    52. return 0;
    53. }

  • 相关阅读:
    Git | git的简单使用教程
    【Linux学习笔记】消息队列
    基于Python爬虫和K-means算法的校园微博热点话题发现系统
    爬虫篇-如何下载selenium及其适配谷歌浏览器插件chromedriver(含chrome各版本及下载地址)
    基于IMDB评论数据集的情感分析
    LeetCode题练习与总结:设计推特--355
    斜率优化dp
    unordered_set和unordered_map的使用【STL】
    虚拟与真实,交互与交易 | 你为什么喜欢元宇宙游戏?
    # Vue3 toRef 和 toRefs 函数
  • 原文地址:https://blog.csdn.net/weixin_43863869/article/details/132744638