当前位置:   article > 正文

UDP聊天室

UDP聊天室

服务器

  1. #include<myhead.h>
  2. struct sockaddr_in serveraddr,caddr;
  3. enum type_t//枚举
  4. {
  5. Login,
  6. Chat,
  7. Quit,
  8. };
  9. typedef struct MSG
  10. {
  11. char type;//L C Q
  12. char name[32];//
  13. char text[128];//
  14. }msg_t;
  15. typedef struct NODE//链表
  16. {
  17. struct sockaddr_in caddr;
  18. struct NODE *next;
  19. }node_t;
  20. node_t *create_node(void)//建头节点
  21. {
  22. node_t *p=(node_t *)malloc(sizeof(node_t));
  23. if(p==NULL)
  24. {
  25. perror("malloc err");
  26. return NULL;
  27. }
  28. p->next=NULL;
  29. return p;
  30. }
  31. void do_login(int ,msg_t ,node_t *,struct sockaddr_in);//登录的函数
  32. void do_chat(int ,msg_t ,node_t *,struct sockaddr_in);//群聊的函数
  33. void do_quit(int ,msg_t ,node_t *,struct sockaddr_in);//退出函数
  34. int main(int argc, char const *argv[])
  35. {
  36. if(argc !=3)
  37. {
  38. printf("Usage:./a.out <port>\n");
  39. return -1;
  40. }
  41. //创建UDP套接字
  42. int sockfd = socket(AF_INET,SOCK_DGRAM,0);
  43. if(sockfd<0)
  44. {
  45. perror("socket err");
  46. exit(-1);
  47. }
  48. //填充服务器网络信息结构体
  49. serveraddr.sin_family=AF_INET;
  50. serveraddr.sin_port=htons(atoi(argv[2]));
  51. serveraddr.sin_addr.s_addr=inet_addr(argv[1]);
  52. socklen_t len = sizeof(caddr);
  53. //定义保存客户端网络信息的结构体
  54. //绑定套接字和服务器网络信息的结构体
  55. bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
  56. printf("bind ok!\n");
  57. msg_t msg;
  58. node_t *p=create_node();
  59. while(1)
  60. {
  61. if(recvfrom(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&caddr,&len)<0)
  62. {
  63. perror("recvfrom err");
  64. return -1;
  65. }
  66. if(msg.type==Login)
  67. {
  68. strcpy(msg.text,"已上线");
  69. printf("ip:%s pord:%d name:%s\n",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port),msg.name);
  70. printf("状态:%s\n",msg.text);
  71. do_login(sockfd,msg,p,caddr);
  72. }
  73. else if(msg.type==Chat)
  74. {
  75. do_chat(sockfd,msg,p,caddr);
  76. }
  77. else if(msg.type==Quit)
  78. {
  79. strcpy(msg.text,"已下线");
  80. printf("ip:%s pord:%d name:%s\n",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port),msg.name);
  81. printf("状态:%s\n",msg.text);
  82. do_quit(sockfd,msg,p,caddr);
  83. }
  84. }
  85. close(sockfd);
  86. return 0;
  87. }
  88. //登录的函数
  89. //功能:
  90. //1》将新登录的用户转发给所有已经登录的用户(遍历链表发送谁登录的消息)
  91. //2》创建新节点来保存新登录用户的信息,链接到链表尾就可已
  92. void do_login(int sockfd,msg_t msg,node_t *p,struct sockaddr_in caddr)
  93. {
  94. sprintf(msg.text,"%s 已上线",msg.name);
  95. while(p->next != NULL)
  96. {
  97. p= p->next;
  98. sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&(p->caddr),sizeof(p->caddr));
  99. //printf("%s\n",msg.text);
  100. }
  101. node_t *new=(node_t *)malloc(sizeof(node_t));
  102. //初始化
  103. new->caddr=caddr;
  104. new->next=NULL;
  105. //链接到链表尾
  106. p->next=new;
  107. return;
  108. }
  109. //群聊的函数
  110. //功能:将客户端发来的聊天内容转发给所有已登录的用户,除了发送聊天内容的用户已外
  111. void do_chat(int sockfd,msg_t msg,node_t *p,struct sockaddr_in caddr)
  112. {
  113. //遍历链表
  114. while(p->next != NULL)
  115. {
  116. p=p->next;
  117. if(memcmp(&(p->caddr),&caddr,sizeof(caddr)) != 0)
  118. {
  119. sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&(p->caddr),sizeof(p->caddr));
  120. }
  121. }
  122. return;
  123. }
  124. //退出函数
  125. //功能:
  126. //1》将谁退出的消息转发给i所有用户
  127. //2》将链表中保存这个推出的用户信息的节点删除
  128. void do_quit(int sockfd,msg_t msg,node_t *p,struct sockaddr_in caddr)
  129. {
  130. sprintf(msg.text,"%s 已下线",msg.name);
  131. while(p->next != NULL)
  132. {
  133. if((memcmp(&(p->next->caddr),&caddr,sizeof(caddr)))==0)
  134. {
  135. node_t *dele=NULL;
  136. dele = p->next;
  137. p->next=dele->next;
  138. free(dele);
  139. dele=NULL;
  140. }
  141. else
  142. {
  143. p=p->next;
  144. sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&(p->caddr),sizeof(p->caddr));
  145. }
  146. }
  147. return;
  148. }

