您的位置:首页 > 理论基础 > 计算机网络

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: