TCP/IP多线程——聊天室(服务器)
2017-12-29 11:05
330 查看
/***************************************************** > File name: client.h > Author: Mr.YUAN > 日期: 2017-12-12 19:57 *****************************************************/ #ifndef CLIENT_H_ #define CLIENT_H_ #include <stdio.h> #include <sqlite3.h> #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <strings.h> #include <stdlib.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <signal.h> #include <pthread.h> #include <semaphore.h> #include <termios.h> #include <time.h> #include <sys/stat.h> #include <fcntl.h> #define SE_PORT 8888 #define reg 1 //注册 #define log 2 //登录 #define exit 4 //退出 #define existing_acc 5 //账号已存在 #define logged_acc 6 //账号已登录 #define error 7 //账号或密码错误 #define log_success 8 //登录成功 #define reg_success 9 //注册成功 #define Exit 10 //退出 #define private_chat 11 //私聊 #define group_chat 12 //群聊 #define group_result 13 //群聊接受 #define online_member 15 //查看在线人数 #define expression 16 //表情 #define phrases 17 //常用语 #define Vip 21 //开会员 #define Shutup 22 //禁言 #define lifted 23 //解禁 #define kick 24 //踢人 #define vip_success 25 //开会员成功 #define Shutup_success 26 //禁言成功 #define Send_success 27 //发送信息成功 #define Send_error 28 //发送信息失败 #define kick_fail 29 //踢人失败 #define kick_success 30 //踢人成功 extern int tcp_init(); extern int tcp_accept(int sfd); extern int tcp_connect(); #endif
/***************************************************** > File name: client.c > Author: Mr.YUAN > 日期: 2017-12-12 18:58 *****************************************************/ #include "server.h" struct send { char name[20]; char toname[20]; char account[20]; char password[20]; int vip; //是否是会员 int cmd; //提取操作符 char msg[200]; //发送、接收消息 char e_s; //确认发送的表情 char p_s; //确认发送的常用语 }; struct recv { char from_name[20]; char to_name[20]; //名字 int result; //返回操作结果 int online_num; //在线人数 char num[20][20]; //在线人名 char msg[200]; //发送、接收消息 char password[20]; //密码 int vip; //是否是会员 char e_s; //确认发送的表情 char p_s; //确认发送的常用语 }; typedef struct node { int socket; char name[20]; struct node* next; }UMge; typedef struct node* PUMge; struct send userIn; struct recv userBack; sqlite3 * db = NULL; int i; int ret; PUMge head; //初始化socket int tcp_init() { int sfd=socket(AF_INET,SOCK_STREAM,0); if(-1==sfd) { perror("socket"); return -1; } int opt=1;//刷新服务器 setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); int ret; struct sockaddr_in server_addr; memset(&server_addr,0,sizeof(struct sockaddr)); server_addr.sin_family=AF_INET; server_addr.sin_port=htons(SE_PORT); server_addr.sin_addr.s_addr=htonl(INADDR_ANY); ret=bind(sfd,(struct sockaddr*)&server_addr,sizeof(struct sockaddr)); if(-1==ret) { perror("bind"); return -1; } ret=listen(sfd,10); if(-1==ret) { perror("listen"); close(sfd); return -1; } return sfd; } //接收 int tcp_accept(int sfd) { struct sockaddr_in client_addr; memset(&client_addr,0,sizeof(struct sockaddr)); int length=sizeof(struct sockaddr); int sfd2=accept(sfd,(struct sockaddr *)&client_addr,&length); if(-1==sfd2) { perror("accept"); close(sfd); return -1; } printf("%s %d connet success!\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port)); return sfd2; } //连接 int tcp_connect(const char* ip) { int ret; int sfd=socket(AF_INET,SOCK_STREAM,0); if(-1==sfd) { perror("socket"); return -1; } struct sockaddr_in server_addr; memset(&server_addr,0,sizeof(struct sockaddr)); server_addr.sin_family=AF_INET; server_addr.sin_port=htons(SE_PORT); server_addr.sin_addr.s_addr=inet_addr(ip); ret=connect(sfd,(struct sockaddr*)&server_addr,sizeof(struct sockaddr)); if(-1==ret) { perror("connect"); close(sfd); return -1; } return sfd; } void now_time() { time_t now; //实例化time_t结构 struct tm *timenow; //实例化tm结构指针 time(&now);//time函数读取现在的时间(国际标准时间非北京时间),然后传值给now timenow = localtime(&now);//localtime函数把从time取得的时间now换算成你电脑中的时间(就是你设置的地区) printf("\t\t\t Time :%s\n",asctime(timenow));//asctime函数把时间转换成字符,通过printf()函数输出"") } void SCAN_N()//清除回车的缓存 { char ch; while((getchar())!='\n'&&ch!=EOF); } //密码不回显 int mygetch( ) { struct termios oldt,newt; int ch; tcgetattr( STDIN_FILENO, &oldt ); newt = oldt; newt.c_lflag &= ~( ICANON | ECHO ); tcsetattr( STDIN_FILENO, TCSANOW, &newt ); ch = getchar(); tcsetattr( STDIN_FILENO, TCSANOW, &oldt ); return ch; } void save_user()//保存用户 { char *errmsg=NULL; char auff[200]={0}; char cuff[200]={0}; sprintf(auff,"insert into save_user values('%s','%s','%s',%d)",userIn.account,userIn.password,userIn.name,userIn.vip); ret=sqlite3_exec(db,auff,NULL,NULL,&errmsg); if(ret!=SQLITE_OK) { printf("插入失败:%d(%s)\n",ret,errmsg); userBack.result=existing_acc; printf("sqlite save_user 插入失败 账户已被注册\n"); return; } printf("sqlute save_user 插入成功\n"); sprintf(cuff,"insert into question values('%s','%s')",userIn.account,userIn.password); ret=sqlite3_exec(db,cuff,NULL,NULL,&errmsg); if(ret!=SQLITE_OK) { printf("insert faile %d(%s)\n",ret,errmsg); return; } userBack.result=reg_success; //注册成功 } void deal_log(int cfd)//登录核对客户端信息 { char **resultp=NULL; int nrow; int ncolumn; int ret; int i; char *errmsg=NULL; char cuff[200]; sprintf(cuff,"select account,password,name,vip from save_user where account ='%s' and password ='%s'",userIn.account,userIn.password); ret=sqlite3_get_table(db,cuff,&resultp,&nrow,&ncolumn,&errmsg); if(ret!=SQLITE_OK) { printf("log error :%d(%s)!\n",ret,errmsg); return; } printf("%s logging ...",resultp[4]); if(1==nrow) { PUMge temp=head->next; /*while(temp!=head)//1111遍历链表 打印用户昵称 { printf("1111\n"); PUMge p=temp; printf("%s \n",p->name); temp=temp->next; }*/ while(temp!=head) { if(strcmp(temp->name,resultp[4])==0) { userBack.result=logged_acc; printf("%s logged error 已经登陆在线\n",userIn.name); return; } temp=temp->next; } userBack.result=log_success;//登陆成功 strcpy(userBack.from_name,resultp[4]); userBack.vip=*(resultp[7])-48; printf("\n%s logg ...\n",resultp[4]); PUMge p=(PUMge) malloc(sizeof( 4000 UMge)/sizeof(char)); if(NULL==p) { perror("malloc"); return; } p->socket=cfd; strcpy(p->name,resultp[4]); printf("%s socket %d...\n",p->name,p->socket); p->next=head->next; head->next=p;//插入结点 } else { userBack.result=error; printf("%s password error\n",resultp[4]); } ret=write(cfd,&userBack,sizeof(userBack)); if(-1==ret) { perror("write"); return; } } int deal_pchar(int cfd)//处理私聊 { int flag=0; PUMge temp=head->next; while(temp!=head)//链表寻找收件人 { if(strcmp(temp->name,userIn.toname)==0&&temp->socket!=cfd) { flag=1; strcpy(userBack.msg,userIn.msg); strcpy(userBack.from_name,userIn.name); userBack.result=private_chat; printf("%s(%d) send %s(%d) ...\n",userIn.name,cfd,userIn.toname,temp->socket); write(temp->socket,&userBack,sizeof(userBack)); break; } temp=temp->next; } printf("%d\n",flag); if(flag) { userBack.result=Send_success; write(cfd,&userBack,sizeof(userBack)); printf("%s send message to %s ...\n",userIn.name,userIn.toname); } else { userBack.result=Send_error; write(cfd,&userBack,sizeof(userBack)); printf("%s send error...\n",userIn.name); } } int deal_groupchat(int cfd)//处理群聊 { int flag=0; PUMge temp=head->next; while(temp!=head) { if(temp->socket!=cfd) { flag=1; strcpy(userBack.from_name,userIn.name); strcpy(userBack.msg,userIn.msg); userBack.result=group_chat; write(temp->socket,&userBack,sizeof(userBack)); } temp=temp->next; } printf("%s send message to all...\n",userIn.name); if(flag) { userBack.result=Send_success; write(cfd,&userBack,sizeof(userBack)); } else { userBack.result=Send_error; write(cfd,&userBack,sizeof(userBack)); printf("%s send grep error ...\n",userIn.name); } } int deal_member(int cfd)//查看在线人员 { userBack.online_num=0; int i=0; PUMge temp=head->next; while(temp!=head) { userBack.online_num++; strcpy(userBack.num[i],temp->name); i++; temp=temp->next; } userBack.result=online_member; write(cfd,&userBack,sizeof(userBack)); printf("show all online_member ...\n"); } int deal_expression(int cfd)//处理表情 { PUMge temp=head->next; int flag=0; while(temp!=head) { if(strcmp(temp->name,userIn.toname)==0&&temp->socket!=cfd) { flag=1; userBack.result=expression; strcpy(userBack.from_name,userIn.name); userBack.e_s=userIn.e_s; write(temp->socket,&userBack,sizeof(userBack)); break; } temp=temp->next; } if(flag) { userBack.result=Send_success; write(cfd,&userBack,sizeof(userBack)); printf("%s send expression to %s ...\n",userIn.name,userIn.toname); } else { userBack.result=Send_error; write(cfd,&userBack,sizeof(userBack)); printf("%s send expression error ...\n",userIn.name); } } int deal_phrases(int cfd)//处理常用语 { PUMge temp=head->next; int flag=0; while(temp!=head) { if(strcmp(temp->name,userIn.toname)==0&&temp->socket!=cfd) { flag=1; userBack.result=phrases; strcpy(userBack.from_name,userIn.name); userBack.p_s=userIn.p_s; write(temp->socket,&userBack,sizeof(userBack)); break; } temp=temp->next; } if(flag) { userBack.result=Send_success; write(cfd,&userBack,sizeof(userBack)); printf("%s send phrases to %s ...\n",userIn.name,userIn.toname); } else { userBack.result=Send_error; write(cfd,&userBack,sizeof(userBack)); printf("%s send phrases error ...\n",userIn.name); } } int deal_vip(int cfd)//升级会员 { char guff[200]; char *errmsg=NULL; printf("11111\n"); sprintf(guff,"update save_user set vip= %d where name = '%s';",userIn.vip,userIn.name); ret=sqlite3_exec(db,guff,NULL,NULL,&errmsg); if(ret!=SQLITE_OK) { printf("update error:%d(%s)\n",ret,errmsg); return -1; } userBack.vip=1; userBack.result=vip_success; write(cfd,&userBack,sizeof(userBack)); printf("%s become vip ...\n",userIn.name); return 0; } int deal_Shutup(int cfd)//处理禁言 { PUMge temp=head->next; int flag=0; while(temp!=head) { if(strcmp(temp->name,userIn.toname)==0) { flag=1; userBack.result=Shutup; strcpy(userBack.from_name,userIn.name); write(temp->socket,&userBack,sizeof(userBack)); } temp=temp->next; } if(flag) { userBack.result=Shutup_success; write(cfd,&userBack,sizeof(userBack)); } else { userBack.result=Send_error; write(cfd,&userBack,sizeof(userBack)); } } int deal_kick(int cfd)//踢人 { PUMge temp=head->next; int flag=0; while(temp!=head) { if(strcmp(temp->name,userIn.toname)==0) { flag=1; userBack.result=kick; strcpy(userBack.from_name,userIn.name); write(temp->socket,&userBack,sizeof(userBack)); break; } temp=temp->next; } if(flag) { userBack.result=kick_success; write(cfd,&userBack,sizeof(userBack)); } else { userBack.result=Send_error; write(cfd,&userBack,sizeof(userBack)); } } int deal_exit(int cfd)//下线 { PUMge temp=head; while(temp->next!=head) { if(strcmp(temp->next->name,userIn.name)==0) { PUMge p= temp->next; temp->next= p->next; free(p); p=NULL; printf("%s log out ...\n",userIn.name); break; } temp=temp->next; } return 0; } void *server_requst(int const cfd)//处理请求 { printf("处理中...\n"); char *errmsg=NULL; while(1) { ret=read(cfd,&userIn,sizeof(userIn)); if(0==ret) { pthread_exit(NULL);//线程退出 } switch(userIn.cmd) { case (reg)://注册 save_user(db); write(cfd,&userBack,sizeof(userBack)); break; case (log)://登录 deal_log(cfd); break; case (private_chat)://私聊 deal_pchar(cfd); break; case (group_chat)://群聊 deal_groupchat(cfd); break; case (Vip)://升级管理员 deal_vip(cfd); break; case (online_member)://查看在线人数 deal_member(cfd); break; case (expression)://表情 deal_expression(cfd); break; case (phrases)://常用语 deal_phrases(cfd); break; case (Shutup)://禁言 deal_Shutup(cfd); break; case (exit): deal_exit(cfd); break; case (kick)://踢人 deal_kick(cfd); break; } } } int main()//主函数 { int sfd; head = (PUMge) malloc (sizeof(UMge)/sizeof(char)); if(head == NULL) { printf("malloc error\n"); } head->next = head; sfd = tcp_init(); char *errmsg = NULL; ret = sqlite3_open("user.db",&db); if(ret != SQLITE_OK) { perror("open user.db error"); return -1; } printf("open user.db success...\n"); ret=sqlite3_exec(db,"create table if not exists save_user(account TEXT,password TEXT,name TEXT,vip INTEGER,primary key(account))",NULL,NULL,&errmsg); if(ret != SQLITE_OK) { printf("create fail:%d(%s)\n", ret, errmsg); return -1; } printf("create save_user success...\n"); ret=sqlite3_exec(db,"create table if not exists question(account TEXT,password TEXT,primary key(account))",NULL,NULL,&errmsg); if(ret !=SQLITE_OK) { printf("creat fail:%d(%s)\n",ret,errmsg); return -1; } pthread_t clientid; while(1) { int cfd; cfd = tcp_accept(sfd); if(cfd == -1) { perror("accept"); return -1; } ret = pthread_create(&clientid, NULL, (void*)server_requst, (void*)cfd); if(ret == -1) { perror("pthread create"); return -1; } pthread_detach(clientid); // 线程分离 pthread_join(clientid, NULL); } sqlite3_close(db); return 0; }
相关文章推荐
- Android_TCP/IP开发——聊天室模型(客户端与服务器进行通信)
- TCP/IP多线程——聊天室(客户端 )
- Linux下面基于TCP多线程聊天室(服务器)
- 高性能、高并发TCP服务器(多线程调用libevent)
- 高性能、高并发TCP服务器(多线程调用libevent)
- hadoop 中 RPC HTTP TCP/IP 服务器的用途
- 多线程TCP/IP通讯的客户端
- Linux基于TCP/IP简单的客户端、服务器通信程序实例
- GConf 错误:联系配置服务器失败;某些可能原因是需要为 ORBit 启用 TCP/IP 联网
- 连接服务器TCP/IP杂记
- 简单的网络服务器(简单的TCP,简单的UDP,多进程多线程TCP)
- 查看服务器的TCP/IP(http)连接情况
- GConf 错误:联系配置服务器失败;某些可能原因是需要为 ORBit 启用 TCP/IP 联网
- tcp/ip客户端与服务器
- WINDOWS (服务器) 和 DOS(客户端) 网络互连 基于TCP/IP的编程实现
- 高性能、高并发TCP服务器(多线程调用libevent)
- TCP/IP 教程(针对LINUX的网络基础请参看 《鸟哥的Linux私房菜 服务器架设篇(第三版) 》)
- QT编写多线程TCP文件接收服务器
- tcp和udp多线程的epoll服务器+客户端源代码
- Linux基于TCP/IP简单的客户端、服务器通信程序实例