• UDP-创建群聊


    服务器

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #define send_port "8888"
    9. #define send_ip "192.168.1.6"
    10. //存储用户端信息
    11. typedef struct user{
    12. struct sockaddr_in user;
    13. struct user* next;
    14. struct user* prve;
    15. }USER;
    16. //创建链表
    17. USER* creat_link(void){
    18. USER* head=(USER*)malloc(sizeof(struct user));
    19. head->next=NULL;
    20. head->prve=NULL;
    21. memset(&(head->user),0,sizeof(head->user));
    22. return head;
    23. }
    24. //新用户上线
    25. void add_link(USER* head,struct sockaddr_in usr){
    26. USER* uhead=(USER*)malloc(sizeof(USER));
    27. uhead->next=head->next;
    28. uhead->prve=head;
    29. uhead->user=usr;
    30. head->next=uhead;
    31. return ;
    32. }
    33. //用户下线
    34. void delete_link(USER* head){
    35. USER* temp =NULL;
    36. temp=head->prve;
    37. temp->next=head->next;
    38. head->next->prve=temp;
    39. free(head);
    40. return ;
    41. }
    42. int main(int argc, const char *argv[])
    43. {
    44. //创建链表
    45. USER* head=creat_link();
    46. int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    47. if(sockfd<0){
    48. perror("socket");
    49. return -1;
    50. }
    51. int optval=1;
    52. int spt=setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,(void *)&optval,sizeof(optval));
    53. if(spt<0){
    54. perror("setsockopt");
    55. return -1;
    56. }
    57. //绑定广播地址
    58. struct sockaddr_in bro_addr;
    59. memset(&bro_addr,0,sizeof(bro_addr));
    60. bro_addr.sin_family=AF_INET;
    61. bro_addr.sin_port=htons(atoi(send_port));
    62. bro_addr.sin_addr.s_addr=inet_addr(send_ip);
    63. memset(bro_addr.sin_zero,0,sizeof(bro_addr.sin_zero));
    64. int bindflag=bind(sockfd,(struct sockaddr*)&bro_addr,sizeof(bro_addr));
    65. if(bindflag<0){
    66. perror("bind");
    67. return -1;
    68. }
    69. //创建子进程
    70. //int key=0;
    71. int pfd[2]={0};
    72. if(pipe(pfd)<0){
    73. perror("pipe");
    74. return -1;
    75. }
    76. printf("无名管道创建成功\n");
    77. pid_t pid=fork();
    78. if(pid>0){ //父进程
    79. while(1){
    80. ssize_t res=0;
    81. USER* temp;
    82. res=read(pfd[0],temp,sizeof(temp));
    83. if(res<0){
    84. perror("read");
    85. return -1;
    86. }
    87. USER* p=(temp)->next;
    88. while(p!=NULL){
    89. printf("%d\n",__LINE__);
    90. char send_buf[1024];
    91. memset(send_buf,0,sizeof(send_buf));
    92. ssize_t res=0;
    93. res=read(pfd[0],send_buf,sizeof(send_buf));
    94. if(res<0){
    95. perror("read");
    96. return -1;
    97. }
    98. int sendflag=sendto(sockfd,send_buf,sizeof(send_buf),0,(struct sockaddr*)&(p->user),sizeof(p->user));
    99. if(sendflag<0){
    100. perror("sendto");
    101. return -1;
    102. }
    103. }
    104. }
    105. }
    106. /*子进程
    107. * 实现客户端的查询是否有客户端上线
    108. * 已上线的客户端,进行数据传输
    109. * 判断是否有客户端用户要退出
    110. * */
    111. else if(0==pid){
    112. while(1){
    113. char recv_buf[1024];//定义字符串,用于接收数据
    114. memset(recv_buf,0,sizeof(recv_buf));//将字符串清空
    115. struct sockaddr_in recv_addr;//定义一个结构体变量,用于接收IP和端口号
    116. memset(&recv_addr,0,sizeof(recv_addr));//清空结构体
    117. socklen_t len=sizeof(recv_buf);//计算字符串的大小
    118. int recvflag=recvfrom(sockfd,recv_buf,sizeof(recv_buf),0,(struct sockaddr *)&recv_addr,&len);//接收数据
    119. if(recvflag<0)//判断接收数据是否成功
    120. {
    121. printf("recvfrom error!\r\n");
    122. return -4;
    123. }
    124. USER* p=head;//创建一个链表节点
    125. int k=0;
    126. while(p->next!=NULL){
    127. p=p->next;
    128. in_port_t port=p->user.sin_port;
    129. if(port==recv_addr.sin_port){
    130. int i=strcmp(recv_buf,"quit");
    131. if(i==0){
    132. delete_link(p);
    133. p=NULL;
    134. k=1;
    135. break;
    136. }
    137. USER** phead=head;
    138. if(write(pfd[1],phead,sizeof(phead))<0){
    139. perror("地址_write");
    140. return -1;
    141. }
    142. if(write(pfd[1],recv_buf,sizeof(recv_buf))<0){
    143. perror("write");
    144. return -1;
    145. }
    146. printf("IP:%s PORT:%d data:%s\n",\
    147. inet_ntoa(recv_addr.sin_addr),ntohs(recv_addr.sin_port),recv_buf);
    148. k=1;
    149. }
    150. }
    151. if(p->next==NULL&&0==k){
    152. add_link(p,recv_addr);
    153. printf("IP:%s PORT:%d上线\n",\
    154. inet_ntoa(recv_addr.sin_addr),ntohs(recv_addr.sin_port));
    155. }
    156. }
    157. }
    158. else{
    159. perror("fork");
    160. return -1;
    161. }
    162. //printf("数据发送完成:%s\n",recv_buf);
    163. close(sockfd);
    164. return 0;
    165. }

    客户端

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #define send_port "8888"
    9. #define send_ip "192.168.1.6"
    10. int main(int argc, const char *argv[])
    11. {
    12. int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    13. if(sockfd<0){
    14. perror("socket");
    15. return -1;
    16. }
    17. int optval=1;
    18. int spt=setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,(void *)&optval,sizeof(optval));
    19. if(spt<0){
    20. perror("setsockopt");
    21. return -1;
    22. }
    23. struct sockaddr_in send_addr;
    24. memset(&send_addr,0,sizeof(send_addr));
    25. send_addr.sin_family=AF_INET;
    26. send_addr.sin_port=htons(atoi(send_port));
    27. send_addr.sin_addr.s_addr=inet_addr(send_ip);
    28. memset(send_addr.sin_zero,0,sizeof(send_addr));
    29. char buf[64];
    30. memset(buf,0,sizeof(buf));
    31. //fgets(buf,sizeof(buf),stdin);
    32. //buf[strlen(buf)-1]='\0';
    33. ssize_t buf_len= sizeof(buf);
    34. if(sendto(sockfd,buf,buf_len,0,(struct sockaddr*)&send_addr,sizeof(send_addr))<0){
    35. perror("sendto");
    36. return -1;
    37. }
    38. int pfd[2]={0};
    39. if(pipe(pfd)<0){
    40. perror("pipe");
    41. return-1;
    42. }
    43. pid_t pid=fork();
    44. if(pid>0){
    45. while(1){
    46. char buf[64];
    47. memset(buf,0,sizeof(buf));
    48. fgets(buf,sizeof(buf),stdin);
    49. buf[strlen(buf)-1]='\0';
    50. ssize_t buf_len= sizeof(buf);
    51. if(sendto(sockfd,buf,buf_len,0,(struct sockaddr*)&send_addr,sizeof(send_addr))<0){
    52. perror("sendto");
    53. return -1;
    54. }
    55. if(strcmp(buf,"quit")==0){
    56. if(write(pfd[1],buf,sizeof(buf))<0){
    57. perror("write");
    58. return -1;
    59. }
    60. printf("退出群聊\n");
    61. pid_t id=wait(NULL);
    62. break;
    63. }
    64. }
    65. }
    66. else if(pid==0){
    67. while(1){
    68. ssize_t res=0;
    69. char bufc[1024];
    70. res=read(pfd[0],bufc,sizeof(bufc));
    71. if(res<0){
    72. perror("read");
    73. return -1;
    74. }
    75. if(strcmp(bufc,"quit")==0){
    76. exit(0);
    77. }
    78. char recv_buf[1024];//定义字符串,用于接收数据
    79. memset(recv_buf,0,sizeof(recv_buf));//将字符串清空
    80. struct sockaddr_in recv_addr;//定义一个结构体变量,用于接收IP和端口号
    81. memset(&recv_addr,0,sizeof(recv_addr));//清空结构体
    82. socklen_t len=sizeof(recv_buf);//计算字符串的大小
    83. int recvflag=recvfrom(sockfd,recv_buf,sizeof(recv_buf),0,(struct sockaddr *)&recv_addr,&len);
    84. if(recvflag<0)//判断接收数据是否成功
    85. {
    86. printf("recvfrom error!\r\n");
    87. return -4;
    88. }
    89. printf("IP:%s PORT:%d data:%s\n",\
    90. inet_ntoa(recv_addr.sin_addr),ntohs(recv_addr.sin_port),recv_buf);
    91. }
    92. }else{
    93. perror("fork");
    94. return -1;
    95. }
    96. printf("数据发送完成\n");
    97. close(sockfd);
    98. return 0;
    99. }

  • 相关阅读:
    酷安官网下载页前端自适应源码
    【计网】三、数据链路层
    StarRocks入门到熟练
    【23-24 秋学期】NNDL 作业7 基于CNN的XO识别
    机器学习中常用的分类算法总结
    uniapp小程序中的登录完整代码(兼容小程序和app)
    999、Android --问题处理-1
    京东获取商品历史价格信息 API 返回值说明
    Azure - 机器学习企业级服务概述与介绍
    Vue08/Vue 生命周期钩子函数( Vue生命周期11个阶段 )应用场景
  • 原文地址:https://blog.csdn.net/qq_50951387/article/details/136609966