300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > linux 下网络编程 聊天室项目

linux 下网络编程 聊天室项目

时间:2018-11-01 16:30:15

相关推荐

linux 下网络编程 聊天室项目

服务端使用框架:非阻塞轮询;

客户端使用框架:多线程;

使用数据库:mysql;

实现主要功能:

1.注册;

2.登录;

3.群聊;

4.私聊;

5.查看聊天记录;

6.查看在线人数;

7.修改个性签名;

8.修改密码;

9.发送文件;

10.退出登录;

11.注销账号;

进入时界面:左边服务器,右边客户端;

登录成功时界面:

客户端:

client.h

#ifndef _select_h_#define _select_h_#include <stdio.h>#include <time.h>#define SIZE 1024#define NOW_MAX 20 typedef struct msg//表示聊天时的信息{char msg[SIZE]; //消息内容char localname[20];//消息目的名称char account[20]; //账户char fromname[20];//消息来源名称char password[20];//用户密码 char signname[40];//个性签名 int cmd;//工作模式int num;//用于保存文件复制的字节数}Msg;//最大允许并行客户端数量void regisc(int client_socket);void main_menu(void);int Ask_server(int client_socket);int entry(int client_socket);void user_menu(void);void User_used(int client_socket);void * readMsg (void *v);void entry_out(int client_socket);void chat_all(int client_socket);void chat_one(int client_socket);void client_logout(int client_socket);void save(Msg*msg);void look_chat();void see_now_time(int client_socket);void revise_sign(int client_socket);void revise_password(int client_socket);void client_guanli(int client_socket);void transfer_file(int client_socket);//传输文件void transfer_file_y(int client_socket);//同意接受文件void transfer_file_n(int client_socket);//拒绝接受文件void start_transfer_file(int client_socket);//开始传输文件void save_transfer_file(Msg * buf);//接受文件#endif

client.c

