这是一个最近写的小项目,想要总结一下,如有不合理地方,请多指教!

一、项目名称

基于UDP的群聊聊天室

二、实现功能:

1.有新用户登录,其他在线的用户可以收到登录信息

2.有用户群聊,其他在线的用户可以收到群聊信息

3.有用户退出,其他在线的用户可以收到退出信息

4.服务器可以发送系统信息

三、初步构思

1.服务器需要给多个用户发送信息,需要创建链表保存各用户的网络信息。

2.消息类型有四种,上线、群聊、退出、系统消息,需要定义消息结构体,结构体中需要包含信息操作码、用户名、消息数据。

四、流程图

客户端:

服务器:

五、代码实现

服务器代码:server.c

#include "chat.h"int main(int argc,const char *argv[]){/*your code*/if(3 != argc){printf("usage: <%s> <ip> <port>\n", argv[0]);return -1;}//创建套接字int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(-1 == sockfd)ERRLOG("socket error");//填充服务器网络信息结构体struct sockaddr_in serveraddr;serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(atoi(argv[2]));serveraddr.sin_addr.s_addr = inet_addr(argv[1]);socklen_t serveraddrlen = sizeof(serveraddr);//设置客户端网络信息结构体struct sockaddr_in clientaddr;memset(&clientaddr, 0, sizeof(clientaddr));socklen_t clientaddrlen = sizeof(clientaddr);//绑定套接字和网络信息结构体if(-1 == bind(sockfd, (struct sockaddr *)&serveraddr, serveraddrlen))ERRLOG("bind error");//linklist_t* h = LinkListCreate();msg_t msg;pid_t pid;pid = fork();if(-1 == pid){ERRLOG("fork error");}else if(0 == pid){//子进程while(1){if(-1 == recvfrom(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&clientaddr, &clientaddrlen))ERRLOG("recvfrom error");switch(msg.code){case L:login(msg, clientaddr, sockfd, h);break;case C:chat(msg, clientaddr, sockfd, h);break;case Q:quit(msg, clientaddr, sockfd, h);break;}}}else{//父进程strcpy(msg.name, "server");msg.code = C;while(1){fgets(msg.txt, sizeof(msg.txt), stdin);msg.txt[strlen(msg.txt)-1] = '\0';if(-1 == sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&serveraddr, serveraddrlen))ERRLOG("sendto error");}}close(sockfd);return 0;
}

客户端代码:client.c

#include "chat.h"int main(int argc,const char *argv[]){/*your code*/if(3 != argc){printf("usage: <%s> <ip> <port>\n", argv[0]);return -1;}//创建套接字int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(-1 == sockfd)ERRLOG("socket error");//填充服务器网络信息结构体struct sockaddr_in serveraddr;serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(atoi(argv[2]));serveraddr.sin_addr.s_addr = inet_addr(argv[1]);socklen_t serveraddrlen = sizeof(serveraddr);//msg_t msg;printf("输入用户名: ");fgets(msg.name, sizeof(msg.name), stdin);msg.name[strlen(msg.name)-1] = '\0';msg.code = L;strcpy(msg.txt, "加入群聊");if(-1 == sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&serveraddr, serveraddrlen))ERRLOG("sendto error");//pid_t pid;pid = fork();if(-1 == pid){ERRLOG("fork error");}else if(0 == pid){//子进程while(1){if(-1 == recvfrom(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&serveraddr, &serveraddrlen))ERRLOG("recv error");printf("[%s:%s]\n", msg.name, msg.txt);}}else{//父进程msg.code = C;while(1){// printf("输入: ");fgets(msg.txt, sizeof(msg.txt), stdin);msg.txt[strlen(msg.txt)-1] = '\0';if(0 == strcmp(msg.txt, "quit")){msg.code = Q;strcpy(msg.txt, "退出群聊");if(-1 == sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&serveraddr, serveraddrlen))ERRLOG("sendto error");break;}if(-1 == sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&serveraddr, serveraddrlen))ERRLOG("sendto error");}kill(pid, SIGKILL);wait(NULL);}close(sockfd);return 0;
}

