当前位置:   article > 正文

UDP-创建群聊

UDP-创建群聊

服务器

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/socket.h>
  4. #include <sys/types.h>
  5. #include <arpa/inet.h>
  6. #include <string.h>
  7. #include <unistd.h>
  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 <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/socket.h>
  4. #include <sys/types.h>
  5. #include <arpa/inet.h>
  6. #include <string.h>
  7. #include <unistd.h>
  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. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/262436
推荐阅读
相关标签
  

闽ICP备14008679号