#include <stdio.h>#include <sys/types.h>/* See NOTES */#include <sys/socket.h>#include<netinet/in.h>#include <arpa/inet.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <pthread.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/types.h>#include "client.h"#define SER_IP "127.0.0.1"#define SER_PORT6789#define LISTEN_MAX 100char myname[20]={0};char signname[100]={0};char account_c[100]={0};char mylocalname[20]; //用于保存传输文件来源的名字char fsignname[40]; //用于保存文件传输名字int root=0;int flag = 1;void *recvdata_do_handler(void *a);/********************************************* TCP通信客户端流程* 1,创建套接字* 2,请求连接* 3,收发数据* 4,关闭套接字* *************************************************/int main(int argc, char *argv[]){//1.创建套接字 IPV4 流式套接字 TCP协议int clifd = socket(AF_INET,SOCK_STREAM,0);if(clifd == -1){perror("socket");return -1;}printf("clifd = %d\n",clifd);struct sockaddr_in seraddr;memset(&seraddr,0,sizeof(struct sockaddr_in));seraddr.sin_family = AF_INET;//ipv4协议类型seraddr.sin_addr.s_addr = inet_addr(SER_IP);seraddr.sin_port = htons(SER_PORT);//端口 网络字节序//2.请求连接if(connect(clifd,(struct sockaddr *)&seraddr,sizeof(struct sockaddr_in)) == -1){perror("connect");return -1;}printf("连接成功\n");Ask_server(clifd);close(clifd);return 0;}void main_menu(void){system("clear");printf("\n\n\n\n\n\n\n\n");printf("+++++++++++++++++++++++++++++++++++++++++\n");printf("+++\t 欢迎使用101聊天室+++\n");printf("+++\t\t1,注册+++\n");printf("+++\t\t2,登录+++\n");printf("+++\t\t3,退出+++\n");printf("+++++++++++++++++++++++++++++++++++++++++\n");}int Ask_server(int client_socket){char ch;int ret;while(1){main_menu();//引用菜单栏printf("请输入您要做操作\n");scanf("%c",&ch);while(getchar() != '\n');switch(ch){case '1': //注册regisc(client_socket);sleep(1);break;case '2': //登录ret = entry(client_socket);if (ret == 1){User_used(client_socket); //调用函数表示用户界面}sleep(1);break;case '3': //退出exit(0);break;}}}//注册函数void regisc(int client_socket){Msg msg;memset(&msg,0,sizeof(msg));msg.cmd=1;printf("请输入用户名\n");scanf("%s",msg.fromname);while(getchar() != '\n');printf("请输入账号\n");scanf("%s",msg.account);while(getchar() != '\n');printf("请输入密码\n");scanf("%s",msg.password);while(getchar() != '\n');printf("请输入个性签名\n");scanf("%s",msg.signname);while(getchar() != '\n');send(client_socket,&msg,sizeof(msg),0);recv(client_socket,&msg,sizeof(msg),0);printf("%d\n",msg.cmd);if(msg.cmd == 1001){printf("注册成功\n");}else if (msg.cmd == -1){printf("用户名以存在,注册失败\n");}else{printf("系统繁忙,注册失败\n");}sleep(2);}//登录账号int entry(int client_socket){Msg msg;memset(&msg,0,sizeof(msg));msg.cmd = 2;printf("登录,请输入账号名: ");scanf("%s",msg.account);while(getchar() != '\n');printf("登录,请输入密码: ");scanf("%s",msg.password);while(getchar() != '\n');printf("\n");write(client_socket, &msg, sizeof(msg));memset(&msg,0,sizeof(msg));read(client_socket, &msg, sizeof(msg));printf("%d\n",msg.cmd);if(msg.cmd == -1) //表示用户不存在{printf("登录失败,系统繁忙.\n");sleep(2);return -1;}if(msg.cmd == -2) //表示用户不存在{printf("登录失败,用户不存在.\n");sleep(2);return -2;}if(msg.cmd == -3){printf("登录失败,用户已登录.\n");sleep(2);return -3;}if(msg.cmd == -4){printf("登录失败,密码错误.\n");sleep(2);return -4;}if(msg.cmd == 1002){printf("登录成功,登录中...\n");printf("%s %s \n",msg.fromname,msg.signname);strcpy(myname,msg.fromname);//保存在线名字strcpy(signname, msg.signname); //保存个性签名strcpy(account_c,msg.account); //保存账号root=msg.num; //获取权限sleep(2);return 1;}}void user_menu(void){system("clear");printf("%s: %s\n",myname,signname);//printf("\n\n\n\n\n\n\n");printf("++++++++++++++++++++++++++++++++++++++++\n");printf("+++ +++\n");printf("+++\t 欢迎使用101聊天室+++\n");printf("+++ +++\n");printf("++++++++++++++++++++++++++++++++++++++++\n");printf("+++\t\t1,群聊+++\n");printf("+++\t\t2,私聊+++\n");printf("+++\t\t3,退出登录 +++\n");printf("+++\t\t4,查看聊天记录 +++\n");printf("+++\t\t5,显示当前在线人员 +++\n");printf("+++\t\t6,修改个性签名 +++\n");printf("+++\t\t7,修改密码 +++\n");printf("+++\t\t8,传输文件 +++\n");printf("+++\t\t9,注销账号 +++\n");printf("+++\t\tA,管理 +++\n");printf("++++++++++++++++++++++++++++++++++++++++\n");}//用户界面void User_used(int client_socket){//要进行读写分离pthread_t read_id;pthread_create(&read_id, NULL, readMsg, (void *)&client_socket);pthread_detach(read_id); //等待线程分离char ch;flag=1;while(flag){user_menu();//调用第二个用户界面printf("请输入您要做操作\n");scanf("%c",&ch);while(getchar() != '\n');switch(ch){case '1': //群聊chat_all(client_socket);break;case '2': //私聊chat_one(client_socket);break;case '3': //退出登录entry_out(client_socket);flag = 0;break;case '4': //查看聊天记录look_chat(); break;case '5': //显示当前在线人数 see_now_time(client_socket);break;case '6': //修改个性签名revise_sign(client_socket);break;case '7': //修改密码revise_password(client_socket);sleep(1);break;case '8': //传输文件transfer_file(client_socket);break;case 'y': //表示愿意接受文件transfer_file_y(client_socket);printf("接收中\n");getchar();break;case 'n': //表示不愿意接受文件transfer_file_n(client_socket);sleep(1);break;case '9':client_logout(client_socket);//表示注销账号flag=0;break;case 'a':if(root==1)//判断是不是管理员client_guanli(client_socket);elseprintf("管理失败没有权限\n");sleep(1);break;}}//pthread_cancel(read_id);}//读写分离专门收消息void * readMsg (void *v){int client_socket = *((int*)v);Msg buf;time_t t;struct tm *pt;int i = 0;while(1){memset(&buf,0,sizeof(Msg));int ret = read(client_socket, &buf, sizeof(Msg));if(ret == -1){perror("read");break;}switch(buf.cmd){case 3: printf(" %s\n",buf.msg);save(&buf); //保存聊天记录break;case 4: //私聊printf(" %s\n",buf.msg);save(&buf); //保存聊天记录break;case -3: //私聊失败printf("私聊失败,用户不存在或下线\n");break;case 5 : //退出登录printf("%s 退出登录\n",buf.fromname);sleep(1);pthread_exit(NULL); //线程退出break;case 6 : //显示当前在线人数printf("当前在线人员:\n");printf("%s\n",buf.msg);break;case 7 : //修改个性签名成功strcpy(signname,buf.signname);printf("修改个性签名成功\n");break;case -7 : //修改个性签名失败printf("修改个性签名失败\n");break;case 8 : //修改密码成功printf("修改密码成功\n");entry_out(client_socket);flag=0;break;case -8 : //修改密码失败printf("修改密码失败\n");break;case 9 : //调用函数确认是否接受文件system("clear");printf("请问你是否接受来自 %s 的文件 %s(y/n)\n",buf.fromname,buf.signname);strcpy(mylocalname,buf.fromname); //保存传输文件来源名字sleep(1);break;case -9 : //表示传输文件失败,没有找到该人printf("发送文件失败,好友不在线或不存在\n");sleep(1);break;case 10 : //表示愿意接受文件,开始传输start_transfer_file(client_socket);sleep(1);break;case -10 : //表示不愿意接受文件printf("发送文件失败,好友拒绝接受文件\n");sleep(1);break;case 11 : //接受文件save_transfer_file(&buf);break;//printf("%d\n",i);case 22:printf("%s\n",buf.msg);break;case 87:printf("禁言成功\n");break;case 88:printf("踢人成功\n");break;case 99:printf("注销成功\n");sleep(1);pthread_exit(NULL); //线程退出break;default:break;}}}void entry_out(int client_socket)//退出登录{Msg msg;memset(&msg,0,sizeof(msg));msg.cmd=5;strcpy(msg.account,account_c);strcpy(msg.fromname,myname);send(client_socket,&msg,sizeof(msg),0);sleep(1);}void chat_all(int client_socket)//群聊{system("clear");Msg msg;time_t t;char senr[150];memset(&msg,0,sizeof(msg));msg.cmd = 3;strcpy(msg.fromname,myname);strcpy(msg.localname,"All");printf("输入quit退出\n");printf("请输入你要群发送的信息\n");while(1){memset(msg.msg,0,sizeof(msg.msg));memset(senr,0,sizeof(senr));// getchar();time(&t);struct tm *pt = localtime(&t);getchar();printf("%d年%d月%d日 %d:%d:%d\n",pt->tm_year+1900,pt->tm_mon+1,pt->tm_mday,pt->tm_hour,pt->tm_min,pt->tm_sec);sprintf(msg.msg,"\t\t\t%d年%d月%d日 %d:%d:%d\n\t\t\t",pt->tm_year+1900,pt->tm_mon+1,pt->tm_mday,pt->tm_hour,pt->tm_min,pt->tm_sec);printf("%s:",msg.fromname);scanf("%s",senr);strcat(msg.msg,msg.fromname);strcat(msg.msg,":");strcat(msg.msg,senr);while(getchar() != '\n');if(strcmp("quit",senr)==0)break;write(client_socket, &msg, sizeof(Msg));}save(&msg);sleep (2);}void chat_one(int client_socket)//私聊{system("clear");Msg msg;char senr[150];time_t t;memset(&msg,0,sizeof(msg));msg.cmd = 4;printf("请输入你要聊天的对象:\n");scanf ("%s",msg.localname);while(getchar() != '\n');strcpy (msg.fromname,myname);while(1){getchar();time(&t);struct tm *pt = localtime(&t);printf("%d年%d月%d日 %d:%d:%d\n",pt->tm_year+1900,pt->tm_mon+1,pt->tm_mday,pt->tm_hour,pt->tm_min,pt->tm_sec);sprintf(msg.msg,"\t\t\t%d年%d月%d日 %d:%d:%d\n\t\t\t",pt->tm_year+1900,pt->tm_mon+1,pt->tm_mday,pt->tm_hour,pt->tm_min,pt->tm_sec);printf("%s:",msg.fromname);scanf("%s",senr);while(getchar() != '\n');if(strcmp("quit",senr)==0){break;}strcat(msg.msg,msg.fromname);strcat(msg.msg,":");strcat(msg.msg,senr);write(client_socket, &msg, sizeof(Msg));save(&msg); //保存聊天记录}sleep(2);}void client_logout(int client_socket)//注销{Msg msg;memset(&msg,0,sizeof(msg));msg.cmd=99;strcpy (msg.account,account_c);send(client_socket,&msg,sizeof(msg),0);}void save(Msg*msg)//保存{char buf2[120];char ai[1050];memset(buf2,0,sizeof(buf2));memset(ai,0,sizeof(ai));if(strcmp(myname,msg->fromname)==0){sprintf(buf2,"../liaotianjilu/%s & %s.txt",msg->fromname,msg->localname);}else{sprintf(buf2,"../liaotianjilu/%s & %s.txt",msg->localname,msg->fromname);}int ps=open(buf2,O_WRONLY|O_CREAT|O_APPEND,0644);sprintf(ai,"%s\n",msg->msg);write(ps,ai,strlen(ai));close (ps);}void look_chat()//查看聊天记录{char buf2[120];char ai[10500];memset(ai,0,sizeof(ai));memset(buf2,0,sizeof(buf2));printf("查看与谁的聊天记录:\n");scanf("%s",buf2);while(getchar()!='\n');sprintf(ai,"../liaotianjilu/%s & %s.txt",myname,buf2);int ps=open(ai,O_RDONLY);if(ps==-1){printf("查看失败\n");sleep(1);return;}memset(ai,0,sizeof(ai));read(ps,ai,sizeof(ai));printf("%s\n",ai);getchar();close(ps);}void see_now_time(int client_socket)//查看在线人数{Msg msg;memset(&msg,0,sizeof(msg));msg.cmd = 6;strcpy (msg.fromname,myname);write(client_socket, &msg, sizeof(Msg));sleep(2);}void client_guanli(int client_socket)//管理{Msg msg;memset(&msg,0,sizeof(msg));printf("请选择:1禁言,2踢人\n");int i;scanf("%d",&i);while(getchar()!='\n');if(i==1){msg.cmd=87;printf("请选择要禁言的人:\n");see_now_time(client_socket);scanf("%s",msg.localname);}else if(i==2){msg.cmd=88;printf("请选择要踢的人:\n");see_now_time(client_socket);scanf("%s",msg.localname);}else{printf("管理失败\n");return;}strcpy (msg.fromname,myname);write(client_socket, &msg, sizeof(Msg));sleep(1);}//修改个性签名void revise_sign(int client_socket){Msg msg;memset(&msg,0,sizeof(msg));msg.cmd = 7;printf("请输入新的个性签名:");scanf("%s",msg.signname);while(getchar() != '\n');strcpy(msg.fromname,myname); //需要保存名字strcpy(msg.account,account_c);write(client_socket, &msg, sizeof(Msg));sleep(2);}//修改密码void revise_password(int client_socket){Msg msg;memset(&msg,0,sizeof(msg));msg.cmd = 8;printf("请输入新的密码: ");scanf("%s",msg.password);while(getchar() != '\n');strcpy(msg.fromname,myname); //需要保存名字strcpy(msg.account,account_c);write(client_socket, &msg, sizeof(Msg));sleep(2);}void transfer_file(int client_socket)//传输文件{Msg msg;msg.cmd = 9;printf("请输入你要传输文件的对象:");scanf ("%s",msg.localname);while(getchar() != '\n');printf("请输入你要传输的本地文件名:");scanf ("%s",msg.signname);while(getchar() != '\n');strcpy(msg.fromname,myname); //需要保存名字write(client_socket, &msg, sizeof(Msg));printf("等待验收中...\n");strcpy(fsignname,msg.signname);strcpy(mylocalname,msg.localname);getchar();}//表示愿意接受文件void transfer_file_y(int client_socket){Msg msg;msg.cmd = 10;strcpy(msg.fromname,myname); strcpy(msg.localname,mylocalname); strcpy(mylocalname,"\0"); //用完后置零write(client_socket, &msg, sizeof(Msg));}//表示不愿意接受文件void transfer_file_n(int client_socket){Msg msg;msg.cmd = -10;strcpy(msg.fromname,myname); strcpy(msg.localname,mylocalname); strcpy(mylocalname,"\0"); //用完后置零write(client_socket, &msg, sizeof(Msg));}//传出文件来源开始传输文件void start_transfer_file(int client_socket){Msg msg;char ai[120];msg.cmd = 11; strcpy(msg.fromname,myname); strcpy(msg.signname,fsignname);strcpy(msg.localname,mylocalname);sprintf(ai,"../send/%s",msg.signname);int fd = open(ai,O_RDONLY); if(fd == -1){perror("open");printf("传输失败\n");return ;}int ret = 0;int i = 0;while(ret = read(fd,msg.msg,SIZE)){if(ret == -1){perror("read");break;}if (ret == 0){break;}msg.num = ret;write(client_socket, &msg, sizeof(Msg));usleep(10000);//这个睡眠时间减缓传输速度,降低不可预祝错误出现}printf("文件复制完成传输\n");strcpy(fsignname,"\0");strcpy(mylocalname,"\0");close(fd);}//接受文件void save_transfer_file(Msg * buf){char ai[120];sprintf(ai,"../recv/%s",buf->signname);int fd = open(ai,O_WRONLY|O_CREAT|O_APPEND,0777);write(fd,buf->msg,buf->num);if(buf->num != SIZE){printf ("文件接受完成\n");}close (fd);}

