• 网络编程day04(网络属性函数、广播、组播、TCP并发)


    今日任务

    对于newfd的话,最好是另存然后传入给分支线程,避免父子线程操作同一个文件描述符

    ------------在tcp多线程服务端----------

    如果使用全局变量,或者指针方式间接访问,会导致所有线程共用一份newfd和cin,那么newfd和cin会被覆盖

    1.广播:

    接收端

    代码:

    1. #include
    2. #include
    3. #include
    4. #include /* See NOTES */
    5. #include
    6. #include
    7. #include
    8. #include
    9. #define ERR_MSG(msg) do{\
    10. perror(msg);\
    11. fprintf(stderr,"__%d__",__LINE__);\
    12. }while(0)
    13. #define IP "192.168.125.255"
    14. #define PORT 8888
    15. /*
    16. * function: 广播,接收方
    17. * @param [ in]
    18. * @param [out]
    19. * @return
    20. */
    21. int main(int argc, const char *argv[])
    22. {
    23. //创建报式套接字
    24. int sfd=socket(AF_INET,SOCK_DGRAM,0);
    25. if(sfd<0){
    26. ERR_MSG("socket");
    27. return -1;
    28. }
    29. puts("socket success");
    30. //绑定IIF(P和端口号(广播ip)
    31. struct sockaddr_in addr;
    32. addr.sin_family=AF_INET;
    33. addr.sin_port=htons(PORT);
    34. addr.sin_addr.s_addr=inet_addr(IP);
    35. socklen_t addrlen=sizeof(addr);
    36. if(bind(sfd,(struct sockaddr*)&addr,addrlen)<0){
    37. ERR_MSG("bind");
    38. }
    39. puts("bind success");
    40. //存储发送方地址消息
    41. struct sockaddr_in source_addr;
    42. socklen_t source_addrlen=sizeof(source_addr);
    43. //循环接受消息
    44. char buf[128]="";
    45. while(1){
    46. bzero(buf,sizeof(buf));
    47. int recv_res=recvfrom(sfd,&buf,sizeof(buf),0,(struct sockaddr*)&source_addr,&source_addrlen);
    48. if(recv_res<0){
    49. ERR_MSG("recvfrom");
    50. return -1;
    51. }
    52. puts("recvfrom success");
    53. printf("[%s:%d]:%s\n",inet_ntoa(source_addr.sin_addr),ntohs(source_addr.sin_port),buf);
    54. }
    55. //关闭
    56. close(sfd);
    57. return 0;
    58. }

    发送端

    代码:

    1. #include
    2. #include
    3. #include
    4. #include /* See NOTES */
    5. #include
    6. #include
    7. #include
    8. #include
    9. #define ERR_MSG(msg) do{\
    10. perror(msg);\
    11. fprintf(stderr,"__%d__",__LINE__);\
    12. }while(0)
    13. #define IP "192.168.125.255"
    14. #define PORT 8888
    15. /*
    16. * function: 广播,发送方
    17. * @param [ in]
    18. * @param [out]
    19. * @return
    20. */
    21. int main(int argc, const char *argv[])
    22. {
    23. //创建报式套接字
    24. int sfd=socket(AF_INET,SOCK_DGRAM,0);
    25. if(sfd<0){
    26. ERR_MSG("socket");
    27. return -1;
    28. }
    29. puts("socket success");
    30. //设置允许广播
    31. int optval=1;//非0为允许
    32. socklen_t optlen=sizeof(optval);
    33. if(setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&optval,optlen)<0){
    34. ERR_MSG("setsockopt");
    35. return -1;
    36. }
    37. //IP和端口号(广播ip)
    38. struct sockaddr_in addr;
    39. addr.sin_family=AF_INET;
    40. addr.sin_port=htons(PORT);
    41. addr.sin_addr.s_addr=inet_addr(IP);
    42. socklen_t addrlen=sizeof(addr);
    43. //循环发送消息
    44. char buf[128]="";
    45. while(1){
    46. bzero(buf,sizeof(buf));
    47. printf("请输入>>>");
    48. fgets(buf,sizeof(buf),stdin);
    49. buf[strlen(buf)-1]='\0';
    50. if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&addr,addrlen)<0){
    51. ERR_MSG("sendto");
    52. return -1;
    53. }
    54. puts("sendto success");
    55. }
    56. //关闭
    57. close(sfd);
    58. return 0;
    59. }

    2.组播

    接收端

    代码:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #define ERR_MSG(msg) do{\
    9. perror(msg);\
    10. fprintf(stderr,"__%d__",__LINE__);\
    11. }while(0)
    12. #define IP "192.168.125.2"
    13. #define PORT 8888
    14. #define GRP_IP "224.1.2.3"
    15. /*
    16. * function: 组播:接收方
    17. * @param [ in]
    18. * @param [out]
    19. * @return
    20. */
    21. int main(int argc, const char *argv[])
    22. {
    23. //创建报式套接字
    24. int sfd=socket(AF_INET,SOCK_DGRAM,0);
    25. if(sfd<0){
    26. ERR_MSG("socket");
    27. return -1;
    28. }
    29. puts("socket success");
    30. //加入多播组
    31. struct ip_mreqn mq;
    32. mq.imr_multiaddr.s_addr = inet_addr(GRP_IP); //组播IP
    33. mq.imr_address.s_addr = inet_addr(IP); //本机IP,ifconfig
    34. mq.imr_ifindex = 2; //网络设备索引号
    35. if(setsockopt(sfd,IPPROTO_IP, IP_ADD_MEMBERSHIP,&mq,sizeof(mq))<0){
    36. ERR_MSG("setsockopt");
    37. return -1;
    38. }
    39. //绑定IIF(P和端口号(广播ip)
    40. struct sockaddr_in addr;
    41. addr.sin_family=AF_INET;
    42. addr.sin_port=htons(PORT);
    43. addr.sin_addr.s_addr=inet_addr(GRP_IP);
    44. socklen_t addrlen=sizeof(addr);
    45. if(bind(sfd,(struct sockaddr*)&addr,addrlen)<0){
    46. ERR_MSG("bind");
    47. }
    48. puts("bind success");
    49. //接受对方地址信息
    50. struct sockaddr_in source_addr;
    51. socklen_t source_addrlen=sizeof(source_addr);
    52. char buf[128]="";
    53. while(1){
    54. //接收消息
    55. bzero(buf,sizeof(buf));
    56. int recv_res = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&source_addr, &source_addrlen);
    57. if(recv_res < 0)
    58. {
    59. ERR_MSG("recvfrom");
    60. return -1;
    61. }
    62. printf("[%s:%d] : %s\n", \
    63. inet_ntoa(source_addr.sin_addr), ntohs(source_addr.sin_port), buf);
    64. }
    65. //关闭
    66. close(sfd);
    67. return 0;
    68. }

    发送端

    代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #define ERR_MSG(msg) do{\
    9. perror(msg);\
    10. fprintf(stderr,"__%d__",__LINE__);\
    11. }while(0)
    12. #define IP "192.168.125.2"
    13. #define PORT 8888
    14. #define GRP_IP "224.1.2.3"
    15. /*
    16. * function: 组播:发送方
    17. * @param [ in]
    18. * @param [out]
    19. * @return
    20. */
    21. int main(int argc, const char *argv[])
    22. {
    23. //创建报式套接字
    24. int sfd=socket(AF_INET,SOCK_DGRAM,0);
    25. if(sfd<0){
    26. ERR_MSG("socket");
    27. return -1;
    28. }
    29. puts("socket success");
    30. //绑定IIF(P和端口号(广播ip)
    31. struct sockaddr_in addr;
    32. addr.sin_family=AF_INET;
    33. addr.sin_port=htons(PORT);
    34. addr.sin_addr.s_addr=inet_addr(GRP_IP);
    35. socklen_t addrlen=sizeof(addr);
    36. if(bind(sfd,(struct sockaddr*)&addr,addrlen)<0){
    37. ERR_MSG("bind");
    38. }
    39. puts("bind success");
    40. char buf[128]="";
    41. while(1){
    42. //发送消息
    43. bzero(buf,sizeof(buf));
    44. printf("请输入>>> ");
    45. fgets(buf, sizeof(buf), stdin);
    46. buf[strlen(buf)-1] = 0;
    47. //发送数据, 主动发送给指定接收放,例如这里可以主动发给接收方
    48. if(sendto(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    49. {
    50. ERR_MSG("sendto");
    51. return -1;
    52. }
    53. printf("sendto success\n");
    54. }
    55. //关闭
    56. close(sfd);
    57. return 0;
    58. }

    3.TCP并发

    多进程

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. //自定义报错提示
    10. #define ERR_MSG(msg) do{\
    11. fprintf(stderr,"__%d__",__LINE__);\
    12. perror(msg);\
    13. }while(0)
    14. #define SER_PORT 8888
    15. #define SER_IP "192.168.125.2"
    16. /*
    17. * function: TCP服务端
    18. * @param [ in]
    19. * @param [out]
    20. * @return
    21. */
    22. int recv_send(int cfd,struct sockaddr_in cli_addr);
    23. void handle(int sig){
    24. while(waitpid(-1,NULL,WNOHANG)>0);
    25. return ;
    26. }
    27. int main(int argc, const char *argv[])
    28. {
    29. //监听回收僵尸进程
    30. if(signal(SIGCHLD,handle)==SIG_ERR){
    31. ERR_MSG("signal");
    32. return -1;
    33. }
    34. //1.创建socket套接字,
    35. int sfd=socket(AF_INET,SOCK_STREAM,0);
    36. if(sfd<0){
    37. ERR_MSG("socket");
    38. return -1;
    39. }
    40. puts("socket create");
    41. //允许端口快速复用
    42. int reuse = 1;
    43. if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
    44. {
    45. ERR_MSG("setsockopt");
    46. return -1;
    47. }
    48. printf("允许端口快速复用成功\n");
    49. //2.绑定服务器IP和端口号bind
    50. struct sockaddr_in addr;
    51. addr.sin_family=AF_INET;
    52. addr.sin_port=htons(SER_PORT);
    53. addr.sin_addr.s_addr=inet_addr(SER_IP);
    54. if(bind(sfd,(struct sockaddr*)&addr,sizeof(addr))<0){
    55. ERR_MSG("bind");
    56. return -1;
    57. }
    58. puts("bind success");
    59. //3.建立监听listen
    60. if(listen(sfd,128)<0){
    61. ERR_MSG("listen");
    62. return -1;
    63. }
    64. puts("listen suucess");
    65. //4.等待客户端连接, accept
    66. struct sockaddr_in cli_addr;
    67. socklen_t cli_addrlen=sizeof(cli_addr);
    68. pid_t pid;
    69. while(1){
    70. int cfd=accept(sfd,(struct sockaddr*)&cli_addr,&cli_addrlen);
    71. if(cfd<0){
    72. ERR_MSG("accept");
    73. return -1;
    74. }
    75. puts("accept");
    76. pid=fork();
    77. if(pid==0){
    78. //子进程执行信息收发
    79. recv_send(cfd,cli_addr);
    80. exit(0);
    81. }else if(pid<0){
    82. ERR_MSG("fork");
    83. return -1;
    84. }
    85. close(cfd);
    86. }
    87. //6.关闭
    88. close(sfd);
    89. return 0;
    90. }
    91. int recv_send(int cfd,struct sockaddr_in cli_addr){
    92. //5.接受发送消息recv;send
    93. char buf[128];
    94. while(1){
    95. bzero(buf,sizeof(buf));
    96. int recv_res=recv(cfd,buf,sizeof(buf),0);
    97. if(recv_res<0){
    98. ERR_MSG("recv");
    99. return -1;
    100. }else if(recv_res==0){
    101. printf("socket peer has shutdown\n");
    102. break;
    103. }
    104. puts("recv success");
    105. printf("[%s:%d]:%s\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),buf);
    106. if(strcmp(buf,"quit")==0)
    107. break;
    108. strcat(buf,"-----i has received");
    109. int send_res=send(cfd,buf,sizeof(buf),0);
    110. if(send_res<0){
    111. ERR_MSG("send");
    112. return -1;
    113. }
    114. puts("send success");
    115. }
    116. }

    多线程

    代码:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. //自定义报错提示
    10. #define ERR_MSG(msg) do{\
    11. fprintf(stderr,"__%d__",__LINE__);\
    12. perror(msg);\
    13. }while(0)
    14. #define SER_PORT 8888
    15. #define SER_IP "192.168.125.2"
    16. struct cliMsg{
    17. int cfd;
    18. struct sockaddr_in cli_addr;
    19. };
    20. /*
    21. * function: TCP服务端
    22. * @param [ in]
    23. * @param [out]
    24. * @return
    25. */
    26. void* recv_send(void*arg);
    27. int main(int argc, const char *argv[])
    28. {
    29. //1.创建socket套接字,
    30. int sfd=socket(AF_INET,SOCK_STREAM,0);
    31. if(sfd<0){
    32. ERR_MSG("socket");
    33. return -1;
    34. }
    35. puts("socket create");
    36. //允许端口快速复用
    37. int reuse = 1;
    38. if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
    39. {
    40. ERR_MSG("setsockopt");
    41. return -1;
    42. }
    43. printf("允许端口快速复用成功\n");
    44. //2.绑定服务器IP和端口号bind
    45. struct sockaddr_in addr;
    46. addr.sin_family=AF_INET;
    47. addr.sin_port=htons(SER_PORT);
    48. addr.sin_addr.s_addr=inet_addr(SER_IP);
    49. if(bind(sfd,(struct sockaddr*)&addr,sizeof(addr))<0){
    50. ERR_MSG("bind");
    51. return -1;
    52. }
    53. puts("bind success");
    54. //3.建立监听listen
    55. if(listen(sfd,128)<0){
    56. ERR_MSG("listen");
    57. return -1;
    58. }
    59. puts("listen suucess");
    60. //4.等待客户端连接, accept
    61. struct sockaddr_in cli_addr;
    62. socklen_t cli_addrlen=sizeof(cli_addr);
    63. pthread_t pth;
    64. while(1){
    65. int cfd=accept(sfd,(struct sockaddr*)&cli_addr,&cli_addrlen);
    66. if(cfd<0){
    67. ERR_MSG("accept");
    68. return -1;
    69. }
    70. puts("accept");
    71. struct cliMsg climsg;
    72. climsg.cfd=cfd;
    73. climsg.cli_addr=cli_addr;
    74. //创建调用线程执行
    75. if(pthread_create(&pth,NULL,recv_send,(void *)&climsg)!=0){
    76. fprintf(stderr,"pthread_create failed __%d__\n",__LINE__);
    77. return -1;
    78. }
    79. pthread_detach(pth);
    80. }
    81. close(sfd);
    82. return 0;
    83. }
    84. void* recv_send(void*arg){
    85. //5.接受发送消息recv;send
    86. int cfd=((struct cliMsg*)arg)->cfd;
    87. struct sockaddr_in cli_addr=((struct cliMsg*)arg)->cli_addr;
    88. char buf[128];
    89. while(1){
    90. bzero(buf,sizeof(buf));
    91. int recv_res=recv(cfd,buf,sizeof(buf),0);
    92. if(recv_res<0){
    93. ERR_MSG("recv");
    94. break;
    95. }else if(recv_res==0){
    96. printf("socket peer has shutdown\n");
    97. break;
    98. }
    99. puts("recv success");
    100. printf("[%s:%d]:%s\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),buf);
    101. if(strcmp(buf,"quit")==0)
    102. break;
    103. strcat(buf,"-----i has received");
    104. int send_res=send(cfd,buf,sizeof(buf),0);
    105. if(send_res<0){
    106. ERR_MSG("send");
    107. break;
    108. }
    109. puts("send success");
    110. }
    111. close(cfd);
    112. pthread_exit(NULL);
    113. }

    今日思维导图

    不知道最近确实是脑子比较慢,还是拖拉,做事太慢了,tcp的代码还没复敲;

  • 相关阅读:
    共享充电语音提醒功能如何实现?
    音视频录制器—捕获并保存摄像头和麦克风数据
    距离度量 —— 汉明距离(Hamming Distance)
    数学建模笔记-第四讲-拟合
    我去探访了下杭州最贵的奢华酒店之一
    最详细的mysql安装教程+mysql文件下载链接
    目录的权限
    Word 文档转换 PDF、图片
    JS学习总结
    一文搞懂HTTPS加密原理
  • 原文地址:https://blog.csdn.net/weixin_53762703/article/details/133150495