赞
踩
1.如果有用户登录,其他用户可以收到这个人的登录信息
2.如果有人发送信息,其他用户可以收到这个人的群聊信息
3.如果有人下线,其他用户可以收到这个人的下线信息
4.服务器可以发送系统信息
- #ifndef UDP_H
- #define UDP_H
- #include <myhead.h>
- #define SER_PORT 8888 // 服务器端口号
- #define SER_IP "192.168.0.105" // 服务器ip地址
- #define CLI_PORT 5555 // 客户端端口号
- #define CLI_IP "192.168.0.105" // 客户端地址
- //枚举
- enum type_t
- {
- Login,
- Chat,
- Quit,
- };
- typedef struct MSG
- {
- char type;//Login名字 Chat内容 Quit退出 //内容编号
- char name[32];//名字
- char text[128];//内容
- }msg_t;
- typedef struct NODE//链表
- {
- struct sockaddr_in cin;
- struct NODE *next;
- }Node,*Nodeptr;
- //创建头节点函数
- Nodeptr create();
- //登录的函数
- //功能:
- //1.将新登录的用户转发给所有已经登录的用户(遍历链表发送谁登录的消息)
- //2.创建新节点来保存新登录用户的信息,链接到链表尾就可以
- void do_login(int sockfd,msg_t msg,Nodeptr p,struct sockaddr_in cin);
- //群聊的函数
- //功能:将客户端发来的聊天内容转发给所有已登录的用户,除了发送聊天内容的用户以外
- void do_chat(int sockfd,msg_t msg,Nodeptr p,struct sockaddr_in cin);
- //退出函数
- //功能:
- //1.将谁退出的消息转发给i所有用户
- //2.将链表中保存这个推出的用户信息的节点删除
- void do_quit(int sockfd,msg_t msg,Nodeptr p,struct sockaddr_in cin);
- #endif
- #include "udp.h"
- // 定义创建头节点函数
- Nodeptr create()
- {
- Nodeptr p = (Nodeptr)malloc(sizeof(Node));
- if (p == NULL)
- {
- perror("malloc error");
- return NULL;
- }
- p->next = NULL;
- return p;
- }
- // 定义登录的函数
- void do_login(int sockfd, msg_t msg, Nodeptr p, struct sockaddr_in cin)
- {
- sprintf(msg.text, "%s 以上线", msg.name);
- while (p->next != NULL)
- {
- p = p->next;
- sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->cin), sizeof(p->cin));
- }
- Nodeptr new = (Nodeptr)malloc(sizeof(Node));
- // 初始化
- new->cin = cin;
- new->next = NULL;
- // 链接到链表尾
- p->next = new;
- return;
- }
- // 定义群聊的函数
- void do_chat(int sockfd, msg_t msg, Nodeptr p, struct sockaddr_in cin)
- {
- // 遍历链表
- while (p->next != NULL)
- {
- p = p->next;
-
- if (memcmp(&(p->cin), &cin,sizeof(cin))!= 0)
- {
- sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->cin), sizeof(p->cin));
- }
- }
- return;
- }
- // 定义退出函数
- void do_quit(int sockfd, msg_t msg, Nodeptr p, struct sockaddr_in cin)
- {
- sprintf(msg.text, "%s 以下线", msg.name);
- while (p->next != NULL)
- {
- if (memcmp(&(p->cin), &cin,sizeof(cin)) == 0)
- {
- Nodeptr q = NULL;
- q = p->next;
- p->next = q->next;
- free(q);
- q = NULL;
- }
- else
- {
- p = p->next;
- sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(p->cin), sizeof(p->cin));
- }
- }
- return;
- }
- // 服务器
- #include "udp.h"
- int main(int argc, char const *argv[])
- {
- // 创建UDP套接字
- int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if (sockfd < 0)
- {
- perror("socket error");
- exit(-1);
- }
- // 填充服务器网络信息结构体
- //定义服务器结构体
- struct sockaddr_in sin;
- sin.sin_family=AF_INET;
- sin.sin_port = htons(SER_PORT);
- sin.sin_addr.s_addr = inet_addr(SER_IP);
-
- // 定义保存客户端网络信息的结构体
- struct sockaddr_in cin;
- cin.sin_family = AF_INET;
- cin.sin_port = htons(CLI_PORT);
- cin.sin_addr.s_addr = inet_addr(CLI_IP);
- socklen_t len = sizeof(cin);
- // 绑定套接字和服务器网络信息的结构体
- bind(sockfd, (struct sockaddr *)&sin, sizeof(sin));
- printf("绑定成功!\n");
- msg_t msg;
- Nodeptr p = create();
- char s[20]="";
- while (1)
- {
- if (recvfrom(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&cin, &len) < 0)
- {
- perror("recvfrom error");
- return -1;
- }
- if (msg.type == Login)
- {
- strcpy(msg.text, "以上线");
- printf("ip:%s pord:%d name:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), msg.name);
- printf("状态:%s\n", msg.text);
- //调用登录函数
- do_login(sockfd, msg, p, cin);
- }
- else if (msg.type == Chat)
- {
- //调用群聊函数
- do_chat(sockfd, msg, p, cin);
- }
- else if (msg.type == Quit)
- {
- strcpy(msg.text, "以下线");
- printf("ip:%s pord:%d name:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), msg.name);
- printf("状态:%s\n", msg.text);
- //调用退出函数
- do_quit(sockfd, msg, p, cin);
- }
- }
- close(sockfd);
- return 0;
- }
- // 客户端
- #include "udp.h"
- int main(int argc, char const *argv[])
- {
- int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if (sockfd < 0)
- {
- perror("socket error");
- exit(-1);
- }
- struct sockaddr_in sin;
- sin.sin_family = AF_INET;
- sin.sin_port = htons(SER_PORT);
- sin.sin_addr.s_addr = inet_addr(SER_IP);
- socklen_t len = sizeof(sin);
- msg_t msg;
- // 先执行登录操作
- printf("请登录:\n");
- msg.type = Login;
- printf("请输入用户名:");
- fgets(msg.name, 32, stdin);
- msg.name[strlen(msg.name) - 1] = 0;
- // 发送登录消息
- if (sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&sin, len) < 0)
- {
- perror("sendto err");
- exit(-1);
- }
- //创建多进程
- pid_t pid = fork();
- if (pid < 0)
- {
- perror("fork error");
- exit(-1);
- }
- else if (pid == 0)
- {
- while (1)
- {
- if (recvfrom(sockfd, &msg, sizeof(msg), 0, NULL, NULL) < 0)
- {
- perror("recvfrom error");
- return -1;
- }
- printf("[%s]:%s\n", msg.name, msg.text);
- }
- }
- else
- {
- while (1)
- {
- fgets(msg.text, sizeof(msg.text), stdin);
- msg.text[strlen(msg.text) - 1] = 0;
- if (strcmp(msg.text, "quit") == 0)
- {
- msg.type = Quit;
- sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&sin, len);
- kill(pid, SIGKILL);
- wait(NULL);
- exit(EXIT_SUCCESS);
- }
- else
- {
- msg.type = Chat;
- }
- // 发送消息
- sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&sin, len);
- }
- }
- close(sockfd);
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。