服务端:

select.h

#ifndef _select_h_#define _select_h_#include <stdio.h>#define SIZE 1024#define NOW_MAX 20 typedef struct msg//表示聊天时的信息{char msg[SIZE]; //消息内容char localname[20];//消息目的名称char account[20]; //账户char fromname[20];//消息来源名称char password[20];//用户密码 char signname[40];//个性签名 int cmd;//工作模式int num;//用于保存文件复制的字节数}Msg;//最大允许并行客户端数量typedef struct now_client //在线人数{char name[20];int socket;int jin;int ti;}NowClient;int regiss(int client_socket, Msg *msg);int entry(int client_socket, Msg *msg);void server_entryout(int client_socket,Msg *msg);void server_chatall(int client_socket, Msg * msg);void server_chatone(int client_socket, Msg * msg);void server_logout(int client_socket,Msg *msg);void server_save(Msg*msg);void see_nowuser(int client_socket, Msg * msg);void sremove(int client_socket, Msg * msg);void shutup(int client_socket, Msg * msg);void server_transfer_file(int client_socket, Msg * msg);//收到开始传输文件命令void server_transfer_file_y(Msg * msg);//接受文件void server_transfer_file_n(Msg * msg);//拒绝文件void server_start_transfer_file(Msg * msg);//开始文件传输void server_revise_sign(int client_socket, Msg * msg);void server_revise_password(int client_socket, Msg * msg);#endif