客户端

  1. #include <myhead.h>
  2. enum type_t
  3. {
  4. Login,
  5. Chat,
  6. Quit,
  7. };
  8. typedef struct
  9. {
  10. char type;//L C Q
  11. char name[32];//
  12. char text[128];//
  13. }msg_t;
  14. int main(int argc, char const *argv[])
  15. {
  16. if(argc !=3)
  17. {
  18. printf("Usage ./a.out <ip> <port>\n");
  19. return -1;
  20. }
  21. int sockfd = socket(AF_INET,SOCK_DGRAM,0);
  22. if(sockfd<0)
  23. {
  24. perror("socket err");
  25. exit(-1);
  26. }
  27. struct sockaddr_in serveraddr;
  28. serveraddr.sin_family=AF_INET;
  29. serveraddr.sin_port=htons(atoi(argv[2]));
  30. serveraddr.sin_addr.s_addr=inet_addr(argv[1]);
  31. socklen_t len = sizeof(serveraddr);
  32. msg_t msg;
  33. //先执行登录操作
  34. printf("请登录:\n");
  35. msg.type=Login;
  36. printf("请输入用户名:");
  37. fgets(msg.name,32,stdin);
  38. if(msg.name[strlen(msg.name)-1]=='\n')
  39. msg.name[strlen(msg.name)-1]='\0';
  40. //发送登录消息
  41. if(sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&serveraddr,len)<0)
  42. {
  43. perror("sendto err");
  44. exit(-1);
  45. }
  46. pid_t pid=fork();
  47. if(pid<0)
  48. {
  49. perror("fork err");
  50. exit(-1);
  51. }
  52. else if(pid==0)
  53. {
  54. while(1)
  55. {
  56. if(recvfrom(sockfd,&msg,sizeof(msg),0,NULL,NULL)<0)
  57. {
  58. perror("recvfrom err");
  59. return -1;
  60. }
  61. printf("[%s]:%s\n",msg.name,msg.text);
  62. }
  63. }
  64. else
  65. {
  66. while(1)
  67. {
  68. fgets(msg.text,sizeof(msg.text),stdin);
  69. if(msg.text[strlen(msg.text)-1]=='\n')
  70. msg.text[strlen(msg.text)-1]='\0';
  71. if(strcmp(msg.text,"quit")==0)
  72. {
  73. msg.type=Quit;
  74. sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&serveraddr,len);
  75. kill(pid,SIGKILL);
  76. wait(NULL);
  77. exit(-1);
  78. }else
  79. {
  80. msg.type=Chat;
  81. }
  82. //发送消息
  83. sendto(sockfd,&msg,sizeof(msg),0,(struct sockaddr *)&serveraddr,len);
  84. }
  85. }
  86. close(sockfd);
  87. return 0;
  88. }

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

闽ICP备14008679号