• 用进程和线程完成TCP进行通信操作及广播和组播的通信


    进程

    代码

    1. #include <stdio.h>
    2. #include <sys/types.h>
    3. #include <sys/socket.h>
    4. #include <netinet/in.h>
    5. #include <arpa/inet.h>
    6. #include <string.h>
    7. #include <unistd.h>
    8. #include <stdlib.h>
    9. #include <signal.h>
    10. #include <sys/wait.h>
    11. #define PORT 8888
    12. #define IP "192.168.124.62"
    13. #define ERR_MSG(msg) do{\
    14. fprintf(stderr,"line=%d",__LINE__);\
    15. perror(msg);\
    16. }while(0)
    17. void handler(int sig)
    18. {
    19. while(waitpid(-1,NULL,WNOHANG)>0);
    20. }
    21. int main(int argc, const char *argv[])
    22. {
    23. //创建套接字
    24. int fd = socket(AF_INET,SOCK_STREAM,0);
    25. if(fd<0)
    26. {
    27. ERR_MSG("socket");
    28. return -1;
    29. }
    30. printf("-流式套接字\n");
    31. //捕获17号信息SIGCHLD
    32. if(signal(17,handler) == SIG_ERR)
    33. {
    34. ERR_MSG("signal");
    35. return -1;
    36. }
    37. //允许端口号重复使用
    38. int reuse = 1;
    39. if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
    40. {
    41. ERR_MSG("setsockopt");
    42. return -1;
    43. }
    44. printf("端口允许快速重用\n");
    45. //创建一个地址信息结构体,bind绑定需要用到
    46. struct sockaddr_in sin;
    47. sin.sin_family = AF_INET;
    48. sin.sin_port = htons(PORT);
    49. sin.sin_addr.s_addr = inet_addr(IP);
    50. //绑定ip和端口
    51. if(bind(fd,(struct sockaddr*)&sin,sizeof(sin))<0)
    52. {
    53. ERR_MSG("bind");
    54. return -1;
    55. }
    56. printf("绑定成功\n");
    57. //将套接字设置为监听状态
    58. if(listen(fd,128)<0)
    59. {
    60. ERR_MSG("listen");
    61. return -1;
    62. }
    63. printf("监听成功\n");
    64. int newfd;
    65. pid_t pid;
    66. struct sockaddr_in cin;
    67. socklen_t socklen = sizeof(cin);
    68. while(1)
    69. {
    70. //获取连接成功的套接字,用于阻塞等待连接
    71. newfd = accept(fd,(struct sockaddr*)&cin,&socklen);
    72. if(newfd <0)
    73. {
    74. ERR_MSG("accept");
    75. return -1;
    76. }
    77. printf("[%s:%d]客户端连接成功%d\n",inet_ntoa(sin.sin_addr),ntohs(sin.sin_port),newfd);
    78. pid = fork();
    79. if(pid == 0)
    80. {
    81. close(fd);
    82. //接收与发送
    83. char buf[128];
    84. ssize_t size;
    85. while(1)
    86. {
    87. //接收
    88. //
    89. bzero(buf,sizeof(buf));//清空数组内容
    90. // size = read(newfd,buf,sizeof(buf));
    91. size = recv(newfd,buf,sizeof(buf),0);
    92. // size = recvfrom(newfd,buf,sizeof(buf),0,NULL,NULL);
    93. if(size<0)
    94. {
    95. ERR_MSG("recv");
    96. return -1;
    97. }else if(size==0)
    98. {
    99. printf("[%s:%d]客户端下线\n",inet_ntoa(sin.sin_addr),ntohs(sin.sin_port));
    100. break;
    101. }
    102. printf("[%s:%d]接收成功newfd=%d:%s\n",inet_ntoa(sin.sin_addr),ntohs(sin.sin_port),newfd,buf);
    103. //发送
    104. printf("服务器回复>>>>");
    105. fgets(buf,sizeof(buf),stdin);
    106. buf[strlen(buf)-1] = '\0';
    107. if(send(newfd,buf,sizeof(buf),0)<0)
    108. {
    109. ERR_MSG("send");
    110. break;
    111. }
    112. printf("发送成功\n");
    113. }
    114. close(newfd);
    115. exit(0);
    116. }
    117. close(newfd);
    118. }
    119. close(fd);
    120. return 0;
    121. }

    运行结果图:

    线程

    代码:

    1. 1 #include <stdio.h>
    2. 2 #include <sys/types.h>
    3. 3 #include <sys/socket.h>
    4. 4 #include <netinet/in.h>
    5. 5 #include <arpa/inet.h>
    6. 6 #include <string.h>
    7. 7 #include <unistd.h>
    8. 8 #include <stdlib.h>
    9. 9 #include <signal.h>
    10. 10 #include <sys/wait.h>
    11. 11 #include <pthread.h>
    12. 12
    13. 13 #define PORT 8888
    14. 14 #define IP "192.168.124.62"
    15. 15 #define ERR_MSG(msg) do{\
    16. 16 fprintf(stderr,"line=%d",__LINE__);\
    17. 17 perror(msg);\
    18. 18 }while(0)
    19. 19
    20. 20 struct msg
    21. 21 {
    22. 22 int newfd;
    23. 23 struct sockaddr_in cin;
    24. 24 };
    25. 25 void* huidiaolist(void* arg);
    26. 26 int main(int argc, const char *argv[])
    27. 27 {
    28. 28 //创建套接字
    29. 29 int fd = socket(AF_INET,SOCK_STREAM,0);
    30. 30 if(fd<0)
    31. 31 {
    32. 32 ERR_MSG("socket");
    33. 33 return -1;
    34. 34 }
    35. 35 printf("-流式套接字\n");
    36. 36 //允许端口号重复使用
    37. 37 int reuse = 1;
    38. 38 if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
    39. 39 {
    40. 40 ERR_MSG("setsockopt");
    41. 41 return -1;
    42. 42 }
    43. 43 printf("端口允许快速重用\n");
    44. 44 //创建一个地址信息结构体,bind绑定需要用到
    45. 45 struct sockaddr_in sin;
    46. 46 sin.sin_family = AF_INET;
    47. 47 sin.sin_port = htons(PORT);
    48. 48 sin.sin_addr.s_addr = inet_addr(IP);
    49. 49 //绑定ip和端口
    50. 50 if(bind(fd,(struct sockaddr*)&sin,sizeof(sin))<0)
    51. 51 {
    52. 52 ERR_MSG("bind");
    53. 53 return -1;
    54. 54 }
    55. 55 printf("绑定成功\n");
    56. 56
    57. 57 //将套接字设置为监听状态
    58. 58 if(listen(fd,128)<0)
    59. 59 {
    60. 60 ERR_MSG("listen");
    61. 61 return -1;
    62. 62 }
    63. 63 printf("监听成功\n");
    64. 64
    65. 65 int newfd;
    66. 66 pid_t pid;
    67. 67 struct sockaddr_in cin;
    68. 68 socklen_t socklen = sizeof(cin);
    69. 69
    70. 70 pthread_t tid;
    71. 71 struct msg clinfo;
    72. 72 while(1)
    73. 73 {
    74. 74 //获取连接成功的套接字,用于阻塞等待连接
    75. 75 newfd = accept(fd,(struct sockaddr*)&cin,&socklen);
    76. 76 if(newfd <0)
    77. 77 {
    78. 78 ERR_MSG("accept");
    79. 79 return -1;
    80. 80 }
    81. 81 printf("[%s:%d]客户端连接成功%d\n",\
    82. 82 inet_ntoa(sin.sin_addr),ntohs(sin.sin_port),newfd);
    83. 83
    84. 84 clinfo.newfd = newfd;
    85. 85 clinfo.cin = cin;
    86. 86 if(pthread_create(&tid,NULL,huidiaolist,(void*)&clinfo)!=0)
    87. 87 {
    88. 88 fprintf(stderr,"line=%d",__LINE__);
    89. 89 break;
    90. 90 }
    91. 91 pthread_detach(tid);
    92. 92 }
    93. 93 close(fd);
    94. 94
    95. 95 return 0;
    96. 96 }
    97. 97
    98. 98 void* huidiaolist(void* arg)
    99. 99 {
    100. 100 //接收与发送
    101. 101 int newfd = ((struct msg*)arg)->newfd;
    102. 102 struct sockaddr_in cin = ((struct msg*)arg)->cin;
    103. 103
    104. 104 char buf[128];
    105. 105 ssize_t size;
    106. 106 while(1)
    107. 107 {
    108. 108 //接收
    109. 109 //
    110. 110 bzero(buf,sizeof(buf));//清空数组内容
    111. 111 // size = read(newfd,buf,sizeof(buf));
    112. 112 size = recv(newfd,buf,sizeof(buf),0);
    113. 113 // size = recvfrom(newfd,buf,sizeof(buf),0,NULL,NULL);
    114. 114 if(size<0)
    115. 115 {
    116. 116 ERR_MSG("recv");
    117. 117 break;
    118. 118 }else if(size==0)
    119. 119 {
    120. 120 printf("[%s:%d]客户端下线\n",\
    121. 121 inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
    122. 122 break;
    123. 123 }
    124. 124 printf("[%s:%d]接收成功newfd=%d:%s\n",\
    125. 125 inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,buf);
    126. 126
    127. 127
    128. 128 //发送
    129. 129 strcpy(buf,"回复");
    130. 130 if(send(newfd,buf,sizeof(buf),0)<0)
    131. 131 {
    132. 132 ERR_MSG("send");
    133. 133 break;
    134. 134 }
    135. 135 printf("发送成功\n");
    136. 136 }
    137. 137 close(newfd);
    138. 138 pthread_exit(NULL);

    结果图:

    广播

    1. #include <stdio.h>
    2. #include <sys/types.h>
    3. #include <sys/socket.h>
    4. #include <netinet/in.h>
    5. #include <string.h>
    6. #include <arpa/inet.h>
    7. #include <unistd.h>
    8. #define PORT 6667
    9. #define IP "192.168.124.255"
    10. #define ERR_MSG(msg) do{\
    11. fprintf(stderr,"line:%d\n",__LINE__);\
    12. perror(msg);\
    13. }while(0)
    14. int main(int argc, const char *argv[])
    15. {
    16. int fd = socket(AF_INET,SOCK_DGRAM,0);
    17. if(fd<0)
    18. {
    19. ERR_MSG("scoket");
    20. return -1;
    21. }
    22. printf("创建流式套接字成功cd=%d\n",fd);
    23. //允许端口被重
    24. int reuse = 1;
    25. if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
    26. {
    27. ERR_MSG("setsockopt");
    28. return -1;
    29. }
    30. printf("允许端口被重复使用\n");
    31. //允许广播
    32. if(setsockopt(fd,SOL_SOCKET,SO_BROADCAST,&reuse,sizeof(reuse))<0)
    33. {
    34. ERR_MSG("setsockopt");
    35. return -1;
    36. }
    37. //绑定服务器地址信息,必须绑定
    38. struct sockaddr_in sin;
    39. sin.sin_family = AF_INET;
    40. sin.sin_port = htons(PORT);
    41. sin.sin_addr.s_addr= inet_addr(IP);
    42. //绑定IP及端口号
    43. if(bind(fd,(struct sockaddr*)&sin,sizeof(sin))<0)
    44. {
    45. ERR_MSG("bind");
    46. return -1;
    47. }
    48. printf("绑定成功\n");
    49. char arr[128];
    50. struct sockaddr_in cin;
    51. socklen_t addrlen = sizeof(arr);
    52. while(1)
    53. {
    54. //发送数据
    55. printf("请输入数据>>>>>");
    56. fgets(arr,sizeof(arr),stdin);
    57. arr[strlen(arr)-1] = '\0';
    58. if(sendto(fd,arr,sizeof(arr),0,\
    59. (struct sockaddr*)&sin,sizeof(sin))<0)
    60. {
    61. ERR_MSG("sendto");
    62. return -1;
    63. }
    64. printf("发送成功\n");
    65. bzero(arr,sizeof(arr));
    66. }
    67. close(fd);
    68. return 0;
    69. }

    组播

    1. #include <stdio.h>
    2. #include <sys/types.h>
    3. #include <sys/socket.h>
    4. #include <netinet/in.h>
    5. #include <string.h>
    6. #include <arpa/inet.h>
    7. #include <unistd.h>
    8. #define PORT 6667
    9. #define IP "224.1.2.3"
    10. #define ERR_MSG(msg) do{\
    11. fprintf(stderr,"line:%d\n",__LINE__);\
    12. perror(msg);\
    13. }while(0)
    14. int main(int argc, const char *argv[])
    15. {
    16. int fd = socket(AF_INET,SOCK_DGRAM,0);
    17. if(fd<0)
    18. {
    19. ERR_MSG("scoket");
    20. return -1;
    21. }
    22. printf("创建流式套接字成功cd=%d\n",fd);
    23. //允许端口被重
    24. int reuse = 1;
    25. if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
    26. {
    27. ERR_MSG("setsockopt");
    28. return -1;
    29. }
    30. printf("允许端口被重复使用\n");
    31. //允许广播
    32. if(setsockopt(fd,SOL_SOCKET,SO_BROADCAST,&reuse,sizeof(reuse))<0)
    33. {
    34. ERR_MSG("setsockopt");
    35. return -1;
    36. }
    37. //绑定服务器地址信息,必须绑定
    38. struct sockaddr_in sin;
    39. sin.sin_family = AF_INET;
    40. sin.sin_port = htons(PORT);
    41. sin.sin_addr.s_addr= inet_addr(IP);
    42. //绑定IP及端口号
    43. if(bind(fd,(struct sockaddr*)&sin,sizeof(sin))<0)
    44. {
    45. ERR_MSG("bind");
    46. return -1;
    47. }
    48. printf("绑定成功\n");
    49. char arr[128];
    50. struct sockaddr_in cin;
    51. socklen_t addrlen = sizeof(arr);
    52. while(1)
    53. {
    54. //发送数据
    55. printf("请输入数据>>>>>");
    56. fgets(arr,sizeof(arr),stdin);
    57. arr[strlen(arr)-1] = '\0';
    58. if(sendto(fd,arr,sizeof(arr),0,\
    59. (struct sockaddr*)&sin,sizeof(sin))<0)
    60. {
    61. ERR_MSG("sendto");
    62. return -1;
    63. }
    64. printf("发送成功\n");
    65. bzero(arr,sizeof(arr));
    66. }
    67. close(fd);
    68. return 0;
    69. }

  • 相关阅读:
    计算机二级python简单应用题刷题笔记(一)
    Visual Studio Code如何写C语言
    可编程 USB 转串口适配器开发板芯片驱动文件说明
    docker系统笔记-03镜像的创建管理和发布
    关于到年底日常生活的工作计划
    新概念英语(第二册)复习——Lesson 16 - Lesson20
    【Java 基础篇】Java标准输入流详解:读取用户输入的完整指南
    SpringCloud之Nacos配置中心解读
    Word参考文献交叉引用
    基于javaweb的农业信息管理系统(java+ssm+jsp+js+html+mysql)
  • 原文地址:https://blog.csdn.net/qq_42129915/article/details/139868295