server.c

#include <stdio.h>#include <sys/types.h>/* See NOTES */#include <sys/socket.h>#include<netinet/in.h>#include <arpa/inet.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <pthread.h>#include <sys/select.h>#include <sys/time.h>#include <sys/types.h>#include <unistd.h>#include <signal.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/types.h>#include "select.h"#include "1mysql.h"#define SER_IP "127.0.0.1"#define SER_PORT6789#define LISTEN_MAX 100NowClient user[NOW_MAX]; //表示当前在线人的资料/********************************************* TCP通信服务器端流程* 1,创建套接字* 2,绑定* 3,监听* 4,等待连接* 5,收发数据* 6,关闭套接字* *************************************************/int all_clifd[256] = {0};//存放所有的客户端描述符int count = 0;//计数MYSQL *my_sql;//数据库描述符void accept_do_handler(int sockfd);void recv_do_handler(int sockfd);void send_to_all_cli(char *buf);int sockfd;void guan()//关闭函数{close(sockfd);mysql_close(my_sql);exit(-1);}int main(int argc, char *argv[]){pid_t pid= fork();if (pid==0){//1.创建套接字 IPV4 流式套接字 TCP协议sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd == -1){perror("socket");return -1;}printf("sockfd = %d\n",sockfd);signal(10,guan);//2.绑定struct sockaddr_in seraddr;memset(&seraddr,0,sizeof(struct sockaddr_in));seraddr.sin_family = AF_INET;//ipv4协议类型// seraddr.sin_addr;//ip地址 网络字节序// inet_aton(SER_IP,&seraddr.sin_addr);seraddr.sin_addr.s_addr = inet_addr(SER_IP);seraddr.sin_port = htons(SER_PORT);//端口 网络字节序int opt=1;setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));if(bind(sockfd,(struct sockaddr *)&seraddr,sizeof(struct sockaddr_in)) == -1){perror("bind");return -1;}printf("绑定成功\n");//3.监听if(listen(sockfd,LISTEN_MAX) == -1){perror("listen");return -1;}printf("监听成功\n");//非阻塞轮询int maxfd = sockfd;//处理连接请求--》sockfd发生可读变化//接收数据--》clifd发生可读变化fd_set readfds;//检测可读变化my_sql=Sconnect();//连接数据库int ret = 0;// struct timeval select_time;int i = 0;while(1){////先去清空集合FD_ZERO(&readfds);//再去添加FD_SET(sockfd,&readfds);for(i = 0;i<count;i++){//添加描sockfd述符FD_SET(all_clifd[i],&readfds);//求出来最大的if(all_clifd[i]>maxfd){maxfd = all_clifd[i];}}printf("\n");//永久阻塞ret = select(maxfd+1,&readfds,NULL,NULL,NULL);if(ret == -1){perror("select");return -1;}else if(ret == 0){printf("超时\n");continue;}//有变化,会打断阻塞,将集合里边没有变化的删除掉else{// printf("有文件描述符发生变化\n");//判断是谁发生的变化,根据变化去作处理//轮询从0到maxfd所有的文件描述符for(i = 0;i<=maxfd;i++){//检查发生变化的是否是readfds集合里边的if(FD_ISSET(i,&readfds)==1){//服务器套接字描述符发生变化//有客户端请求连接if(i == sockfd){accept_do_handler(sockfd);}//有客户端发消息else{recv_do_handler(i);}}} }}}else{char a;while(1){printf("y/n\n");a=getchar();if(a=='y'){printf("1");kill(pid,10);exit(0);}}}}void accept_do_handler(int sockfd){//4.等待连接//存放连接成功之后,客户端的IP地址和端口struct sockaddr_in cliaddr;memset(&cliaddr,0,sizeof(struct sockaddr_in));socklen_t len = sizeof(struct sockaddr_in);int clifd = accept(sockfd,(struct sockaddr *)&cliaddr,&len);if(clifd == -1){perror("accept");return;}//存储所有的客户端描述符all_clifd[count] = clifd;count++;}void recv_do_handler(int client_socket){// 5.数据收发int i = 0;int ret = 0;int pos = 0;//记录下表Msg msg;memset(&msg,0,sizeof(msg));//阻塞ret = recv(client_socket,&msg,sizeof(msg),0);char shi[1024];sprintf(shi,"%s %s %s %s",msg.fromname,msg.account,msg.signname,msg.password);printf("%s\n",shi);if(ret==-1){perror("recv");return ;}else if(ret == 0){for(i = 0;i<count;i++){if(all_clifd[i] == client_socket){all_clifd[i] = 0;pos = i;break;}}for(i = pos;i<count-1;i++){all_clifd[i] = all_clifd[i+1];}all_clifd[count-1]=0;count--;}else{switch (msg.cmd){case 1 : // 注册regiss(client_socket, &msg);break;case 2 : //登录ret = entry(client_socket, &msg);send(client_socket , &msg ,sizeof(Msg),0);if (ret == 1){//在线人数加1int i;for (i=0; i<NOW_MAX; i++){if(user[i].socket == 0){strcpy(user[i].name, msg.fromname);user[i].socket = client_socket;user[i].jin=0;user[i].ti=0;printf("客户端在线人数加一\n");break;}}char guanbuf[1000];sprintf(msg.msg,"%s已登录",msg.fromname);msg.cmd=22;//用户界面for(i=0;i<NOW_MAX;i++){if(user[i].socket == 0)continue;if(user[i].socket==client_socket)continue;send(user[i].socket,&msg,sizeof(Msg),0);} }break;case 3://群聊server_chatall(client_socket, &msg);server_save(&msg);break;case 4 : //私聊server_chatone(client_socket, &msg);server_save(&msg);break;case 5://退出登录server_entryout(client_socket,&msg);sprintf(msg.msg,"%s已下线",msg.fromname);msg.cmd=22;for(i=0;i<NOW_MAX;i++){if(user[i].socket == 0)continue;if(user[i].socket==client_socket)continue;send(user[i].socket,&msg,sizeof(Msg),0);} break;case 6://在线人数see_nowuser(client_socket,&msg);break;case 7://改签名server_revise_sign(client_socket, &msg);break;case 8://改密码server_revise_password(client_socket, &msg);break;case 9://传输文件server_transfer_file(client_socket, &msg);break;case 10: //接受传输文件server_transfer_file_y(&msg);break;case -10 : //拒绝传输文件server_transfer_file_n(&msg);break;case 11: //一切条件都已成立,直接开始传输server_start_transfer_file(&msg);break;case 87://禁言shutup(client_socket,&msg);break;case 88://移除sremove(client_socket,&msg);break;case 99://注销server_logout(client_socket,&msg);break;}}}int regiss(int client_socket, Msg *msg)//注册{//printf("nihaos%d\n",__LINE__);int flag;int i=-1,j=-1,a=0;i=search(my_sql,msg);j=search1(my_sql);if(j==0){a=1;}printf("%d\n",i);if(i==0){ //printf("nihaos%d\n",__LINE__);flag= data_insert(my_sql,msg,client_socket,a);msg->cmd+=1000;}else if(i==1)msg->cmd=-1;printf("%d\n",msg->cmd);// printf("nihaos%d\n",__LINE__);send(client_socket,msg,sizeof(Msg),0);}int entry(int client_socket, Msg *msg){printf(" %s进行登录\n",msg->fromname);//用户登录int flag = Entry_User(my_sql,msg,client_socket);if (flag == -1){printf("登录失败,系统繁忙\n");msg->cmd = -1;return -1;}if (flag == -2){printf("登录失败,用户名不存在\n");msg->cmd = -2;return -2;}if (flag == -3){printf("登录失败,用户已登录\n");msg->cmd = -3;return -3;}if (flag == -4){printf("登录失败,密码错误\n");msg->cmd = -4;return -4;}else {printf("登录成功\n");msg->cmd += 1000;return 1;}}void server_entryout(int client_socket,Msg *msg)//退出登录{int ret= change(my_sql,"type","0",msg->account);//printf("%d\n",client_socket);if(ret==0){int i ;for(i=0; i<NOW_MAX; i++){if(user[i].socket == client_socket){user[i].socket = 0;printf("客户端在线人数减一\n");break;}}msg->cmd=5;sprintf(msg->msg,"退出登录成功");}else{sprintf(msg->msg,"退出登录失败");msg->cmd=-5;}//printf("%d\n",client_socket);char shi [1024];sprintf(shi,"%s %s %s %s %d",msg->fromname,msg->account,msg->signname,msg->password,msg->cmd);printf("%s\n",shi);send(client_socket,msg,sizeof(Msg),0);//printf("fasongcg\n");}void server_chatall(int client_socket, Msg * msg)//群聊{printf (" %s 进行群发.\n",msg->fromname);int j;for (j=0; j<NOW_MAX; j++){if(user[j].socket==client_socket){if(user[j].ti==1){memset(msg->msg,0,1000);sprintf(msg->msg,"发送失败已被移除群聊");write(client_socket, msg , sizeof(Msg));return ;}if(user[j].jin==1){memset(msg->msg,0,1000);sprintf(msg->msg,"发送失败已被禁言");write(client_socket, msg , sizeof(Msg));return ;}break;}}int i;for(i=0; i<NOW_MAX; i++){if (user[i].socket != 0&&user[i].socket!=client_socket&&user[i].ti!=1){write(user[i].socket, msg , sizeof(Msg));}}}void server_chatone(int client_socket, Msg * msg)//私聊{printf ("私聊 %s发送信息给%s\n",msg->fromname,msg->localname);int i;for(i=0; i<NOW_MAX; i++){if(user[i].socket != 0 && strcmp(user[i].name, msg->localname) == 0){write(user[i].socket, msg , sizeof(Msg));printf("私聊成功\n");break;}}if (i == NOW_MAX){msg->cmd = -3; //表示私聊失败write(client_socket, msg , sizeof(Msg));printf("私聊失败\n");}}void server_logout(int client_socket,Msg *msg)//注销{int ret=mysql_delete(my_sql,msg->account);if(ret==0){printf("注销成功\n");int i ;for(i=0; i<NOW_MAX; i++){if(user[i].socket == client_socket){user[i].socket = 0;printf("客户端在线人数减一\n");break;}}msg->cmd=99;}elsemsg->cmd=-99;send(client_socket,msg,sizeof(Msg),0);}void server_save(Msg*msg)//保存聊天记录{char buf2[120];char ai[1250];memset(buf2,0,sizeof(buf2));memset(ai,0,sizeof(ai));sprintf(buf2,"../serverliaotianjilu/all.txt");int ps=open(buf2,O_WRONLY|O_CREAT|O_APPEND,0644);sprintf(ai,"%s->%s:%s\n",msg->fromname,msg->localname,msg->msg);write(ps,ai,strlen(ai));close (ps);}void see_nowuser(int client_socket, Msg * msg)//在线人员{printf("%s 查看当前在线人员\n",msg->fromname);int i;int len;char buf[1024] = {0};for(i=0; i<NOW_MAX; i++){if(user[i].socket != 0){strcat(buf,user[i].name);len = strlen(buf);buf[len] = ' ';}}strcpy(msg->msg,buf);write(client_socket, msg, sizeof(Msg));printf("查看成功\n");}void server_revise_sign(int client_socket, Msg * msg)//修改个性签名{printf("%s 修改个性签名\n",msg->fromname);int ret = change(my_sql,"signname",msg->signname,msg->account); //修改数据库if (ret == -1){msg->cmd = -7;printf("%s 修改个性签名失败\n",msg->fromname);write(client_socket, msg, sizeof(Msg));}printf("%s 修改个性签名成功\n",msg->fromname);write(client_socket, msg, sizeof(Msg));}//修改密码void server_revise_password(int client_socket, Msg * msg){printf("%s 修改密码\n",msg->fromname);int ret = change(my_sql,"passwd",msg->password,msg->account);if (ret == -1){msg->cmd = -8;printf("%s 修改密码失败\n",msg->fromname);write(client_socket, msg, sizeof(Msg));}printf("%s 修改密码成功\n",msg->fromname);write(client_socket, msg, sizeof(Msg));}void shutup(int client_socket, Msg * msg)//禁言{int i;for (i=0; i<NOW_MAX; i++){if(strcmp(user[i].name ,msg->localname)==0){user[i].jin=1;break;}}write(client_socket, msg, sizeof(Msg));}void sremove(int client_socket, Msg * msg)//移除{int i;for (i=0; i<NOW_MAX; i++){if(strcmp(user[i].name ,msg->localname)==0){user[i].ti=1;break;}}write(client_socket, msg, sizeof(Msg));}//传输文件void server_transfer_file(int client_socket, Msg * msg){printf ("%s 请求发送%s文件给 %s\n",msg->fromname,msg->signname,msg->localname);int i;for(i=0; i<NOW_MAX; i++){if(user[i].socket != 0 && strcmp(user[i].name, msg->localname) == 0){write(user[i].socket, msg , sizeof(Msg));printf("发送给%s信息进行判断是否接受\n",msg->localname);break;}}if (i == NOW_MAX){msg->cmd == -9; //表示传输文件失败write(client_socket, msg , sizeof(Msg));printf("发送文件失败,好友不在线或不存在\n");}}void server_transfer_file_y(Msg * msg)//接收文件{printf("%s 接受文件传输.\n",msg->fromname);int i;for(i=0; i<NOW_MAX; i++){if(user[i].socket != 0 && strcmp(user[i].name, msg->localname) == 0){write(user[i].socket, msg , sizeof(Msg));break;}}}//拒绝文件void server_transfer_file_n(Msg * msg){printf("%s 不愿意接受文件传输.\n",msg->fromname);int i;for(i=0; i<NOW_MAX; i++){if(user[i].socket != 0 && strcmp(user[i].name, msg->localname) == 0){write(user[i].socket, msg , sizeof(Msg));break;}}}void server_start_transfer_file(Msg * msg){//printf("文件传输中\n");int i;for(i=0; i<NOW_MAX; i++){if(user[i].socket != 0 && strcmp(user[i].name, msg->localname) == 0){write(user[i].socket, msg , sizeof(Msg)); //写文件数据break;}}if(msg->num != 1024){printf("文件传输完成\n");}}

