TCP/IP多线程——聊天室(服务器)


/*****************************************************
    > 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(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;
}









  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值