封装函数:chat.c

#include "chat.h"linklist_t* LinkListCreate(){linklist_t* h = (linklist_t* )malloc(sizeof(*h));if(h == NULL){printf("malloc error\n");return NULL;}h->next = NULL;return h;
}
void LinkListInsertTail(linklist_t* h, struct sockaddr_in clientaddr){linklist_t* temp = (linklist_t* )malloc(sizeof(*temp));if(temp == NULL){printf("malloc error\n");return;}  temp->clientaddr = clientaddr;while(h->next != NULL){h = h->next;}temp->next = h->next;h->next = temp;return;
}
void login(msg_t msg, struct sockaddr_in clientaddr, int sockfd, linklist_t* h){printf("%s进入聊天室...\n", msg.name);linklist_t* th;th = h;sprintf(msg.txt, "进入聊天室...\n");while(th->next != NULL){printf("-----\n");th = th->next;if(-1 == sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(th->clientaddr), sizeof(clientaddr)))ERRLOG("sendto error");}LinkListInsertTail(h, clientaddr);
}
void chat(msg_t msg, struct sockaddr_in clientaddr, int sockfd, linklist_t* h){printf("[%s:%s]\n", msg.name, msg.txt);linklist_t* th;th = h;while(th->next != NULL){th = th->next;// strcmp(h->clientaddr.sin_addr.s_addr, clientaddr.sin_addr.s_addr)if(memcmp(&clientaddr, &(th->clientaddr), sizeof(clientaddr))){if(-1 == sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(th->clientaddr), sizeof(clientaddr)))ERRLOG("sendto error");}}return;
}
void quit(msg_t msg, struct sockaddr_in clientaddr, int sockfd, linklist_t* h){printf("退出聊天室...\n");linklist_t* th;linklist_t* temp;th = h;while(th->next != NULL){if(memcmp(&clientaddr, &(th->next->clientaddr), sizeof(clientaddr))){th = th->next;if(-1 == sendto(sockfd, &msg, sizeof(msg), 0, (struct sockaddr *)&(th->clientaddr), sizeof(clientaddr)))ERRLOG("sendto error");}else{temp = th->next;th->next = temp->next;if(temp != NULL){free(temp);}temp = NULL;}}return;
}

chat.h

#ifndef __CHAT_H__
#define __CHAT_H__#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>#define ERRLOG(msg) do{\printf("%s:%s:%d\n", __FILE__, __func__, __LINE__);\perror(msg);\exit(-1);\}while(0)typedef struct {char code;char name[32];char txt[128];
} msg_t;#define L 1 //登录
#define C 2 //群聊
#define Q 3 //退出typedef struct node {struct sockaddr_in clientaddr;struct node* next;
} linklist_t;linklist_t* LinkListCreate();
void LinkListInsertTail(linklist_t* h, struct sockaddr_in clientaddr);
void login(msg_t msg, struct sockaddr_in clientaddr, int sockfd, linklist_t* h);
void chat(msg_t msg, struct sockaddr_in clientaddr, int sockfd, linklist_t* h);
void quit(msg_t msg, struct sockaddr_in clientaddr, int sockfd, linklist_t* h);
#endif

六、最终效果

