




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、基于Linux C的socket聊天室1 系统功能 11 支持群聊天。1. 2 支持向指定用户发送悄悄话功能。1. 3 支持不同消息不同颜色显示。1. 4 用户名为登录的唯一标示,所以不允许重名,客户端登录具有重名检查功能。1. 5 支持上线下线通知。1. 6 支持服务器发送系统消息功能。1. 7 支持登录时检测服务器是否在线。1. 8 支持服务器下线通知客户端,客户端强行下线。2 硬件平台21 功能 用来作为对Linux C程序所用软件以及操作系统的安装的载体, 2. 2 特点 计算机的整体配置还算不错,4G内存,500G硬盘,1G独立显卡等,使得运行一般的大游戏都不卡。2. 3 组成 K4
2、3T系列华硕计算机一台,外加键盘一个。3 软件平台31 操作系统平台 主要有Windows7操作系统和ubuntu操作系统,电脑以安装Window7为主,ubuntu操作系统以虚拟系统的方式安装在电脑上。3. 2 系统软件平台 主要用到的软件有:Linux的ubuntu操作系统,VMware Workstation软件,Window7下的记事本软件,wps软件和CodeBlocks C编程软件以及GCC编译器等等。3. 3 系统设计3.3.1模块设计 主要写了两个模块程序,一个是服务端程序,另一个是客户端程序,在服务端程序主要完成对服务的基本配置以及对客户端程序的一些初始化参数进行设计等,实现
3、端用户聊天的功能。在客户端程序里,完成对客户信息的封装,可以供多个客户同时登陆,并能对错误信息给出对应的提示,方便用户使用。服务程序文件盒客户端程序文件分别为server.c和client.c,使用Gcc来调试运行成server和client文件,先启动server程序,配置服务端信息,然后启动客户端client程序,用户登陆,进行聊天。 3.3.2 服务端程序server.c主要代码如下:typedef struct char name10;SA_IN address; USER;/XXX :用户链表typedef struct Hnode_list USER data;struct Hno
4、de_list *next; Hlink, *plink;int memoryError(plink p);int creatUserList(plink head);int findUser(plink head, char name10);int delUser(plink head, char name10);int getAllUser(plink const head);int addUser(plink head, USER data);/XXX :用户链表void ProcessLogin(char* command, SA_IN rec_addr);void ProcessCh
5、at(char* command);void ProcessQuit(char* command);int ProcessPrivate(char* command,SA_IN rec_addr);void ProcessAd();void sig_int(int signum);/ctl+c关掉服务器static plink head;static int socket_fd; int main(void) char bufBUFFERSIZE;SA_IN address, rec_addr;socklen_t length;struct timeval tv;tv.tv_sec=60;/插
6、播广告时间tv.tv_usec=0;head = malloc(sizeof(Hlink);/用户列表头creatUserList(head); /创建列表signal(SIGINT,sig_int);if (socket_fd = socket(AF_INET, SOCK_DGRAM, 0) = -1) perror("Socket creation fails");exit(-1);memset(&address, 0, sizeof(address);address.sin_family = AF_INET;address.sin_addr.s_addr =
7、inet_addr(SERVER_IP);address.sin_port = htons(SERVER_PORT);if (bind(socket_fd, (SA *) &address, sizeof(address) = -1) perror("Socket is bound to fail");exit(-1);/30秒没有收到任何消息就发送广告printf("The server to start successip:%sn",inet_ntoa(address.sin_addr);length = sizeof(rec_addr);s
8、etsockopt(socket_fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv);while (1) memset(buf,0,sizeof(buf);/服务器只有此处用来接收if (recvfrom(socket_fd, buf, sizeof(buf), 0, (SA *) &rec_addr, &length)= -1)buf0='A'/发送广告标志位switch (buf0) case 'L':/登录ProcessLogin(buf, rec_addr);break;case 'C'
9、;:/群聊天ProcessChat(buf);break;case 'Q':/退出ProcessQuit(buf);break;case 'A':/广告ProcessAd();break;case 'P':/悄悄话ProcessPrivate(buf,rec_addr);break;default:printf("ERROR");break;3.3.3 客户端client.c主要代码如下:#define BUFFERSIZE 1024typedef struct sockaddr SA;typedef struct socka
10、ddr_in SA_IN;#define SERVER_IP ""#define SERVER_PORT 8000void sig_user1(int signo);void sig_user2(int signo);void sig_alrm(int signo);char* ProcessLogin(SA_IN serv_addr);/以下为无关紧要的功能函数声明void dispDot();int msSleep(long ms);static pid_t pid;static int socket_fd;int main(void) char bu
11、fBUFFERSIZE;char buf_tempBUFFERSIZE;char name10;SA_IN serv_addr;signal(SIGUSR1, sig_user1);signal(SIGUSR2,sig_user2);signal(SIGINT,SIG_IGN);/拒绝用户ctrl+c强制退出,只能键入quit退出if (socket_fd = socket(AF_INET, SOCK_DGRAM, 0) = -1) perror("socket build error");exit(-1);/XXX:服务器配置信息memset(&serv_addr
12、, 0, sizeof(serv_addr);serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP);serv_addr.sin_port = htons(SERVER_PORT);/XXXstrcpy(name, ProcessLogin(serv_addr);/得到登录名if (pid = fork() = -1) perror("child process build error");return -1;if (pid = 0)/子进程,用来接收服务器的消息mems
13、et(buf,'0',BUFFERSIZE);/必须清空否则会有虚假数据memset(buf_temp,'0',BUFFERSIZE);sprintf(buf, "C%s On-line", name);if (sendto(socket_fd, buf, sizeof(buf), 0, (SA *) &serv_addr,sizeof(serv_addr) < 0) perror("On-line failure");kill(getppid(), SIGUSR1);/唤醒主进程让其输入while (1)
14、memset(buf,'0',BUFFERSIZE);/必须清空否则会有虚假数据memset(buf_temp,'0',BUFFERSIZE);if (recvfrom(socket_fd, buf, sizeof(buf), 0, NULL, NULL) < 0) perror("Receive messages failure"); if (strncmp("Q",buf,1) = 0) /接收服务器下线通知printf("03322;30m%s", buf+1); /输出黑色文字系统消息ki
15、ll(getppid(), SIGUSR2);kill(getpid(), SIGUSR2);else if (strncmp("A",buf,1) = 0)printf("03322;96m%s", buf+1); /输出灰色文字系统消息else if (strncmp("P",buf,1) = 0)printf("03322;31m%s", buf+1); /输出红色文字系统消息else if (strncmp("R",buf,1) = 0)if (strncmp(buf+1, name,
16、strlen(name) = 0)sprintf(buf_temp, "me%s", buf + strlen(name)+1);printf("03322;32m%s", buf_temp);/输出黄色文字自己的消息elseprintf("03322;33mMessages are received %s", buf+1); /输出绿色文字printf("03322;30m");/恢复黑色/主进程/pause();/等待SIGUSR1int quit_flag = 0;getchar();/清空输入名字时残存的回
17、车符,因为ProcessLogin使用scanfwhile (1)/父进程memset(buf,'0',BUFFERSIZE);/必须清空否则会有虚假数据memset(buf_temp,'0',BUFFERSIZE);fgets(buf_temp,BUFFERSIZE,stdin);/采用fgets比采用scanf好,聊天时可以键入空格buf_tempstrlen(buf_temp)-1='0'if (strncmp("quit", buf_temp, 4) = 0) /退出sprintf(buf, "Q%s&quo
18、t;, name);quit_flag = 1;/键入$开头为悄悄话else if (strncmp("$", buf_temp, 1) = 0) /注:发送悄悄话的格式:$对方名称$消息内容char *check=buf_temp+1;/必须对其检查一定要有两个$.$否则造成服务器当机while(*check!='0'&&*check!='$')check+;if(*check!='$')printf("system n message format: $ each other name $ mes
19、sage content n < enter >n");continue;sprintf(buf, "P%s%s", name,buf_temp);else /群发消息sprintf(buf, "C%s say:%s", name, buf_temp);/开始发送消息if (sendto(socket_fd, buf, sizeof(buf), 0, (SA *) &serv_addr,sizeof(serv_addr) < 0)perror("Send failure");if (quit_fla
20、g)kill(pid, SIGUSR2);break;kill(getpid(), SIGUSR2);4 系统测试测试数据及截图如下所示:5 系统源码5.1 服务端源码#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <dirent.h>#include <sys/types.h>#include <sys/socket.h>#include &l
21、t;netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include <netdb.h>#include <signal.h>#define BUFFERSIZE 1024typedef struct sockaddr SA;typedef struct sockaddr_in SA_IN;#define SERVER_IP ""#define SERVER_PORT 8000#include <time.h>typedef stru
22、ct char name10;SA_IN address; USER;/XXX :用户链表typedef struct Hnode_list USER data;struct Hnode_list *next; Hlink, *plink;int memoryError(plink p);int creatUserList(plink head);int findUser(plink head, char name10);int delUser(plink head, char name10);int getAllUser(plink const head);int addUser(plink
23、 head, USER data);/XXX :用户链表void ProcessLogin(char* command, SA_IN rec_addr);void ProcessChat(char* command);void ProcessQuit(char* command);int ProcessPrivate(char* command,SA_IN rec_addr);void ProcessAd();void sig_int(int signum);/ctl+c关掉服务器static plink head;static int socket_fd;int main(void) cha
24、r bufBUFFERSIZE;SA_IN address, rec_addr;socklen_t length;struct timeval tv;tv.tv_sec=60;/插播广告时间tv.tv_usec=0;head = malloc(sizeof(Hlink);/用户列表头creatUserList(head); /创建列表signal(SIGINT,sig_int);if (socket_fd = socket(AF_INET, SOCK_DGRAM, 0) = -1) perror("Socket creation fails");exit(-1);memse
25、t(&address, 0, sizeof(address);address.sin_family = AF_INET;address.sin_addr.s_addr = inet_addr(SERVER_IP);address.sin_port = htons(SERVER_PORT);if (bind(socket_fd, (SA *) &address, sizeof(address) = -1) perror("Socket is bound to fail");exit(-1);/30秒没有收到任何消息就发送广告printf("The s
26、erver to start successip:%sn",inet_ntoa(address.sin_addr);length = sizeof(rec_addr);setsockopt(socket_fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv);while (1) memset(buf,0,sizeof(buf);/服务器只有此处用来接收if (recvfrom(socket_fd, buf, sizeof(buf), 0, (SA *) &rec_addr, &length)= -1)buf0='A'/
27、发送广告标志位switch (buf0) case 'L':/登录ProcessLogin(buf, rec_addr);break;case 'C':/群聊天ProcessChat(buf);break;case 'Q':/退出ProcessQuit(buf);break;case 'A':/广告ProcessAd();break;case 'P':/悄悄话ProcessPrivate(buf,rec_addr);break;default:printf("ERROR");break;void
28、 ProcessLogin(char* command, SA_IN rec_addr) char name10;USER user;char bufBUFFERSIZE;memset(buf,'0',BUFFERSIZE);strcpy(name, command + 1);if (findUser(head, name) = -1) strcpy(, name);user.address = rec_addr;addUser(head, user);buf0 = 'Y'if (sendto(socket_fd, buf, sizeof(bu
29、f), 0, (SA *) &rec_addr,sizeof(rec_addr) = -1)perror("Login failed");else buf0 = 'N'if (sendto(socket_fd, buf, sizeof(buf), 0, (SA *) &rec_addr,sizeof(rec_addr) = -1)perror("Login failed");void ProcessChat(char* command) char bufBUFFERSIZE;SA_IN address;memset(buf
30、,'0',BUFFERSIZE);sprintf(buf, "R%sn<Please enter the>n", command + 1); /'n'强行推送数据必须否则要到缓冲区满才一次性发送plink p = head->next;while (p != NULL) address = (p->data).address;if (sendto(socket_fd, buf, sizeof(buf), 0, (SA *) &address,sizeof(address) < 0)perror("
31、;Message sent failure");p = p->next;void ProcessQuit(char* command) char name10;char bufBUFFERSIZE;memset(buf,'0',BUFFERSIZE);SA_IN address;sprintf(name, "%s", command + 1);plink p = head->next;delUser(head, name);sprintf(buf, "R%s Get offlinen", name);while (p
32、 != NULL) address = (p->data).address;if (sendto(socket_fd, buf, sizeof(buf), 0, (SA *) &address,sizeof(address) < 0) perror("Message sent failure");p = p->next;void ProcessAd()char bufBUFFERSIZE;char buf_tempBUFFERSIZE;memset(buf,'0',BUFFERSIZE);/必须清空否则会有虚假数据memset(bu
33、f_temp,'0',BUFFERSIZE);SA_IN address;plink p = head->next;strcat(buf,"A<<System message>>The current online usersn");while (p != NULL)sprintf(buf_temp,"%s:%s ", (p->data).name, inet_ntoa(p->data).address.sin_addr);strcat(buf,buf_temp);p = p->next;s
34、trcat(buf,"n<Please enter the>n");p = head->next;while (p != NULL) address = (p->data).address;if (sendto(socket_fd, buf, sizeof(buf), 0, (SA *) &address,sizeof(address) < 0) perror("Message sent failure");p = p->next;int ProcessPrivate(char* command,SA_IN r
35、ec_addr)char bufBUFFERSIZE;char buf_tempBUFFERSIZE;char name_from10;char name_to10;int non_user_flag=0;int i,j;for(i=1,j=0;commandi!='$'i+,j+)name_fromj=commandi;name_fromj='0'i+;for(j=0;commandi!='$'i+,j+)name_toj=commandi;name_toj='0'i+;memset(buf,'0',BUFFER
36、SIZE);/必须清空否则会有虚假数据memset(buf_temp,'0',BUFFERSIZE);strcpy(buf_temp,command+i);strcat(buf_temp,"n<Please enter the>n");/双方名字及消息准备就绪sprintf(buf,"Pfrom%sThe whispers%s",name_from,buf_temp);plink p = head->next;SA_IN address;while (p != NULL) if (strcmp(p->data).n
37、ame, name_to) = 0)address = (p->data).address;break;p = p->next;if (p = NULL)non_user_flag=1;if(!non_user_flag)if (sendto(socket_fd, buf, sizeof(buf), 0, (SA *) &address,sizeof(address) < 0)perror("Whispers send failure");sprintf(buf,"R%s Have received the message, the wi
38、sps sent successfullyn<Please enter the>n",name_to);if (sendto(socket_fd, buf, sizeof(buf), 0, (SA *) &rec_addr,sizeof(address) < 0)perror("Message sent failure");elsesprintf(buf,"R%s not on-line,Whispers send failuren<Please enter the>n",name_to);if (send
39、to(socket_fd, buf, sizeof(buf), 0, (SA *) &rec_addr,sizeof(address) < 0)perror("Whispers send failure");return 0;void sig_int(int signum)char bufBUFFERSIZE;plink p = head->next;SA_IN address;sprintf(buf,"Q The server is offlinen");while (p != NULL) address = (p->data
40、).address;if (sendto(socket_fd, buf, sizeof(buf), 0, (SA *) &address,sizeof(address) < 0) perror("Offline messages sent to the client");p = p->next;printf("Server is shut downn");exit(0);/XXX:使用带头结点的单向链表 存放用户信息int memoryError(plink p) /判断内存是否申请成功if (p = NULL) printf(&qu
41、ot;MEMORY ERROR!");return 1;return 0;int creatUserList(plink head) if (memoryError(head)return -1;head->next = NULL;int addUser(plink head, USER data) /始终在表头插入plink new_create = malloc(sizeof(Hlink);if (memoryError(new_create)return -1;new_create->data = data;new_create->next = head-&g
42、t;next;head->next = new_create;int delUser(plink head, char name10) plink q = head;plink p = head->next;while (p != NULL) if (strcmp(p->data).name, name) = 0)break;q = p;p = p->next;if (p = NULL) printf("Delete user failuren");return -1;q->next = p->next;free(p);p = NULL;
43、int findUser(plink head, char name10) plink p = head->next;while (p != NULL) if (strcmp(p->data).name, name) = 0)return 0;p = p->next;if (p = NULL)return -1;5.2 客户端源码#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#i
44、nclude <dirent.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <errno.h>#include <netdb.h>#include <signal.h>#define BUFFERSIZE 1024typedef struct sockaddr SA;typedef struct sockaddr_in SA_IN;#define
45、 SERVER_IP ""#define SERVER_PORT 8000void sig_user1(int signo);void sig_user2(int signo);void sig_alrm(int signo);char* ProcessLogin(SA_IN serv_addr);/以下为无关紧要的功能函数声明void dispDot();int msSleep(long ms);static pid_t pid;static int socket_fd;int main(void) char bufBUFFERSIZE;char buf
46、_tempBUFFERSIZE;char name10;SA_IN serv_addr;signal(SIGUSR1, sig_user1);signal(SIGUSR2,sig_user2);signal(SIGINT,SIG_IGN);/拒绝用户ctrl+c强制退出,只能键入quit退出if (socket_fd = socket(AF_INET, SOCK_DGRAM, 0) = -1) perror("socket build error");exit(-1);/XXX:服务器配置信息memset(&serv_addr, 0, sizeof(serv_add
47、r);serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr(SERVER_IP);serv_addr.sin_port = htons(SERVER_PORT);/XXXstrcpy(name, ProcessLogin(serv_addr);/得到登录名if (pid = fork() = -1) perror("child process build error");return -1;if (pid = 0)/子进程,用来接收服务器的消息memset(buf,'0',B
48、UFFERSIZE);/必须清空否则会有虚假数据memset(buf_temp,'0',BUFFERSIZE);sprintf(buf, "C%s On-line", name);if (sendto(socket_fd, buf, sizeof(buf), 0, (SA *) &serv_addr,sizeof(serv_addr) < 0) perror("On-line failure");kill(getppid(), SIGUSR1);/唤醒主进程让其输入while (1) memset(buf,'0
49、9;,BUFFERSIZE);/必须清空否则会有虚假数据memset(buf_temp,'0',BUFFERSIZE);if (recvfrom(socket_fd, buf, sizeof(buf), 0, NULL, NULL) < 0) perror("Receive messages failure"); if (strncmp("Q",buf,1) = 0) /接收服务器下线通知printf("03322;30m%s", buf+1); /输出黑色文字系统消息kill(getppid(), SIGUSR
50、2);kill(getpid(), SIGUSR2);else if (strncmp("A",buf,1) = 0)printf("03322;96m%s", buf+1); /输出灰色文字系统消息else if (strncmp("P",buf,1) = 0)printf("03322;31m%s", buf+1); /输出红色文字系统消息else if (strncmp("R",buf,1) = 0)if (strncmp(buf+1, name, strlen(name) = 0)spr
51、intf(buf_temp, "me%s", buf + strlen(name)+1);printf("03322;32m%s", buf_temp);/输出黄色文字自己的消息elseprintf("03322;33mMessages are received %s", buf+1); /输出绿色文字printf("03322;30m");/恢复黑色/主进程/pause();/等待SIGUSR1int quit_flag = 0;getchar();/清空输入名字时残存的回车符,因为ProcessLogin使用s
52、canfwhile (1)/父进程memset(buf,'0',BUFFERSIZE);/必须清空否则会有虚假数据memset(buf_temp,'0',BUFFERSIZE);fgets(buf_temp,BUFFERSIZE,stdin);/采用fgets比采用scanf好,聊天时可以键入空格buf_tempstrlen(buf_temp)-1='0'if (strncmp("quit", buf_temp, 4) = 0) /退出sprintf(buf, "Q%s", name);quit_flag = 1;/键入$开头为悄悄话else if (strncmp("$", buf_temp, 1) = 0) /注:发送悄悄话的格式:$对方名称$消息内容char *check=buf_temp+1;/必须对其检查一定要有两个$.$否则造成服务器当机while(*check!='0'
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 电影拍摄道具的回收与再利用考核试卷
- 城市规划旅游规划与开发考核试卷
- 碳酸饮料行业的产品包装设计考核试卷
- 糖果国际贸易实务与谈判考核试卷
- 2025年的北京市房屋租赁合同
- 2025简化版企业间借款协议合同
- 2025劳动合同书(标准版本)
- 2025存量房买卖合同附件
- 苏溪镇某创业园(二)标准厂房工程、广西钦州某燃煤电厂一期2×600MW机组工程施工组织设计
- 苏教版化学高中化学必修2全集教案(送课件习题)
- 全国河大音像版初中信息技术八年级上册第三章第三节《循环结构程序设计》教学设计
- 企业健康管理计划规划方案讨论
- 隧道高空作业施工方案
- 危险性较大的分部分项工程专项施工方案严重缺陷清单(试行)
- 深信服超融合HCI技术白皮书-20230213
- 2025年陕西省土地工程建设集团有限责任公司招聘笔试参考题库附带答案详解
- 《多样的中国民间美术》课件 2024-2025学年人美版(2024)初中美术七年级下册
- 人教版 七年级 下册 语文 第四单元《青春之光》课件
- 2024物业管理数字化升级服务合同
- 灌浆作业安全操作规程(3篇)
- 药品追回管理制度内容
评论
0/150
提交评论