数据库端:

1mysql.h

#ifndef _mysql_h_#define _mysql_h_#include <stdio.h>#include <mysql/mysql.h>#include <string.h>#include <stdlib.h>#include "select.h"#define HOSTNAME "localhost"#define USERNAME "root"#define PASSWD"1"#define DATABASENAME "chatroom"#define TABLENAME "infor"void print_all_data(MYSQL *mysql,Msg *msg);int search(MYSQL *mysql,Msg *msg);MYSQL * Sconnect();int data_insert(MYSQL *mysql,Msg *msg,int sockfd,int root);int Entry_User(MYSQL *con,Msg *msg,int my_sockfd);int change(MYSQL *my_sql,char *field,char * changenaem,char *naem);int mysql_delete(MYSQL *my_sql,char *deletename);int search1(MYSQL *mysql);#endif

mysql.c

#include "1mysql.h"#include "select.h"MYSQL * Sconnect()//连接数据库{static MYSQL my_sql;//0.初始化核心结构体mysql_init(&my_sql);//1.连接数据库//指定使用"hello"数据库MYSQL*p = mysql_real_connect(&my_sql,HOSTNAME,USERNAME,PASSWD,DATABASENAME,0,NULL,0);if(p == NULL){// perror("mysql_real_connect");printf("mysql_error:%s\n",mysql_error(&my_sql));return NULL;}printf("数据库连接成功\n");return &my_sql;}void print_all_data(MYSQL *mysql,Msg *msg){char buf[256];int ret = 0;memset(buf,0,sizeof(buf));sprintf(buf,"SELECT * FROM %s",TABLENAME);// printf("buf:%s\n",buf);ret = mysql_real_query(mysql,buf,strlen(buf));if(ret != 0){printf("mysql_error:%s\n",mysql_error(mysql));return;}// printf("查询数据成功\n");//获取结果集MYSQL_RES *pres = mysql_store_result(mysql);if(pres == NULL){printf("mysql_error:%s\n",mysql_error(mysql));return;} // printf("获取结果集成功\n");MYSQL_ROW row;int i,j;for(i = 0;i<mysql_num_rows(pres);i++){//读取结果集里边的一行数据row = mysql_fetch_row(pres);if(row == NULL){printf("mysql_error:%s\n",mysql_error(mysql));return;}for(j=0;j<mysql_num_fields(pres);j++){printf("%s\t",row[j]?row[j]:NULL);}printf("\n");}//释放结果集mysql_free_result(pres);}int search(MYSQL *mysql,Msg *msg)//查询数据表某一项{int ret;char buf[256];printf("nihaos\n");sprintf(buf,"SELECT * FROM %s WHERE account='%s'",TABLENAME,msg->account);ret = mysql_real_query(mysql,buf,strlen(buf));MYSQL_RES *pres = mysql_store_result(mysql);uint64_t rownum = mysql_num_rows(pres);return rownum; }int search1(MYSQL *mysql)//查询数据表{int ret;char buf[256];printf("nihaos\n");sprintf(buf,"SELECT * FROM %s ",TABLENAME);ret = mysql_real_query(mysql,buf,strlen(buf));MYSQL_RES *pres = mysql_store_result(mysql);uint64_t rownum = mysql_num_rows(pres);return rownum; }int data_insert(MYSQL *mysql,Msg *msg,int sockfd,int root)//插入数据表{char query[1024];sprintf(query,"insert into %s values('%s','%s','%s','%d','%d','%d','%s')",TABLENAME ,msg->fromname,msg->account,msg->password,0,sockfd,root,msg->signname);printf("%s\n",query);if((mysql_real_query(mysql,query,(unsigned int)strlen(query))) != 0){printf("insert failed.\n");return 0;}return 1;}int Entry_User(MYSQL *con,Msg *msg,int my_socket)//登录{char query[1024],shi[1024];sprintf(query,"SELECT * FROM %s WHERE account = '%s'",TABLENAME,msg->account);if((mysql_real_query(con,query,(unsigned int)strlen(query))) != 0){printf("insert failed.\n");return -1;}MYSQL_RES *pres = mysql_store_result(con);uint64_t rownum = mysql_num_rows(pres);if(rownum==0){return -2;}MYSQL_ROW row;int num_fields=mysql_num_fields(pres);row=mysql_fetch_row(pres);if(strcmp(row[3],"1")==0){return -3;}if(strcmp(msg->password,row[2])!=0){return -4;}char di[10];sprintf(di,"%d",my_socket);change(con,"socket",di,msg->account);change(con,"type","1",msg->account);strcat(msg->signname,row[6]);strcat(msg->fromname,row[0]);if(strcmp(row[5],"1")==0)msg->num=1;elsemsg->num=0;return 0;}int change(MYSQL *my_sql,char *field,char * changenaem,char *naem)//修改数据表{char query[1024];sprintf(query,"update %s set %s = '%s' where account='%s'",TABLENAME,field,changenaem,naem);if((mysql_real_query(my_sql,query,(unsigned int) strlen(query)))!=0){printf("insert failed.\n");return -1;}return 0;}int mysql_delete(MYSQL *my_sql,char *deletename)//删除数据表{char query[1024];sprintf(query,"delete from %s where account='%s'",TABLENAME,deletename);if((mysql_real_query(my_sql,query,(unsigned int) strlen(query)))!=0){printf("insert failed.\n");return -1;}return 0;}

编译客户端:gcc client.c -lmysqlclient -lpthread -o c

编译服务端:gcc server.c mysql.c -lmysqlclient -lpthread -o s

注意:使用mysql要安装相应的库;

安装服务器端

sudo apt-get install mysql-server

安装客户端

sudo apt-get install mysql-client

安装C语言API库

sudo apt-get install libmysqlclient-dev

如果想直接运行代码的话还要在mysql里面添加chatroom数据库,在chatroom库里面添加infor数据表;

步骤1:创建chatroom数据库,代码:create database chatroom;

步骤2:进入chatroom数据库,代码:use chatroom;

步骤3:创建infor数据表,代码:CREATE TABLE infor(name varchar(20),account varchar(20),passwd varchar(20),type int,socket int,root int,signname varchar(100));

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。