基于UDP的群聊聊天室相关推荐

  1. UDP实现群聊聊天室

    UDP实现群聊聊天室 ​ 大家好,今天为大家带来了一个非常有意思的小程序--UDP实现的群聊聊天室.这个程序使用的UDP协议,并使用DatagramSocket的子类MulticastSocket实现 ...

  2. Java培训:UDP实现群聊聊天室

    大家好,今天为大家带来了一个非常有意思的小程序--UDP实现的群聊聊天室.这个程序使用的UDP协议,并使用DatagramSocket的子类MulticastSocket实现组播,可以部署在一个局域网 ...

  3. 使用UDP实现群聊聊天室

    今天为大家带来了一个非常有意思的小程序--UDP实现的群聊聊天室.这个程序使用的UDP协议,并使用DatagramSocket的子类MulticastSocket实现组播,可以部署在一个局域网内的多台 ...

  4. 基于python3的群聊聊天室

    码云地址 基于websocket 开源聊天室 chatroom: 非常简单的聊天 具有高匿名聊天作用本项目使用 python3 + html5 + websocket + gzip github地址: ...

  5. Python3群聊聊天室

    类似群聊 需求 有人进入聊天室需要输入姓名,姓名不能重复 有人进入聊天室时,其他人会收到通知:xxx 进入了聊天室 一个人发消息,其他人会收到:xxx : xxxxxxxxxxx 有人退出聊天室,则其 ...

  6. 【基于UDP的网络聊天室】

    总结下近期写的小项目,在学习中同时积累解决问题的经验,以及真正的项目中解决问题的思路,如有不合理地方,请多指教! 一.项目名称 基于UDP的网络聊天室 二.功能 1.当有新用户登录时,其他在线用户可以 ...

  7. 基于UDP的网络聊天室网络编程0811作业-洪庆乐

    项目:基于UDP的网络聊天室 功能:1.服务器日志系统,且可以查看(实现) 2.有用户,其他用户收到这个人登入信息(实现) 3.群发消息(实现) 4.如果有用户下线,其他用户收到下线消息(实现) 5. ...

  8. Java网络编程——基于UDP协议的聊天室

    UDP简述    UDP(User Datagram Protocol)协议是Internet 协议集支持的一个无连接的传输协议,中文名为用户数据报协议.它为应用程序提供了一种无需建立连接就可以发送封 ...

  9. Java网络编程,使用Java实现UDP和TCP网络通信协议,以及基于UDP的在线聊天室。

    文章目录 前言 一.网络编程概念 1.网络 2. 网络编程的目的 3.想要达到这个效果需要什么 4.网络分层 二.网络编程Java类 1.IP地址:InetAddress 2.端口 3.TCP连接 3 ...

最新文章

  1. java继承详解加练习题
  2. R语言使用dplyr聚合统计分组数据、ggplot2可视化分组线图、使用geom_line函数自定义设置线条类型、粗细、颜色(Change line types + colors by groups)
  3. 扎克伯格又被黑,这次是他的 Pinterest 账号
  4. Spring Cloud Alibaba - 12 使用Nacos的元数据实现金丝雀发布功能
  5. 使用apache的HttpGet\HttpPost获取返回内容编码问题
  6. javascript-按圆形排列DIV元素(三)实例---- 图片按椭圆形转动
  7. mysql 查看锁_MySQL反应慢的排查思路
  8. 我最喜欢的Java高级开发人员书籍
  9. windows修改时间服务器,在Windows中设置时间服务器 2012 R2
  10. nagios监控之(监控配置)
  11. sqlite3_column
  12. 魅思V20全新正规视频系统源码
  13. mpu6050 z轴校准_大渡口区上门校正检定量具外校-第三方检测计量出校准证书
  14. 学web前端开发写给新手的建议,超实用
  15. CentOS7下如何正确安装并启动Docker(图文详解)
  16. 北京市市级行政区界线
  17. python+selenium 自动拖拽滑块
  18. matlab中matconvnet,MATLAB2017a编译MatConvNet过程中出现的各种问题
  19. web手机服务器系统,web手机服务器系统
  20. Java 生成数字证书系列(四)生成数字证书(续)

热门文章

  1. 商场三十六计——第2计 “围魏救赵”
  2. java学习的步骤_Java Learning Path (by Evan)
  3. MySQL基本概念以及简单操作
  4. 个人下载mysql什么版本_Mysql各个版本区别及官网下载
  5. python transpose函数_numpy中transpose和swapaxes函数讲解
  6. 【SCADA案例】智能楼宇/家居的远程监控示例
  7. 【运维篇】resize2fs命令 – 调整文件系统大小
  8. 开源支付系统,助你快速开发支付功能
  9. 删除win7下的系统托盘缓存
  10. Slowfast环境配置问题 | 安装PyAV报错An error occurred while installing package ‘conda-forge::olefile-0.46-pyh9f