当前位置: 首页 > news >正文

网络编程练习:UDP聊天室

 【1】服务器代码

#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "head.h"// 服务器-------------------------------------------------------------------------》短信的接收方/*创建一个空的单向链表*/
Node_p Create();/*登录,聊天,退出*/
void login(int fd_s, Msg msg, Node_p p, struct sockaddr_in caddr);
void chat(int fd_s, Msg msg, Node_p p, struct sockaddr_in caddr);
void quit(int fd_s, Msg msg, Node_p p, struct sockaddr_in caddr);int main(int argc, char const *argv[])
{int fd_s;// 1.创建数据报套接字(socket)------------------》有手机fd_s = socket(AF_INET, SOCK_DGRAM, 0);if (fd_s < 0){perror("soc err\n");return -1;}// printf("%d\n", fd_s);// 2.指定网络信息--------------------------------------》有号码struct sockaddr_in saddr, caddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(atoi(argv[1]));saddr.sin_addr.s_addr = INADDR_ANY;int len = sizeof(caddr);// 3.绑定套接字(bind)------------------------------》绑定手机if (bind(fd_s, (struct sockaddr *)&saddr, sizeof(saddr)) < 0){perror("bind err\n");return -1;}// printf("bind ok\n");printf("欢迎使用欢欢聊天室\n");Msg msg;Node_p p = Create(); // 创建空链表pid_t pid;pid = fork(); // 创建新进程if (pid < 0){perror("fork err\n");return -1;}else if (pid == 0){fgets(msg.text, sizeof(msg.text), stdin);if (msg.text[strlen(msg.text) - 1] == '\n')msg.text[strlen(msg.text) - 1] = '\0';msg.type = 'C';strcpy(msg.name, "server");sendto(fd_s, &msg, sizeof(msg), 0, (struct sockaddr *)&saddr, len);}else{// 4.接收、发送消息(recvfrom sendto)-------》收短信while (1){int ret;ret = recvfrom(fd_s, &msg, sizeof(msg), 0, (struct sockaddr *)&caddr, &len);if (ret < 0){perror("recv err\n");return -1;}// printf("addr: %s  port: %d\n", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));if (msg.type == 'L'){// printf("addr: %s  port: %d\n", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));printf("<%s> 已登录\n", msg.name);sprintf(msg.text, "<%s> 已登录", msg.name);login(fd_s, msg, p, caddr);}else if (msg.type == 'C'){printf("[%s]: %s\n", msg.name, msg.text);chat(fd_s, msg, p, caddr);}else if (msg.type == 'Q'){sprintf(msg.text, "<%s> 已下线", msg.name);printf("<%s> 已下线\n", msg.name);quit(fd_s, msg, p, caddr);}}}// 5.关闭套接字(close)----------------------------》接收完毕close(fd_s);return 0;
}/*创空表*/
Node_p Create()
{Node_p p = (Node_p)malloc(sizeof(Node_t)); // 开辟一个节点大小的堆区空间if (NULL == p)                             // 开辟失败{printf("malloc lost");return NULL;}p->next = NULL; // 初始化头节点指针域return p;       // 开辟成功,返回
}/*登录*/
void login(int fd_s, Msg msg, Node_p p, struct sockaddr_in caddr)
{while (p->next != NULL){p = p->next;sendto(fd_s, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->addr), sizeof(p->addr));}/*创建新的节点*/Node_p p_new = (Node_p)malloc(sizeof(Node_t));if (p_new == NULL){perror("malloc err\n");return;}/*初始化节点*/p_new->addr = caddr;p_new->next = NULL;/*将新节点连接到链表中*/p->next = p_new;// p = p_new;return;
}/*聊天*/
void chat(int fd_s, Msg msg, Node_p p, struct sockaddr_in caddr)
{while (p->next != NULL){p = p->next;if ((memcmp(&(p->addr), &caddr, sizeof(caddr))) == 0){continue;}sendto(fd_s, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->addr), sizeof(p->addr));}
}/*退出*/
void quit(int fd_s, Msg msg, Node_p p, struct sockaddr_in caddr)
{while (p->next != NULL){if ((memcmp(&(p->next->addr), &caddr, sizeof(caddr))) == 0){Node_p p_del = NULL;p_del = p->next;p->next = p_del->next;free(p_del);p_del = NULL;continue;}else{p = p->next;sendto(fd_s, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->addr), sizeof(p->addr));}}return;
}

【2】客户端代码 

#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include "head.h"
#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>// 客户端---------------------------------------------------------------------------》短信的发送方struct sockaddr_in saddr;
int len = sizeof(saddr);int main(int argc, char const *argv[])
{// 1.创建数据报套接字(socket)------------------》有手机int fd_c;fd_c = socket(AF_INET, SOCK_DGRAM, 0);if (fd_c < 0){perror("soc err\n");return -1;}// printf("%d\n", fd_c);// 2.指定网络信息--------------------------------------》有对方号码saddr.sin_family = AF_INET;saddr.sin_port = htons(atoi(argv[1]));saddr.sin_addr.s_addr = inet_addr("192.168.31.187");Msg msg;msg.type = 'L';printf("欢迎使用欢欢聊天室\n");printf("请输入用户名:");fgets(msg.name, N, stdin);if (msg.name[strlen(msg.name) - 1] == '\n')msg.name[strlen(msg.name) - 1] = '\0';sendto(fd_c, &msg, sizeof(msg), 0, (struct sockaddr *)&saddr, sizeof(saddr));pid_t pid = fork();if (pid < 0){perror("fork err");exit(-1);}else if (pid == 0){while (1){if (recvfrom(fd_c, &msg, sizeof(msg), 0, NULL, NULL) < 0){perror("recvfrom err");return -1;}if (msg.type == 'L')printf("%s\n", msg.text);else if (msg.type == 'C')printf("[%s]:%s\n", msg.name, msg.text);else if (msg.type == 'Q')printf("%s\n", msg.text);}}else{while (1){fgets(msg.text, sizeof(msg.text), stdin);if (msg.text[strlen(msg.text) - 1] == '\n')msg.text[strlen(msg.text) - 1] = '\0';if (strcmp(msg.text, "quit") == 0){msg.type = 'Q';sendto(fd_c, &msg, sizeof(msg), 0, (struct sockaddr *)&saddr, len);kill(pid, SIGKILL);wait(NULL);exit(-1);}else{ msg.type = 'C';}// 发送消息sendto(fd_c, &msg, sizeof(msg), 0, (struct sockaddr *)&saddr, len);}}close(fd_c);return 0;
}

今天的分享就到这里结束啦,如果有哪里写的不好的地方,请指正。
如果觉得不错并且对你有帮助的话点个关注支持一下吧!


http://www.mrgr.cn/news/31267.html

相关文章:

  • 虚拟机安装nginx需要注意的一些事项
  • Linux 进程3
  • 5G技术对IT行业的影响及未来发展
  • 操作系统 | 学习笔记 | | 王道 | 5.2 设备独立软件
  • OpenAi assistant run always fails when called from PHP
  • 基于嵌入式的智能物流柜( 触摸屏/0.96寸oled屏)
  • pytorch快速入门(一)—— 基本工具及平台介绍
  • Bigemap GIS Office 2024注册机 全能版地图下载软件
  • nginx常用配置及调优
  • 力扣题解(统计特殊整数)
  • 使用adb命令进行内存测试
  • Jenkins自动化部署后端项目看这篇就够了
  • 万魔头戴式耳机怎么样?万魔、西圣、JBL三款旗舰机型激战评测!
  • Vue 修饰符 | 指令 区别
  • 【秋招笔试】09.20-58同城秋招(已改编)-三语言题解
  • Python基础
  • Python教你用20行代码做一个骰子模拟博弈游戏
  • Rocprofiler测试
  • Redis-01 入门和十大数据类型
  • 2024年8月月终总结