聊天室 源码

要求
实现一个简单的聊天室,具有私聊,群聊和传送文件的基本功能,以及一些小细节的实现。
头文件

#ifndef MY_CHAT_H
#define MY_CHAT_H
#include<pthread.h>
//倾听的最大数量
#define LISTENG 20
//端口
#define SERV_PORT 4508
#define MAX 1024

pthread_mutex_t mutex_cli; 
pthread_mutex_t mutex;
pthread_cond_t cond;
pthread_cond_t cond_cli;

typedef struct{ 
    int t;
    long size;
    int cont;
    int type;
    int type1;
    int send_fd;
    int recv_fd;
    int line;
    int relation;//0 申请 1 好友 -1 黑名单
    char send_id[4];
    char recv_id[4];
    char send_name[4];
    char recv_name[4];
    char read_buf[1024];
    char write_buf[1024];
    char buf[1024];
}bag;

typedef struct{
    int id[500];
    int fri_id[500];
    int buf_num;
    char buf[500][1024];
    char time[500][100];
}fri_mes;

typedef struct{
    int gro_id;//群号
    int id[500];//发言人的账号
    int number;//记录条数
    char buf[500][1024];//聊天记录
    char time[500][100];//时间
}gro_mes;

typedef struct{
    int gro_id;
    char gro_name[4];
    int gro_mem_id;
    int gro_chmod;//群主 2 管理员 1 普通成员 0
}gro;

typedef struct friend{
    int fri_number;
    char fri_name[500][4];
    int fri_id[500];
    int fri_line[500];
}fri;

typedef struct {
    int id[500];
    int chmod[500];
    int number;
}group;

typedef struct BOX {
    //文件数量
    int file_number;
    //文件名字
    char file_name[500][100];
    //文件发送者账号
    int file_id[500];
    //接收消息的人的账号
    int recv_id;
    //发送消息人的账号
    int send_id[500];
    //发送好友请求人的账号
    int plz_id[500];
    //发送的消息
    char read_buf[500][MAX];
    //发送的请求
    char write_buf[500][100];
    //消息数量
    int talk_number;
    //请求数量
    int friend_number;
    //群里发送消息的人
    int send_id1[500];
    //消息内容
    char message[500][MAX];
    //群消息数量
    int number;
    //群号
    int group_id[500];//消息的群号
    struct BOX *next;
} BOX;

BOX *box_head;
BOX *box_tail;

#endif

服务端

#include <sys/types.h>                                                   
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <mysql.h>
#include <stdlib.h>
#include"my_chat.h"
#include <sys/epoll.h>
#include <termios.h>
#include<time.h>
#include <sys/stat.h>
#include <fcntl.h> 

MYSQL mysql;

int sock_init()
{
    int sock_fd;
    struct sockaddr_in serv_addr;

    sock_fd=socket(AF_INET,SOCK_STREAM | SOCK_NONBLOCK,0);
    if(sock_fd<0)
    {
        perror("socket failed");
        return -1;
    }

    int optval=1;
    if(setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,(void *)&optval,sizeof(int))<0)
    {
        perror("setsockopt failed");
        return -1;
    }

    memset(&serv_addr,0,sizeof(struct sockaddr_in));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_port=htons(SERV_PORT);
    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);

    if(bind(sock_fd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr_in))<0)
    {
        perror("bind failed");
        return -1;
    }

    if(listen(sock_fd,LISTENG)<0)
    {
        perror("listen failed");
        return -1;
    }
    printf("服务端监听中...\n");
    return sock_fd;
}

void mysql_init1()
{   //句柄
    if(NULL == mysql_init(&mysql)){
		perror("mysql_init failed");
        return;
	}

	//初始化数据库
	if(mysql_library_init(0, NULL, NULL) != 0){
        perror("mysql_library_init failed");
        return;
	}

	//连接数据库
	if(NULL == mysql_real_connect(&mysql, "127.0.0.1", "root", "hh123456789", "try", 0, NULL, 0)){
        perror("mysql_real_connect failed");
        return;
	}

	//设置中文字符集
	if(mysql_set_character_set(&mysql, "utf8") < 0){
        perror("mysql_set_character_set failed");
        return;
	}
	
	printf("连接mysql数据库成功!\n");
}

int login(bag *recv_bag)
{
    printf("检查信息中...\n");
    bag *bag1=recv_bag;
    int ret;
    char sql[1280]; 
    MYSQL_RES *result=NULL;
    MYSQL_ROW row;

    memset(sql,0,1280);
    sprintf(sql,"select * from 身份信息 where id = '%s' and passwd ='%s' and line = 0",bag1->send_id,bag1->read_buf);
    ret=mysql_query(&mysql,sql);
   
    if(!ret)
    {
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row)
        {
            memset(sql,0,1280);
            sprintf(sql,"update 身份信息 set line = 1 , sockfd = %d where id = '%s'",bag1->recv_fd,bag1->send_id);
            ret=mysql_query(&mysql,sql);

            memset(bag1->write_buf,0,1024);
            strcpy(bag1->write_buf,"login successfully");
            strcpy(bag1->send_name,row[1]);

            if(ret<0)
            {
                perror("login failed");
                exit(1);
            } 
            
            ret=send(bag1->recv_fd,bag1,sizeof(bag),0);
            if(ret<0)
            {
                perror("send failed");
                exit(1);
            }
            printf("login successfully\n");
            mysql_free_result(result);
            
            return 1;
        }else{
            strcpy(bag1->write_buf,"login failed");
            send(bag1->recv_fd,bag1,sizeof(bag),0);
            printf("login failed\n");
        }
    }else{
        strcpy(bag1->write_buf,"login failed");
        send(bag1->recv_fd,bag1,sizeof(bag),0);
        printf("login failed\n");
    }
    return 0;
}

int resign(bag *recv_bag)
{
     bag *bag1=recv_bag;
    char sql[1280];
    int j=100;
    int ret;
    MYSQL_RES *result=NULL;
    MYSQL_ROW row;

    memset(sql,0,1280);

    sprintf(sql,"select * from 身份信息");
    ret=mysql_query(&mysql,sql);
    if(ret<0)
    {
        perror("mysql_query failed");
        return -1;
    }

    result=mysql_store_result(&mysql);
    while(row=mysql_fetch_row(result))
    {
        j++;
    }
    sprintf(bag1->send_id,"%d",j);
    bag1->line=0;

    pthread_mutex_lock(&mutex);
    memset(sql,0,1280);
    sprintf(sql,"insert into 身份信息 values('%s','%s','%s',%d,%d)",bag1->send_id,bag1->send_name,bag1->read_buf,bag1->line,bag1->recv_fd);
    mysql_query(&mysql,sql);
    ret=send(bag1->recv_fd,bag1,sizeof(bag),0);
    if(ret<0)
    {
        perror("send failed");
        pthread_mutex_unlock(&mutex);
        return -1;
    }
    printf("注册成功!\n");
    pthread_mutex_unlock(&mutex);
    return 0;
}

int add_fri(bag *recv_bag)
{
    bag *bag1=recv_bag;
    char sql[1280];
    MYSQL_RES *result=NULL;
    MYSQL_ROW row,row1;
    int t;
    int ret;
    BOX *box=box_head;
    memset(sql,0,1280);
    sprintf(sql,"select * from 身份信息 where id = '%s'",bag1->recv_id);
    ret=mysql_query(&mysql,sql);
            
    if(!ret){
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row==NULL)
        {
            strcpy(bag1->write_buf,"-2");
        }else{

            memset(sql,0,1280);
            sprintf(sql,"select * from friend where id1 = '%s' and id2='%s' ",bag1->send_id,bag1->recv_id);

            ret=mysql_query(&mysql,sql);
            if(!ret){
                result=mysql_store_result(&mysql);
                row1=mysql_fetch_row(result);
                if(row1){
                    t=atoi(row1[2]);
                    if(t==1){
                        strcpy(bag1->write_buf,"1");
                    }else if(t==-1)
                    {
                        strcpy(bag1->write_buf,"-1");                        
                    }else if(t==0){
                        strcpy(bag1->write_buf,"3");
                    }else{
                        strcpy(bag1->write_buf,"4");
                    }
                    send(bag1->recv_fd,bag1,sizeof(bag),0);
                    return 0;
                }else{ 
                    printf("正在发送请求!\n");
                   
                    pthread_mutex_lock(&mutex);
                        
                    memset(sql,0,1280);
                    sprintf(sql,"insert into friend values('%s','%s',0)",bag1->send_id,bag1->recv_id);
                    ret=mysql_query(&mysql,sql);
                    if(ret<0)
                    {
                        perror("failed");
                        exit(1);
                    }

                    strcpy(bag1->write_buf,"0");
                    pthread_mutex_unlock(&mutex);
                    send(bag1->recv_fd,bag1,sizeof(bag),0);
                    if(atoi(row[3])==0){
                        while(box!=NULL)
                        {
                            if(box->recv_id==atoi(bag1->recv_id))
                            {
                                break;
                            }
                            box=box->next;
                        }

                        if(box==NULL)
                        {
                            box=(BOX *)malloc(sizeof(BOX));
                            box->friend_number=0;
                            box->number=0;
                            box->talk_number=0;
                            box->file_number=0;
                            box->next=NULL;
                            box->recv_id=atoi(bag1->recv_id);
                            box->plz_id[box->friend_number]=atoi(bag1->send_id);
                            box->friend_number++;
                            if(box_head==NULL)
                            {
                                box_head=box;
                                box_tail=box;
                            }else{
                                box_tail->next=box;
                                box_tail=box;
                            }
                        }else{
                            box->plz_id[box->friend_number]=atoi(bag1->send_id);
                            box->friend_number++;
                        }
                       
                    }else{
                        bag1->send_fd=atoi(row[4]);
                        strcpy(bag1->write_buf,"0");
                        send(bag1->recv_fd,bag1,sizeof(bag),0);
                        bag1->type=18;
                        bag1->type1=1;
                        send(bag1->send_fd,bag1,sizeof(bag),0);
                    }
                }       
            }else{
                strcpy(bag1->write_buf,"4");
                send(bag1->recv_fd,bag1,sizeof(bag),0);
            }
        }
    }else{
        strcpy(bag1->write_buf,"4");
         send(bag1->recv_fd,bag1,sizeof(bag),0);
    }
    return 0;
}

int xiugai(bag *recv_bag)
{
     bag *bag1=recv_bag;
    int t=bag1->type1;
    char sql[1280];
    int ret;
    pthread_mutex_lock(&mutex);
    if(t==1){
        memset(sql,0,1280);
        sprintf(sql,"update 身份信息 set name = '%s' where id = '%s'",bag1->read_buf,bag1->send_id);
        mysql_query(&mysql,sql);
        printf("修改中...\n");
    }else if(t==2){
        memset(sql,0,1280);
        sprintf(sql,"update 身份信息 set passwd = '%s' where id = '%s'",bag1->read_buf,bag1->send_id);
        mysql_query(&mysql,sql);
        printf("修改中...\n");
    }
    pthread_mutex_unlock(&mutex);
}

int deal(bag *recv_bag)
{
    bag *bag1=recv_bag;
    char sql[1280];
    MYSQL_RES *result=NULL;
    MYSQL_ROW row;
    switch(bag1->type1)
    {
        case 1:
        {
            if(strcmp(bag1->read_buf,"tongyi")==0)
            {
                pthread_mutex_lock(&mutex);
                memset(sql,0,1280);
                sprintf(sql,"update friend set relation = 1 where id1 = '%s' and id2 = '%s'",bag1->recv_id,bag1->send_id);
                mysql_query(&mysql,sql);

                memset(sql,0,1280);
                sprintf(sql,"insert into friend values('%s','%s',1)",bag1->send_id,bag1->recv_id);
                mysql_query(&mysql,sql);
                pthread_mutex_unlock(&mutex);
            }else if(strcmp(bag1->read_buf,"jujue")==0){
                memset(sql,0,1280);
                sprintf(sql," delete from friend where relation = 0 and id1 ='%s' and id2 = '%s' ",bag1->recv_id,bag1->send_id);
                mysql_query(&mysql,sql);
            }
            break;
        }
    }
}

int del_fri(bag *recv_bag)
{
    bag *bag1=recv_bag;
    char sql[1280];
    char sql1[1280];
    MYSQL_RES *result=NULL;
    MYSQL_ROW row;
    memset(sql,0,1280);
    sprintf(sql,"select * from friend where id1 ='%s' and id2 = '%s'",bag1->send_id,bag1->recv_id);
    mysql_query(&mysql,sql);
    result=mysql_store_result(&mysql);
    row=mysql_fetch_row(result);

    if(row)
    {
        pthread_mutex_lock(&mutex);
        memset(sql,0,1280);
        sprintf(sql,"delete from friend where id1 = '%s' and id2 ='%s'",bag1->send_id,bag1->recv_id);
        mysql_query(&mysql,sql);
        memset(sql1,0,1280);
        sprintf(sql1,"delete from friend where id1 = '%s' and id2 ='%s'",bag1->recv_id,bag1->send_id);
        mysql_query(&mysql,sql1);
        pthread_mutex_unlock(&mutex);
        memset(bag1->write_buf,0,sizeof(bag1->write_buf));

        strcpy(bag1->write_buf,"delete success");
    }else{
        memset(bag1->write_buf,0,sizeof(bag1->write_buf));
        strcpy(bag1->write_buf,"no exist");
    }
    send(bag1->recv_fd,bag1,sizeof(bag),0);
    return 0;
}

int display_fri(bag *recv_bag)
{
    bag *bag1=recv_bag;
    fri *list;
    list=(fri *)malloc(sizeof(fri));
    char sql[1280];
    char sql1[1280];
    MYSQL_RES *result=NULL;
    MYSQL_RES *result1=NULL;
    MYSQL_ROW row,row1;
    int ret;
   

    list->fri_number=0;

    pthread_mutex_lock(&mutex);
    memset(sql,0,1280);
    sprintf(sql,"select * from friend where id1 ='%s' and relation =1",bag1->send_id);
    mysql_query(&mysql,sql);
    result=mysql_store_result(&mysql);

    while(row=mysql_fetch_row(result))
    {
        list->fri_id[list->fri_number]=atoi(row[1]);
        
        memset(sql1,0,1280);
        sprintf(sql1,"select * from  身份信息 where id = '%s'",row[1]);
        mysql_query(&mysql,sql1);
        result1=mysql_store_result(&mysql);
        row1=mysql_fetch_row(result1);

        list->fri_line[list->fri_number]=atoi(row1[3]);
        strcpy(list->fri_name[list->fri_number],row1[1]);

        list->fri_number++;
    }
    pthread_mutex_unlock(&mutex);
    memset(bag1->write_buf,0,sizeof(bag1->write_buf));

    if(list->fri_number==0)
    {
        strcpy(bag1->write_buf,"no exist");
    }else{
        strcpy(bag1->write_buf,"success");
    }

    send(bag1->recv_fd,bag1,sizeof(bag),0);
    send(bag1->recv_fd,list,sizeof(fri),0);
    return 0;
}

int black_fri(bag *recv_bag)
{
    bag *bag1;
    bag1=recv_bag;
    char sql[1280];
    MYSQL_RES *result;
    MYSQL_ROW row;

    pthread_mutex_lock(&mutex);
    memset(sql,0,sizeof(sql));
    sprintf(sql,"select *from friend where id1 ='%s' and id2='%s' and relation =1 ",bag1->send_id,bag1->recv_id);
    mysql_query(&mysql,sql);
    result=mysql_store_result(&mysql);
    row=mysql_fetch_row(result);
    if(row==NULL)
    {
        memset(bag1->write_buf,0,sizeof(bag1->write_buf));
        strcpy(bag1->write_buf,"no exist");
    }else{
        memset(sql,0,sizeof(sql));
        sprintf(sql,"update friend set relation = -1 where id1 = '%s' and id2 ='%s' ",bag1->send_id,bag1->recv_id);
        mysql_query(&mysql,sql);

        memset(sql,0,sizeof(sql));
        sprintf(sql,"update friend set relation = -1 where id1 = '%s' and id2 ='%s' ",bag1->recv_id,bag1->send_id);
        mysql_query(&mysql,sql);
        strcpy(bag1->write_buf,"success");
    }
    send(bag1->recv_fd,bag1,sizeof(bag),0);
    pthread_mutex_unlock(&mutex);
    return 0;
}

int white_fri(bag *recv_bag)
{
    bag *bag1;
    bag1=recv_bag;
    char sql[1280];
    MYSQL_RES *result;
    MYSQL_ROW row;

    pthread_mutex_lock(&mutex);
    memset(sql,0,sizeof(sql));
    sprintf(sql,"select *from friend where id1 ='%s' and id2='%s' and relation = -1 ",bag1->send_id,bag1->recv_id);
    mysql_query(&mysql,sql);
    result=mysql_store_result(&mysql);
    row=mysql_fetch_row(result);
    if(row==NULL)
    {
        memset(bag1->write_buf,0,sizeof(bag1->write_buf));
        strcpy(bag1->write_buf,"failed");
    }else{
        memset(sql,0,sizeof(sql));
        sprintf(sql,"update friend set relation = 1 where id1 = '%s' and id2 ='%s' ",bag1->send_id,bag1->recv_id);
        mysql_query(&mysql,sql);

        memset(sql,0,sizeof(sql));
        sprintf(sql,"update friend set relation = 1 where id1 = '%s' and id2 ='%s' ",bag1->recv_id,bag1->send_id);
        mysql_query(&mysql,sql);
        strcpy(bag1->write_buf,"success");
    }
    send(bag1->recv_fd,bag1,sizeof(bag),0);
    pthread_mutex_unlock(&mutex);
    return 0;
}

int chat_single(bag *recv_bag)
{
    bag *bag1;
    bag1=recv_bag;
    char sql[1280];
    MYSQL_RES *result=NULL;
    MYSQL_ROW row,row1;
    BOX *box;
    time_t t;
    char shijian[100];

    memset(sql,0,1280);
    sprintf(sql,"select * from 身份信息 where id = '%s' ",bag1->recv_id);
    mysql_query(&mysql,sql);
    result=mysql_store_result(&mysql);
    row=mysql_fetch_row(result);

    if(row==NULL)
    {
        strcpy(bag1->write_buf,"failed");
        send(bag1->recv_fd,bag1,sizeof(bag),0);
        return 0;
    }else{
        memset(sql,0,1280);
        sprintf(sql,"select * from friend where id1 ='%s' and id2 ='%s' ",bag1->send_id,bag1->recv_id);
        mysql_query(&mysql,sql);
        result=mysql_store_result(&mysql);
        row1=mysql_fetch_row(result);
        if(row1!=NULL)
        {
            if(atoi(row1[2])==-1)//黑名单
            {
                strcpy(bag1->write_buf,"black");
                send(bag1->send_fd,bag1,sizeof(bag),0);
                return 0;   
            }else{
                bag1->send_fd=atoi(row[4]);
                pthread_mutex_lock(&mutex);
                strcpy(bag1->write_buf,"success");
                send(bag1->recv_fd,bag1,sizeof(bag),0);
                pthread_mutex_unlock(&mutex);

                if(atoi(row[3])==1){
                    bag1->type=19;
                    send(bag1->send_fd,bag1,sizeof(bag),0);//给收消息的那端发消息
                }else{
                    box=box_head;
                    while(box!=NULL)
                    {
                        if(box->recv_id==atoi(bag1->recv_id))
                        {
                            break;
                        }
                        box=box->next;
                    }

                    if(box==NULL)
                    {
                        box=(BOX *)malloc(sizeof(BOX));
                        box->friend_number=0;
                        box->recv_id=atoi(bag1->recv_id);
                        box->talk_number=0;
                        box->number=0;
                        box->file_number=0;
                        box->next=NULL;
                        box->send_id[box->talk_number]=atoi(bag1->send_id);
                        strcpy(box->read_buf[box->talk_number],bag1->read_buf);
                        box->talk_number++;
                        if(box_head==NULL)
                        {
                            box_head=box;
                            box_tail=box;
                        }else{
                            box_tail->next=box;
                            box_tail=box;
                        }
                    }else{
                        box->send_id[box->talk_number]=atoi(bag1->send_id);
                        strcpy(box->read_buf[box->talk_number],bag1->read_buf);
                        box->talk_number++;
                    }
                }
                memset(sql,0,sizeof(sql));
                time(&t);
                ctime_r(&t,shijian);
                sprintf(sql,"insert into friend_mes values('%s','%s','%s','%s')",bag1->send_id,bag1->recv_id,bag1->read_buf,shijian);
                mysql_query(&mysql,sql);
            }
        }else{
            strcpy(bag1->write_buf,"failed");
            send(bag1->send_fd,bag1,sizeof(bag),0);
            return 0;
        }
    }
}

int mes_fri(bag * recv_bag)
{
    bag * bag1=recv_bag;
    fri_mes *message;
    char sql[1280];
    MYSQL_RES *result=NULL;
    MYSQL_ROW row;
    message=(fri_mes *)malloc(sizeof(fri_mes));

    message->buf_num=0;
   
    memset(sql,0,sizeof(sql));
    sprintf(sql,"select *from friend_mes where ( id1 ='%s' and id2 ='%s') or (id1 ='%s' and id2 ='%s')",bag1->send_id,bag1->recv_id,bag1->recv_id,bag1->send_id);

    mysql_query(&mysql,sql);
    result=mysql_store_result(&mysql);
    while(row=mysql_fetch_row(result))
    {
        message->id[message->buf_num]=atoi(row[0]);
        message->fri_id[message->buf_num]=atoi(row[1]);
        strcpy(message->buf[message->buf_num],row[2]);
        strcpy(message->time[message->buf_num],row[3]);
        message->buf_num++;
    }
    send(bag1->recv_fd,bag1,sizeof(bag),0);
    send(bag1->recv_fd,message,sizeof(fri_mes),0);
    return 0;
}

int create_gro(bag *recv_bag)
{
    bag *bag1=recv_bag;
    int j=999;
    MYSQL_RES *result=NULL;
    MYSQL_ROW row,row1;
    char sql[1280];
    int ret;
    gro *group;

    group=(gro *)malloc(sizeof(gro));
    memset(sql,0,sizeof(sql));
    sprintf(sql,"select * from gro");
    pthread_mutex_lock(&mutex);
    ret=mysql_query(&mysql,sql);
    if(!ret)
    {
        result=mysql_store_result(&mysql);
        while(row=mysql_fetch_row(result))
        {
            if(j<atoi(row[0]))
            {
                j=atoi(row[0]);
            }
        }
        j++;
        group->gro_id=j;

        strcpy(bag1->write_buf,"success");
        sprintf(bag1->recv_id,"%d",group->gro_id);

        memset(sql,0,sizeof(sql));
        sprintf(sql,"select * from 身份信息 where id ='%s'",bag1->send_id);
        mysql_query(&mysql,sql);
        result=mysql_store_result(&mysql);
        row1=mysql_fetch_row(result);
        
        strcpy(group->gro_name,row1[1]);
        group->gro_mem_id=atoi(bag1->send_id);

        memset(sql,0,sizeof(sql));
        sprintf(sql,"insert into gro values (%d, %d,'%s',2) ",group->gro_id,group->gro_mem_id,group->gro_name);
        mysql_query(&mysql,sql);
    }else{
        strcpy(bag1->write_buf,"failed");
    }
    send(bag1->recv_fd,bag1,sizeof(bag),0);
    pthread_mutex_unlock(&mutex);
    return 0;
    
}

int dis_gro(bag *recv_bag)
{
    bag * bag1=recv_bag;
    char sql[1280];
    int ret;
    MYSQL_RES *result=NULL;
    MYSQL_ROW row;
    memset(sql,0,sizeof(sql));
    pthread_mutex_lock(&mutex);
    sprintf(sql,"select *from gro where gro_id = %d and gro_member_id = %d ",atoi(bag1->read_buf),atoi(bag1->send_id));
    ret=mysql_query(&mysql,sql);
    if(!ret){
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row==NULL)
        {
            strcpy(bag1->write_buf,"failed");
        }else{
            if(atoi(row[3])==2)
            {
                strcpy(bag1->write_buf,"success");
                memset(sql,0,sizeof(sql));
                sprintf(sql,"delete from gro where gro_id = %d ",atoi(bag1->read_buf));
                mysql_query(&mysql,sql);
            }else{
                strcpy(bag1->write_buf,"no rights");
            }
        }
    }else{
        strcpy(bag1->write_buf,"failed");
    }

    send(bag1->recv_fd,bag1,sizeof(bag),0);
    pthread_mutex_unlock(&mutex);
    return 0;
}

int add_gro(bag *recv_bag)
{
    bag *bag1=recv_bag;
    char sql[1280];
    char sql1[1280];
    MYSQL_RES *result=NULL;
    MYSQL_ROW row,row1,row2;
    int ret;
    BOX *box;

    box=(BOX *)malloc(sizeof(BOX));
    memset(sql,0,sizeof(sql));
    sprintf(sql,"select * from gro where gro_id ='%d'", atoi(bag1->read_buf));
    ret=mysql_query(&mysql,sql);
    if(!ret){
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row!=NULL)
        {   
            pthread_mutex_lock(&mutex);

            memset(sql,0,sizeof(sql));
            sprintf(sql,"select *from gro where gro_id = %d and gro_member_id = %d",atoi(bag1->read_buf),atoi(bag1->send_id));
            mysql_query(&mysql,sql);
            result=mysql_store_result(&mysql);
            row2=mysql_fetch_row(result);

            if(row2!=NULL){
                strcpy(bag1->write_buf,"sended");
                pthread_mutex_unlock(&mutex);
            }else{
                memset(sql,0,sizeof(sql));
                sprintf(sql,"select *from 身份信息 where id = '%s'",bag1->send_id);
                mysql_query(&mysql,sql);
                result=mysql_store_result(&mysql);
                row1=mysql_fetch_row(result);
                strcpy(bag1->send_name,row1[1]);

                memset(sql,0,sizeof(sql));
                sprintf(sql,"insert into gro values(%d,%d,'%s',0)",atoi(bag1->read_buf),atoi(bag1->send_id),bag1->send_name);
                mysql_query(&mysql,sql);
                strcpy(bag1->write_buf,"sending");
                pthread_mutex_unlock(&mutex);
            }
        }else{
            strcpy(bag1->write_buf,"failed");
        }
    }else{
        strcpy(bag1->write_buf,"failed");
    }
    send(bag1->recv_fd,bag1,sizeof(bag),0);
    return 0;
}

int exit_gro(bag *recv_bag)
{
    bag *bag1=recv_bag;
    char sql[1280];
    MYSQL_RES *result=NULL;
    MYSQL_ROW row;
    int ret;

    memset(sql,0,sizeof(sql));

    sprintf(sql,"select *from gro where gro_id = %d and gro_member_id= %d ",atoi(bag1->read_buf),atoi(bag1->send_id));
    ret=mysql_query(&mysql,sql);
    if(!ret)
    {
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row!=NULL)
        {
            if(atoi(row[3])!=2){
                memset(sql,0,sizeof(sql));
                sprintf(sql,"delete from gro where gro_id = %d and gro_member_id= %d",atoi(bag1->read_buf),atoi(bag1->send_id));
                mysql_query(&mysql,sql);
                
            }else{
                memset(sql,0,sizeof(sql));
                sprintf(sql,"delete from  gro where gro_id = %d",atoi(bag1->read_buf));
                mysql_query(&mysql,sql);
            }
            strcpy(bag1->write_buf,"success");
        }else{
            strcpy(bag1->write_buf,"no find");
        }
    }else{
        strcpy(bag1->write_buf,"failed");
    }
    send(bag1->recv_fd,bag1,sizeof(bag),0);
    return 0;
}

int check_mes(bag *recv_bag)
{
    bag *bag1=recv_bag;
    gro_mes *message;
    char sql[1280];
    MYSQL_RES *result=NULL;
    MYSQL_ROW row;

    message=(gro_mes *)malloc(sizeof(gro_mes));
    message->number=0;
    memset(sql,0,sizeof(sql));
    sprintf(sql,"select * from gro_mes where gro_id =%d",atoi(bag1->read_buf));
    mysql_query(&mysql,sql);
    result=mysql_store_result(&mysql);
    while(row=mysql_fetch_row(result))
    {
        message->gro_id=atoi(bag1->read_buf);
        strcpy(message->buf[message->number],row[2]);
        message->id[message->number]=atoi(row[1]);
        strcpy(message->time[message->number],row[3]);
        message->number++;
    }
    send(recv_bag->recv_fd,bag1,sizeof(bag),0);
    send(recv_bag->recv_fd,message,sizeof(gro_mes),0);
    return 0;
}

int deal_gro(bag *recv_bag)
{
    bag *bag1=recv_bag;
    char sql[1280];
    int ret;
    MYSQL_RES *result=NULL;
    MYSQL_ROW row,row1;

    memset(sql,0,sizeof(sql));
    sprintf(sql,"select * from gro where gro_id = %d and chmod =2 ",atoi(bag1->read_buf));//找群主
    ret=mysql_query(&mysql,sql);
    if(!ret)
    {
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row!=NULL)
        {
            memset(sql,0,sizeof(sql));
            sprintf(sql,"select * from gro where gro_id =%d and gro_member_id =%d",atoi(bag1->read_buf),atoi(bag1->recv_id));//找人
            mysql_query(&mysql,sql);
            result=mysql_store_result(&mysql);
            row1=mysql_fetch_row(result);

            if(row1!=NULL){
                if(strcmp(row[1],bag1->send_id)==0){
                    switch(bag1->type1)
                    {
                        case 1:
                        {
                            
                                if(atoi(row1[3])==1)
                                {
                                    strcpy(bag1->write_buf,"dealed");
                                }else{
                                    memset(sql,0,sizeof(sql));
                                    sprintf(sql,"update gro set chmod=1 where gro_id=%d and gro_member_id =%d",atoi(bag1->read_buf),atoi(bag1->recv_id)); 
                                    mysql_query(&mysql,sql);
                                    strcpy(bag1->write_buf,"success");
                                }                        
                        
                            break;
                        }
                        case 2:
                        {
                            
                                if(atoi(row1[3])==1)
                                {
                                    memset(sql,0,sizeof(sql));
                                    sprintf(sql,"update gro set chmod=0 where gro_id=%d and gro_member_id =%d",atoi(bag1->read_buf),atoi(bag1->recv_id));
                                    mysql_query(&mysql,sql);
                                    strcpy(bag1->write_buf,"success");
                                }else{
                                    strcpy(bag1->write_buf,"no admin");
                                }
                            
                            break;
                        }
                        case 3:
                        {
                            if(atoi(row1[3])!=2)
                            {
                                memset(sql,0,sizeof(sql));
                                sprintf(sql,"delete from gro where gro_id =%d and gro_member_id =%d ",atoi(bag1->read_buf),atoi(bag1->recv_id));
                                mysql_query(&mysql,sql);
                                strcpy(bag1->write_buf,"success");
                            }else{
                                strcpy(bag1->write_buf,"no possible");
                            }
                            break;
                        }
                    }
                }else{
                    strcpy(bag1->write_buf,"no chmod");
                }
            }else{
                strcpy(bag1->write_buf,"no find id");
            }
        }else{
            strcpy(bag1->write_buf,"no find gro");
        }
    }else{
        strcpy(bag1->write_buf,"failed");
    }
    send(bag1->recv_fd,bag1,sizeof(bag),0);
    return 0;
}

int chat_double(bag *recv_bag)
{
    bag *bag1=recv_bag;
    char sql[1280];
    char sql1[1280];
    int ret;
    MYSQL_RES *result=NULL;
    MYSQL_RES *result1=NULL;
    MYSQL_ROW row,row1,row2;
    BOX *box;
    char shijian[100];
    time_t t;

    
    box=box_head;
    memset(sql,0,sizeof(sql));
    sprintf(sql,"select * from gro where gro_id = %d and gro_member_id = %d",atoi(bag1->read_buf),atoi(bag1->send_id));
    ret=mysql_query(&mysql,sql);
    if(!ret)
    {
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row!=NULL)
        {
            memset(sql,0,sizeof(sql));
            sprintf(sql,"select * from gro where gro_id = %d",atoi(bag1->read_buf));
            mysql_query(&mysql,sql);
            result=mysql_store_result(&mysql);

            while(row1=mysql_fetch_row(result))
            {
                if(strcmp(row1[1],bag1->send_id)==0){
                    continue;
                }
                    strcpy(bag1->recv_id,row1[1]);
                    
                    memset(sql1,0,sizeof(sql));
                    sprintf(sql1,"select *from 身份信息 where id = '%s'",bag1->recv_id);
                    mysql_query(&mysql,sql1);
                    result1=mysql_store_result(&mysql);
                    row2=mysql_fetch_row(result1);
                    strcpy(bag1->buf,"success");
                    bag1->send_fd=atoi(row2[4]);
                    send(bag1->recv_fd,bag1,sizeof(bag),0);
                    
                    if(atoi(row2[3])==1)//在线
                    {
                        bag1->type=20;
                        send(bag1->send_fd,bag1,sizeof(bag),0);
                    }else{
                        while(box!=NULL)
                        {
                            if(box->recv_id==atoi(bag1->recv_id))
                            {
                                break;
                            }
                            box=box->next;
                        }
                        
                        if(box==NULL)
                        {
                            box=(BOX *)malloc(sizeof(BOX));
                            box->recv_id=atoi(bag1->recv_id);
                            box->friend_number=0;
                            box->number=0;
                            box->talk_number=0;
                            box->file_number=0;
                            box->next=NULL;
                            box->send_id1[box->number]=atoi(bag1->send_id);
                            box->group_id[box->number]=atoi(bag1->read_buf);
                            strcpy(box->message[box->number],bag1->write_buf);
                            box->number++;
                            if(box_head==NULL)
                            {
                                box_head=box;
                                box_tail=box;
                            }else{
                                box_tail->next=box;
                                box_tail=box;
                            }
                        }else{
                            box->send_id1[box->number]=atoi(bag1->send_id);
                            box->group_id[box->number]=atoi(bag1->read_buf);
                            strcpy(box->message[box->number],bag1->write_buf);
                            box->number++;
                        }
                    }
            }   
            memset(sql,0,sizeof(sql));
            time(&t);
            ctime_r(&t,shijian);
            sprintf(sql,"insert into gro_mes values(%d,%d,'%s','%s')",atoi(bag1->read_buf),atoi(bag1->send_id),bag1->write_buf,shijian);
            mysql_query(&mysql,sql);    
        }else{
            strcpy(bag1->buf,"no find");
            send(bag1->recv_fd,bag1,sizeof(bag),0);
        }
    }else{
        strcpy(bag1->buf,"failed");
        send(bag1->recv_fd,bag1,sizeof(bag),0);
    }
    return 0;
}

int send_file(bag *recv_bag)
{
    bag *bag1=recv_bag;
    int fd=open("file", O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IXUSR);
    char sql[1280];
    MYSQL_RES *result=NULL;
    MYSQL_ROW row;
    int ret;
    int len;

    if(strcmp(bag1->buf,"ok")==0)
    {
        memset(sql,0,sizeof(sql));
        sprintf(sql,"select * from 身份信息 where id= '%s'",bag1->recv_id);
        ret=mysql_query(&mysql,sql);
        if(!ret){
            result=mysql_store_result(&mysql);
            row=mysql_fetch_row(result);
            if(row!=NULL){
                if(atoi(row[3])==0)
                {
                    memset(bag1->buf,0,sizeof(bag1->buf));
                    strcpy(bag1->buf,"no online");
                    send(bag1->recv_fd,bag1,sizeof(bag),0);
                }else{
                    memset(bag1->buf,0,sizeof(bag1->buf));
                    strcpy(bag1->buf,"success");

                    send(bag1->recv_fd,bag1,sizeof(bag),0);
                    bag1->send_fd=atoi(row[4]);
                    bag1->type=22;
                    send(bag1->send_fd,bag1,sizeof(bag),0);
                }
            }else{
                memset(bag1->buf,0,sizeof(bag1->buf));
                strcpy(bag1->buf,"no find");
                send(bag1->recv_fd,bag1,sizeof(bag),0);
            }
        }
    }else{
        write(fd,bag1->write_buf,bag1->size);
        close(fd);
        send(bag1->recv_fd,bag1,sizeof(bag),0);
    }
    return 0;
}

int recv_file(bag *recv_bag)
{
    bag *bag1=recv_bag;
    int fd=open("file",O_RDONLY);
    int len;

    memset(bag1->write_buf,0,sizeof(bag1->write_buf));
    memset(bag1->buf,0,sizeof(bag1->buf));
    lseek(fd,(-1)*bag1->t,SEEK_END);
   
    while((len=read(fd,bag1->write_buf,1023))>0)
    {
        bag1->size=len;
        send(bag1->recv_fd,bag1,sizeof(bag),0);
    }
    close(fd);
    return 0;
}

int check_fri_fro(bag * recv_bag)
{
    bag *bag1=recv_bag;
    char sql[1280];
    MYSQL_RES *result=NULL;
    MYSQL_ROW row;
    int ret;
    fri *list;

    list=(fri *)malloc(sizeof(fri));
    list->fri_number=0;
    memset(sql,0,sizeof(sql));
    sprintf(sql,"select* from gro where gro_id= %d order by chmod desc",atoi(bag1->read_buf));
    ret=mysql_query(&mysql,sql);

    if(!ret)
    {
        result=mysql_store_result(&mysql);
        while(row=mysql_fetch_row(result))
        {
            list->fri_id[list->fri_number]=atoi(row[1]);
            strcpy(list->fri_name[list->fri_number],row[2]);
            list->fri_line[list->fri_number]=atoi(row[3]);
            list->fri_number++;
        }
        strcpy(bag1->write_buf,"success");
    }else{
        strcpy(bag1->write_buf,"failed");
    }
    send(bag1->recv_fd,bag1,sizeof(bag),0);
    send(bag1->recv_fd,list,sizeof(fri),0);
    return 0;
}

int check_info(bag *recv_bag)
{
    bag *bag1=recv_bag;
    char sql[1280];
    MYSQL_RES *result=NULL;
    MYSQL_ROW row;

    memset(sql,0,sizeof(sql));
    sprintf(sql,"select * from 身份信息 where id =%s",bag1->send_id);
    mysql_query(&mysql,sql);
    result=mysql_store_result(&mysql);
    row=mysql_fetch_row(result);

    if(row==NULL)
    {
        strcpy(bag1->write_buf,"failed");
    }else{
        strcpy(bag1->write_buf,"success");
        strcpy(bag1->send_name,row[1]);
    }
    send(bag1->recv_fd,bag1,sizeof(bag),0);
    return 0;
}

int check_group(bag *recv_bag)
{
    bag *bag1=recv_bag;
    group *lis;
    char sql[1280];
    MYSQL_RES *result=NULL;
    MYSQL_ROW row;

    lis=(group *)malloc(sizeof(group));
    lis->number=0;
    memset(sql,0,sizeof(sql));
    sprintf(sql,"select * from gro where gro_member_id =%d order by chmod desc",atoi(bag1->send_id));
    mysql_query(&mysql,sql);
    result=mysql_store_result(&mysql);

    while(row=mysql_fetch_row(result))
    {
        lis->id[lis->number]=atoi(row[0]);
        lis->chmod[lis->number]=atoi(row[3]);
        lis->number++;
    }
    if(lis->number!=0){
        strcpy(bag1->write_buf,"success");
    }else{
        strcpy(bag1->write_buf,"failed");
    }
    send(bag1->recv_fd,bag1,sizeof(bag),0);
    send(bag1->recv_fd,lis,sizeof(group),0);
    return 0;
}

void *func(void *bag1)
{
    pthread_detach(pthread_self());
    BOX *box=box_head;
    bag *recv_bag;
    recv_bag=(bag *)bag1;
    
    int t;
    int ret;
   

    switch(recv_bag->type)
    {   
        case 1://登陆
        {
            t=login(recv_bag);
            if(t==1)
            {
                while(box!=NULL)
                {
                    if(box->recv_id==atoi(recv_bag->send_id)){
                        break;
                    }
                    box=box->next;
                }
                if(box!=NULL)
                {
                    send(recv_bag->recv_fd,box,sizeof(BOX),0);
                    box->friend_number=0;
                    box->talk_number=0;
                }else{
                    box=(BOX *)malloc(sizeof(BOX));
                    box->recv_id=atoi(recv_bag->send_id);
                    box->friend_number=box->talk_number=0;
                    box->number=0;
                    box->next=NULL;
                    if(box_head==NULL)
                    {
                        box_head=box;
                        box_tail=box;
                    }else{
                        box_tail->next=box;
                        box_tail=box;
                    }
                    send(recv_bag->recv_fd,box,sizeof(BOX),0);
                }
            }
            break;
        }
        case 2://注册
        {
            resign(recv_bag);
            break;
        }
        case 3://私聊
        {
            chat_single(recv_bag);
            break;
        }
        case 4://加好友
        {
            add_fri(recv_bag);
            break;
        }
        case 5://删好友
        {
            del_fri(recv_bag);
            break;
        }
        case 6://显示好友
        {
            display_fri(recv_bag);
            break;
        }
        case 7://聊天记录 
        {
            mes_fri(recv_bag);
            break;
        }
        case 8://拉黑好友
        {
            black_fri(recv_bag);
            break;
        }
        case 9://移出好友
        {
            white_fri(recv_bag);
            break;
        }
        case 10://开始群聊
        {
            chat_double(recv_bag);
            break;
        }
        case 11://创建群聊
        {
            create_gro(recv_bag);
            break;
        }
        case 12://解散群聊
        {
            dis_gro(recv_bag);
            break;
        }
        case 13://申请加群
        {
            add_gro(recv_bag);
            break;
        }
        case 14://退出群聊
        {
            exit_gro(recv_bag);
            break;
        }
        case 15://查看群聊天记录
        {
            check_mes(recv_bag);
            break;
        }
        case 16://管理群事务 
        {
            deal_gro(recv_bag);
            break;
        }
        case 17://修改信息
        {
            xiugai(recv_bag);
            break; 
        } 
        case 18://处理消息
        {
            deal(recv_bag);
            break;
        }
        case 21://传送文件
        {
            send_file(recv_bag);
            break;
        }
        case 23://接收文件
        {
            recv_file(recv_bag);
            break;
        }
        case 24://查看群好友
        {
            check_fri_fro(recv_bag);
            break;
        }
        case 25://查看个人信息
        {
            check_info(recv_bag);
            break;
        }
        case 26://查看群好友
        {
            check_group(recv_bag);
            break;
        }
    }
}

void service(int sock_fd)
{
    printf("服务器启动...\n");
    bag recv_bag;
    bag *bag1;
    struct sockaddr_in client_addr;
    socklen_t len;
    struct epoll_event epfd;
    struct epoll_event ev[20];
    char choice[2];

    int conn_fd;
    int epollfd;
    int maxevents;
    int ready;
    int i;
    int ret;
    char sql[128];
    MYSQL_RES *result=NULL;
    MYSQL_ROW row;

    len=sizeof(struct sockaddr_in);

    epollfd=epoll_create(1024);

    epfd.data.fd=sock_fd;
    epfd.events=EPOLLIN | EPOLLET;//读 et

    if((epoll_ctl(epollfd, EPOLL_CTL_ADD, sock_fd, &epfd))<0)
    {
        perror("epoll_ctl failed");
        return ;
    }

    maxevents=1;
    while(1)
    {
        if(maxevents==0)
        {
            maxevents++;
        }
        if((ready=epoll_wait(epollfd,ev,maxevents,-1))<=0)
        {
            perror("epoll_wait failed");
            continue;
        }

        for(i=0;i<ready;i++)
        {
            if(ev[i].data.fd==sock_fd)
            {
                if((conn_fd = accept(sock_fd, (struct sockaddr*)&client_addr, &len))<0)
                {
                    perror("accept failed");
                    continue;
                }
                printf("连接成功,套接字为%d\n",conn_fd);

                epfd.data.fd=conn_fd;
                epfd.events=EPOLLIN | EPOLLET;

                if((epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_fd, &epfd))<0)
                {
                    perror("epoll_ctl failed");
                    continue;
                }
                maxevents++;
                continue;
            }else if(ev[i].events & EPOLLIN)
            {
                memset(&recv_bag,0,sizeof(bag));
                //printf("流程%d\n",ev[i].data.fd);
                ret=recv(ev[i].data.fd,&recv_bag,sizeof(bag),MSG_WAITALL);
                
                if(ret<0)
                {
                    close(ev[i].data.fd);
                    perror("recv failed");
                    continue;
                }

                if(recv_bag.type==0)
                {
                    send(ev[i].data.fd,&recv_bag,sizeof(bag),0);
                    memset(sql,0,128);
                    sprintf(sql,"update 身份信息 set line = 0 , sockfd = 0 where line =1 and id ='%s' ",recv_bag.send_id);
                    mysql_query(&mysql,sql);
                    epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_fd, &epfd);
                    maxevents--;
                    continue;
                }
                
                pthread_t tid;
                recv_bag.recv_fd=ev[i].data.fd;
                bag1 = (bag*)malloc(sizeof(bag));
                memcpy(bag1, &recv_bag, sizeof(bag));
                pthread_create(&tid,NULL,func,(void *)bag1);
            }
        }
    }
}

void close_mysql()
{
    mysql_close(&mysql);
    mysql_library_end();
}

int main()
{
    int sock_fd=sock_init();
    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond,NULL);
    mysql_init1();
    service(sock_fd);
    close_mysql();
} 

编译命令

$ gcc -I/usr/include/mysql server.c -L/usr/lib/mysql -lmysqlclient -ldl -lpthread -o server
$./server

客户端

#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<errno.h> 
#include<stdlib.h>
#include"my_chat.h"
#include <termios.h>
#include <sys/stat.h>
#include <fcntl.h>

bag *recv_bag;
bag *send_bag;
int sing;
BOX *box;
pthread_t tid;
fri *list;
fri_mes *mes;
gro_mes *message;
group *lis;

int socket_init(struct sockaddr_in client_addr)
{
    int sock_fd=socket(AF_INET,SOCK_STREAM,0);
    
    client_addr.sin_addr.s_addr=htonl(INADDR_ANY);//通信对象的IP地址,0.0.0.0表示所有IP地址
    //client_addr.sin_addr.s_addr=inet_addr("192.168.30.155");
    client_addr.sin_family=AF_INET; //IPv4协议
    client_addr.sin_port=htons(SERV_PORT);//应用层端口号
    //绑定套接字和结构体----主机自检端口号是否重复,IP是否准确
    if(connect(sock_fd,(struct sockaddr *)&client_addr,sizeof(client_addr))<0)
    {
        perror("connect failed");
        return -1;
    }else{
        printf("客户端初始化完成\n");
    }
    return sock_fd;

}

void getpasswd(char *passwd)
{
    struct termios oldt, newt;
    char ch;
    tcgetattr(0, &oldt);
    newt = oldt;
    newt.c_lflag &= ~(ICANON | ECHO);
    int  i = 0;

    while(1)
    {
        tcsetattr(0, TCSANOW, &newt);
        ch = getchar();
        tcsetattr(0, TCSANOW, &oldt);
        if(ch=='\n')
        {
            passwd[i]='\0';
            break;
        }
        passwd[i]=ch;
        i++;
        printf("*");
    }
    printf("\n");
}

int login(int fd)
{
    int ret;

    printf("--------------------------------------------\n");
    printf("                 请输入账号:\n");
    scanf("%s",send_bag->send_id);
    getchar();
    printf("                 请输入密码:\n");
    getpasswd(send_bag->read_buf);
    memset(send_bag->write_buf,0,1024);
    ret=send(fd,send_bag,sizeof(bag),0);//发帐号密码
    if(ret<0)
    {
        perror("send failed");
        exit(1);
    }
    pthread_mutex_lock(&mutex_cli);
    while(sing==0){
        pthread_cond_wait(&cond_cli, &mutex_cli);
    }
    pthread_mutex_unlock(&mutex_cli);
    sing=0;

}

int resign(int fd)
{
    int ret;
    char passwd[8];
    memset(passwd,0,8);
    printf("--------------------------------------------\n");
    printf("                 请输入昵称:\n");
    scanf("%s",send_bag->send_name);
    getchar();
    printf("                 请输入密码:\n");
    getpasswd(send_bag->read_buf);
    printf("                 请再输入一次密码:\n");
    getpasswd(passwd);

    while(1){
        if(strcmp(send_bag->read_buf,passwd)==0)
        {
            printf("                 两次输入一致!\n");
            ret=send(fd,send_bag,sizeof(bag),0);//发送帐号密码
            if(ret<0)
            {
                perror("send failed");
                exit(1);
            }

            pthread_mutex_lock(&mutex_cli);
            pthread_cond_wait(&cond_cli, &mutex_cli);
            pthread_mutex_unlock(&mutex_cli);

            printf("                 注册成功!你的账号是%s\n",send_bag->send_id);
            printf("                 请重新登陆!\n");
            break;
        }else{
            printf("                 输入不正确!请再次输入!\n");
            printf("                 请输入:\n");
            getpasswd(passwd);
            continue;
        }
    }
   
}

int add_fri(int fd)
{
    int t;

    printf("                  输入要添加的账号:\n");
    scanf("%s",send_bag->recv_id);
    getchar();

    send(fd,send_bag,sizeof(bag),0);

    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli, &mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    t=atoi(send_bag->write_buf);
    if(t==1)
    {
        printf("                  该人已经是你的好友!\n");
    }else if(t==-2)
    {
        printf("                  该账号不存在!\n");
    }else if(t==-1)
    {
        printf("                  该人已被你拖入黑名单!\n");
    }else if(t==0)
    {
        printf("                  已发送请求!\n");
    }else if(t==3){
        printf("                  已发送过申请!\n");
    }else{
        printf("                  添加错误!\n");
    }


    return 0;
}

int xiugai(int fd)
{
    int choice;
    
    printf("--------------------------------------------\n");
    printf("                1--修改昵称\n");
    printf("                2--修改密码\n");
    printf("                0--退出\n");
    printf("--------------------------------------------\n");
    printf("                请选择\n");
    scanf("%d",&choice);
    getchar();
    switch(choice)
    {
        case 1:
        {
            send_bag->type1=1;
            printf("                输入修改的名字:\n");
            scanf("%s",send_bag->read_buf);
            getchar();

            send(fd,send_bag,sizeof(bag),0);
            pthread_mutex_lock(&mutex_cli);
            pthread_cond_signal(&cond_cli);
            pthread_mutex_unlock(&mutex_cli);
            printf("修改完成!\n");
            break;
        }
        case 2:
        {
            send_bag->type1=2;
            printf("                输入修改的密码:\n");
            getpasswd(send_bag->read_buf);

            send(fd,send_bag,sizeof(bag),0);
            pthread_mutex_lock(&mutex_cli);
            pthread_cond_signal(&cond_cli);
            pthread_mutex_unlock(&mutex_cli);        
            printf("修改完成!\n");
            break;
        }
        case 0:
            return 0;
        default:
            printf("                  输入错误!返回!\n");
            return 0;
    }
}

void menu1()
{
    
        printf("--------------------------------------------\n");
        printf("                  菜单\n");
        printf("--------------------------------------------\n");
        printf("             1--开始私聊\n");
        printf("             2--添加好友\n");
        printf("             3--删除好友\n");
        printf("             4--显示好友列表\n");
        printf("             5--查看好友聊天记录\n");
        printf("             6--好友拖入黑名单\n");
        printf("             7--好友移出黑名单\n");
        printf("             8--开始群聊\n");
        printf("             9--创建群聊\n");
        printf("             10--解散群聊\n");
        printf("             11--申请加群\n");
        printf("             12--退出群聊\n");
        printf("             13--查看群聊天记录\n");
        printf("             14--管理群聊\n");
        printf("             15--修改个人信息\n");
        printf("             16--处理消息\n");
        printf("             17--文件传送\n");
        printf("             18--文件接收\n");
        printf("             19--查看群好友列表\n");
        printf("             20--查看个人信息\n");
        printf("             21--查看群列表\n");
        printf("             0--退出\n");
        printf("--------------------------------------------\n");
        printf("             请选择:\n");
}

void menu()
{
    printf("--------------------------------------------\n");
    printf("-----------------登录界面--------------------\n");
    printf("--------------------------------------------\n");
    printf("                 1--登陆\n");
    printf("                 2--注册\n");
    printf("                 0--退出\n");
    printf("--------------------------------------------\n");
    printf("--------------------------------------------\n");
    printf("                 请选择:\n");
}

int deal(int fd)
{
    int choose;
    int i;
    int choice;
    printf("--------------------------------------------\n");
    printf("                 1--处理好友申请\n");
    printf("                 2--查看好友消息\n");
    printf("                 3--查看群消息\n");
    printf("                 4--退出\n");
    printf("--------------------------------------------\n");
    printf("                 请选择:\n");
    scanf("%d",&choose);
    getchar();
    switch(choose)
    {
        case 1:
        {
            send_bag->type1=1;
            if(box->friend_number==0)
            {
                printf("暂无好友申请!\n");
                getchar();
                break;
            }else{
                for(i=0;i<box->friend_number;i++)
                {
                    printf("                 账号为%d请求加你为好友!\n",box->plz_id[i]);
                    printf("                 1--同意\n");
                    printf("                 2--拒绝\n");
                    printf("--------------------------------------------\n");
                    printf("                 请选择:\n");
                    scanf("%d",&choice);
                    getchar();
                    if(choice==1)
                    {
                        strcpy(send_bag->read_buf,"tongyi");
                        sprintf(send_bag->recv_id,"%d",box->plz_id[i]);
                        send(fd,send_bag,sizeof(bag),0);

                    }else if(choice ==2)
                    {
                        strcpy(send_bag->read_buf,"jujue");
                        sprintf(send_bag->recv_id,"%d",box->plz_id[i]);
                        send(fd,send_bag,sizeof(bag),0);

                    }else{
                        printf("                 输入错误!\n");
                        break;
                    }
                }
                box->friend_number=0;
                printf("                 处理完成!\n");
                memset(send_bag->read_buf,0,1024);
                break;
            }
        }
        case 2:
        {
            send_bag->type1=2;
            if(box->talk_number==0)
            {
                printf("暂无好友消息!\n");
                getchar();
                break;
            }else{
                for(i=0;i<box->talk_number;i++)
                {
                    printf("账号%d:%s\n", box->send_id[i], box->read_buf[i]);
                }
                box->talk_number=0;
                printf("处理完成!\n");
                break;
            }
        }
        case 3:
        {
            send_bag->type1=3;
            if(box->number==0)
            {
                printf("暂无群聊消息!\n");
                getchar();
                break;
            }else{
                for(i=0;i<box->number;i++)
                {
                    printf("群号为%d 账号%d:%s\n", box->group_id[i],box->send_id1[i], box->message[i]);
                }
                box->number=0;
                printf("处理完成!\n");
                break;
            }
        }
        case 4:
            break;
        default:
        {
            printf("输入错误!\n");
            printf("按任意键返回!\n");
            getchar();
            break;
        }
    }
}

int del_fri(int fd)
{
    printf("--------------------------------------------\n");
    printf("             输入要删除的好友账号:\n");
    scanf("%s",send_bag->recv_id);
    getchar();
    send(fd,send_bag,sizeof(bag),0);

    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli, &mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    if(strcmp(send_bag->write_buf,"delete success")==0)
    {
        printf("                 删除成功!\n");
    }else 
    {
        printf("                 删除失败!\n");
    }
    return 0;
}

int display_fri(int fd)
{
    int i;
    send(fd,send_bag,sizeof(bag),0);

    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli, &mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    if(strcmp(send_bag->write_buf,"success")==0)
    {
        printf("好友列表:\n");
        for(i=0;i<list->fri_number;i++)
        {
            printf("id:%d     name:%s",list->fri_id[i],list->fri_name[i]);
            if(list->fri_line[i]==1)
            {
                printf("                    --在线\n");
            }else if(list->fri_line[i]==0)
            {
                printf("                    --掉线\n");
            }
        }
    }else{
        printf("你没有好友!\n");
    }

    return 0;
}

int chat_single(int fd)
{
    printf("--------------------------------------------\n");
    printf("              输入聊天的人的账号:\n");
    scanf("%s",send_bag->recv_id);
    getchar();
    printf("与%s开始聊天!\n",send_bag->recv_id);

    while(1)
    {
        scanf("%[^\n]",send_bag->read_buf);
        getchar();
        if(strcmp(send_bag->read_buf,"#obey")==0)
        {
            printf("与%s聊天结束!\n",send_bag->recv_id);
            break;
        }

        send(fd,send_bag,sizeof(bag),0);

        pthread_mutex_lock(&mutex_cli);
        pthread_cond_wait(&cond_cli, &mutex_cli);
        pthread_mutex_unlock(&mutex_cli);

        if(strcmp(send_bag->write_buf,"black")==0)
        {
            printf("你处于黑名单中!无法发送消息!\n");
            break;
        }else if(strcmp(send_bag->write_buf,"failed")==0)
        {
            printf("聊天失败!可能不是好友!或者暂无该账号!\n");
            break;
        }
    }
    memset(send_bag->recv_id,0,sizeof(send_bag->recv_id));
    return 0;
}

int black_fri(int fd)
{
    printf("--------------------------------------------\n");
    printf("              输入拉黑的人的账号:\n");
    scanf("%s",send_bag->recv_id);
    getchar();

    send(fd,send_bag,sizeof(bag),0);

    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli, &mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    if(strcmp(send_bag->write_buf,"success")==0)
    {
        printf("拉黑成功!\n");
    }else{
        printf("拉黑失败!\n");
    }
    return 0;
}

int check_fri(int fd)
{
    int i;
    printf("--------------------------------------------\n");
    printf("             查看聊天记录的好友账号(上限五百条):\n");
    scanf("%s",send_bag->recv_id);
    getchar();

    send(fd,send_bag,sizeof(bag),0);

    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli, &mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    for(i=0;i<mes->buf_num;i++)
    {
        if(mes->id[i]==atoi(send_bag->send_id))
        printf("\033[34mtime:%s   id:%d     message;%s\n\033[0m",mes->time[i],mes->id[i],mes->buf[i]);
        else
         printf("\033[32mtime:%s   id:%d     message;%s\n\033[0m",mes->time[i],mes->id[i],mes->buf[i]);
    }
}

int white_fri(int fd)
{
    printf("--------------------------------------------\n");
    printf("              输入移出的人的账号:\n");
    scanf("%s",send_bag->recv_id);
    getchar();

    send(fd,send_bag,sizeof(bag),0);

    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli, &mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    if(strcmp(send_bag->write_buf,"success")==0)
    {
        printf("移出成功!\n");
    }else{
        printf("移出失败!\n");
    }
    return 0;
}

int create_gro(int fd)
{
    send(fd,send_bag,sizeof(bag),0);

    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli, &mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    if(strcmp(send_bag->write_buf,"success")==0)
    {
        printf("创建成功!创建的群号为%s!\n",send_bag->recv_id);
    }else{
        printf("创建失败!\n");
    }
    return 0;
}

int dis_gro(int fd)
{
    printf("--------------------------------------------\n");
    printf("              输入解散的群聊的账号:\n");
    scanf("%s",send_bag->read_buf);
    getchar();

    send(fd,send_bag,sizeof(bag),0);
    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli, &mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    if(strcmp(send_bag->write_buf,"success")==0)
    {
        printf("解散成功!\n");
    }else if(strcmp(send_bag->write_buf,"no rights")==0)
    {
        printf("您没有权限!\n");
    }else {
        printf("解散失败!\n");
    }
    return 0;
}

int add_gro(int fd)
{
    printf("--------------------------------------------\n");
    printf("              输入申请加入的群聊的账号:\n");
    scanf("%s",send_bag->read_buf);
    getchar();

    send(fd,send_bag,sizeof(bag),0);
    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli, &mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    if(strcmp(send_bag->write_buf,"sending")==0)
    {
        printf("成功加入群聊!\n");
    }else if(strcmp(send_bag->write_buf,"sended")==0)
    {
        printf("已经进入群聊!\n");
    }else{
        printf("进群失败!\n");
    }
    return 0;
}

int exit_gro(int fd)
{
    printf("--------------------------------------------\n");
    printf("              输入要退出的群聊的账号:\n");
    scanf("%s",send_bag->read_buf);
    getchar();

    send(fd,send_bag,sizeof(bag),0);
    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli, &mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    if(strcmp(send_bag->write_buf,"success")==0)
    {
        printf("退出成功!\n");
    }else if(strcmp(send_bag->write_buf,"no find")==0)
    {
        printf("您不在该群中!\n");
    }else{
        printf("退出出错!\n");
    }
    return 0;
}

int check_gro(int fd)
{
    int i;
    printf("--------------------------------------------\n");
    printf("             输入要查看聊天记录的群聊的账号:\n");
    scanf("%s",send_bag->read_buf);
    getchar();

    send(fd,send_bag,sizeof(bag),0);
    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli, &mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    for(i=0;i<message->number;i++)
    {
        if(message->id[i]==atoi(send_bag->send_id))
        printf("\033[34mtime:%s   id:%d     message;%s\n\033[0m",message->time[i],message->id[i],message->buf[i]);
        else
         printf("\033[32mtime:%s   id:%d     message;%s\n\033[0m",message->time[i],message->id[i],message->buf[i]);
    }
    return 0;
}

int chat_double(int fd)
{
    printf("--------------------------------------------\n");
    printf("              输入聊天的群聊的账号:\n");
    scanf("%s",send_bag->read_buf);
    getchar();

    printf("欢迎进入%s群聊!\n",send_bag->read_buf);
    while(1)
    {
        scanf("%[^\n]",send_bag->write_buf);
        getchar();
        if(strcmp(send_bag->write_buf,"#obey")==0)
        {
            printf("退出%s群聊!\n",send_bag->read_buf);
            break;
        }

        send(fd,send_bag,sizeof(bag),0);

        pthread_mutex_lock(&mutex_cli);
        pthread_cond_wait(&cond_cli, &mutex_cli);
        pthread_mutex_unlock(&mutex_cli);

        if(strcmp(send_bag->buf,"no find")==0)
        {
            printf("你未加入该群聊!\n");
            break;
        }
        if(strcmp(send_bag->buf,"failed")==0)
        {
            printf("进入失败!\n");
            break;
        }
    }

    memset(send_bag->read_buf,0,sizeof(send_bag->read_buf));
    return 0;
}

int deal_gro(int fd)
{
    int choose;

    printf("--------------------------------------------\n");
    printf("                 1--设置管理员:\n");
    printf("                 2--取消管理员\n");
    printf("                 3--群踢人\n");
    printf("                 4--返回\n");
    scanf("%d",&choose);
    getchar();
    switch(choose)
    {
        case 1:
        {
            send_bag->type1=1;
            printf("请输入要设置的管理员账号:\n");
            scanf("%s",send_bag->recv_id);
            getchar();
            printf("请输入设置群聊的账号:\n");
            scanf("%s",send_bag->read_buf);
            getchar();

            send(fd,send_bag,sizeof(bag),0);
            pthread_mutex_lock(&mutex_cli);
            pthread_cond_wait(&cond_cli, &mutex_cli);
            pthread_mutex_unlock(&mutex_cli);

            break;
        }
        case 2:
        {
            send_bag->type1=2;
            printf("请输入要取消管理的管理员账号:\n");
            scanf("%s",send_bag->recv_id);
            getchar();
            printf("请输入设置群聊的账号:\n");
            scanf("%s",send_bag->read_buf);
            getchar();

            send(fd,send_bag,sizeof(bag),0);
            pthread_mutex_lock(&mutex_cli);
            pthread_cond_wait(&cond_cli, &mutex_cli);
            pthread_mutex_unlock(&mutex_cli);
            break;
        }
        case 3:
        {
            send_bag->type1=3;
            printf("请输入被踢出人的账号:\n");
            scanf("%s",send_bag->recv_id);
            getchar();
            printf("请输入设置群聊的账号:\n");
            scanf("%s",send_bag->read_buf);
            getchar();

            send(fd,send_bag,sizeof(bag),0);
            pthread_mutex_lock(&mutex_cli);
            pthread_cond_wait(&cond_cli, &mutex_cli);
            pthread_mutex_unlock(&mutex_cli);
            break;
        }
        case 4:
        {
            printf("返回上一级!\n");
            return 0;
        }
        default:
        {
            printf("输入错误!按任意键返回!");
            getchar();
            return 0;
        }
    }

    if(strcmp(send_bag->write_buf,"success")==0)
    {
        printf("成功修改!\n");
    }else if(strcmp(send_bag->write_buf,"dealed")==0)
    {
        printf("已经是管理员了!\n");
    }else if(strcmp(send_bag->write_buf,"no admin")==0)
    {
        printf("该用户还不是管理员!\n");
    }else if(strcmp(send_bag->write_buf,"no possible")==0)
    {
        printf("该人是群主!\n");
    }else if(strcmp(send_bag->write_buf,"no chmod")==0)
    {
        printf("没有权限!\n");
    }else if(strcmp(send_bag->write_buf,"no find id")==0)
    {
        printf("该人不在该群!\n");
    }else if(strcmp(send_bag->write_buf,"no find gro")==0)
    {
        printf("该群不存在!\n");
    }else{
        printf("修改失败!\n");
    }
    return 0;
}

int send_file(int fd)
{
    struct stat buf;
    int pd;
    int i,j;
    char name[100];
    int len;
    j=0;
    printf("要发送好友的账号:\n");
    scanf("%s",send_bag->recv_id);
    getchar();
    printf("要发送的文件:(绝对路径)\n");
    scanf("%s",send_bag->read_buf);
    getchar();

    if((lstat(send_bag->read_buf,&buf))<0)
    {
        printf("获取文件失败!按任意键返回!\n");
        getchar();
        return 0;
    }

    if((pd=open(send_bag->read_buf,O_RDONLY))<0)
    {
        printf("无法打开文件!按任意键返回!\n");
        getchar();
        return 0;
    }

    sing=0;
    send_bag->cont=0;

    memset(send_bag->buf,0,sizeof(send_bag->buf));
    memset(send_bag->write_buf,0,sizeof(send_bag->write_buf));

    for(i=0;i<=strlen(send_bag->read_buf);i++)
    {
        if(send_bag->read_buf[i]=='/')
        {
            j=0; 
            i++;                       
            memset(name,0,sizeof(name));
        }
        name[j]=send_bag->read_buf[i];
        j++;
    }
    name[i]='\0';
   
    strcpy(send_bag->read_buf,name);
    send_bag->t=buf.st_size;

    while((len=read(pd,send_bag->write_buf,1023))>0)//1023
    {
        send_bag->size=len;
        send(fd,send_bag,sizeof(bag),0);
        memset(send_bag->write_buf,0,sizeof(send_bag->write_buf));
        printf("cont=%d\n",send_bag->cont);
        pthread_mutex_lock(&mutex_cli);
        while(sing==0){
            pthread_cond_wait(&cond_cli, &mutex_cli);
        }
        pthread_mutex_unlock(&mutex_cli);
        send_bag->cont++;
        sing=0;
    }
    close(pd);

    sing=0;
    strcpy(send_bag->buf,"ok");
    send(fd,send_bag,sizeof(bag),0);

    pthread_mutex_lock(&mutex_cli);
    while(sing==0){
        pthread_cond_wait(&cond_cli, &mutex_cli);
    }
    pthread_mutex_unlock(&mutex_cli);
    sing=0;
    
    if(strcmp(send_bag->buf,"success")==0)
    {
        printf("传送完成!\n");
    }else if(strcmp(send_bag->buf,"no online")==0)
    {
        printf("该账号不在线!\n");
    }else if(strcmp(send_bag->buf,"no find")==0)
    {
        printf("该账号不存在!\n");
    }else{
        printf("%s",send_bag->buf);
        printf("发送错误!\n");
    }
   
    return 0;
}

int recv_file(int fd)
{
    int i;
    int choice;
    send_bag->cont=0;

    if(box->file_number==0)
    {
        printf("暂无文件需要接收!按任意键退出!\n");
        getchar();
        return 0;
    }else{
        for(i=0;i<box->file_number;i++)
        {
            printf("                 %d给你发送了一个文件%s,是否接收!\n",box->file_id[i],box->file_name[i]);
            printf("                 1--同意\n");
            printf("                 2--拒绝\n");
            printf("--------------------------------------------\n");
            printf("                 请选择:\n");
            scanf("%d",&choice);
            getchar();
            if(choice==1)
            {
                    memset(send_bag->buf,0,sizeof(send_bag->buf));
                    send(fd,send_bag,sizeof(bag),0);

                    pthread_mutex_lock(&mutex_cli);
                    while(sing==0){
                        pthread_cond_wait(&cond_cli, &mutex_cli);
                    }
                    pthread_mutex_unlock(&mutex_cli);
                    sing=0;
                   
                    printf("接收完成!\n");
            }else if(choice ==2)
            {
                printf("已拒绝接收!\n");
            }else{
                printf("输入错误!\n");
            }
        }
       box->file_number=0;
    }
    return 0;      
}

int check_gro_fri(int fd)
{
    int i=0;

    printf("要查看的群账号:\n");
    scanf("%s",send_bag->read_buf);
    getchar();
    
    send(fd,send_bag,sizeof(bag),0);

    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli,&mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    if(strcmp(send_bag->write_buf,"success")==0)
    {
        printf("群好友列表:\n");
        for(i=0;i<list->fri_number;i++)
        {
            if(list->fri_line[i]==2)
            {
                printf("群主:     id:%d     name:%s\n",list->fri_id[i],list->fri_name[i]);
            }else if(list->fri_line[i]){
                printf("管理员:   id:%d     name:%s\n",list->fri_id[i],list->fri_name[i]);
            }else{
                printf("普通成员: id:%d     name:%s\n",list->fri_id[i],list->fri_name[i]);
            }
        }
    }else{
        printf("查询失败!\n");
    }   
    return 0;
}

int check_info(int fd)
{
    send(fd,send_bag,sizeof(bag),0);

    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli,&mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    if(strcmp(send_bag->write_buf,"success")==0)
    {
        printf("id:%s         name:%s\n",send_bag->send_id,send_bag->send_name);
    }else{
        printf("显示错误!\n");
    }
    return 0;
}

int check_group(int fd)
{
    int i;
    send(fd,send_bag,sizeof(bag),0);

    pthread_mutex_lock(&mutex_cli);
    pthread_cond_wait(&cond_cli,&mutex_cli);
    pthread_mutex_unlock(&mutex_cli);

    if(strcmp(send_bag->write_buf,"success")==0)
    {
        for(i=0;i<lis->number;i++)
        {
            if(lis->chmod[i]==2)
            {
                printf("你拥有的群:   id:%d\n",lis->id[i]);
            }else if(lis->chmod[i]==1)
            {
                printf("你管理的群:   id:%d\n",lis->id[i]);
            }else if(lis->chmod[i]==0)
            {
                printf("你加入的群:   id:%d\n",lis->id[i]);
            }
        }
    }else{
        printf("暂未加入群!\n");
    }
    return 0;
}

void *thread_send(void *arg)
{
    int fd=*(int *)arg;
    int ret;
    int t;
    int choose;
    send_bag=(bag *)malloc(sizeof(bag));
    send_bag->send_fd=fd;
    while(1){
        menu();
        scanf("%d",&choose);
        getchar();
        switch (choose){
            case 1://登陆
            {
                send_bag->type=1;
                login(fd);
                break;
            }
            case 2://注册
            {
                send_bag->type=2;
                resign(fd);
                break;
            }
            case 0://退出
            {
                send_bag->type=0;
                ret=send(fd,send_bag,sizeof(bag),0);
                if(ret<0){
                    perror("send failed");
                    exit(1);
                }
                printf("即将退出!\n");
                pthread_exit(0);
            }
            default:
            {
                printf("输入错误!重新输入!\n");
                break;
            }
        }

        if(choose<0||choose>2)
        {
            continue;
        }else if(choose==1){               
            if(strcmp(send_bag->write_buf,"login successfully")==0)
            {
                printf("%s欢迎登陆~\n",send_bag->send_name);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                break;
            }else if(strcmp(send_bag->write_buf,"login failed")==0)
            {   
                printf("登陆失败!请重新登陆!\n");
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                continue;
            }else{
                printf("对比出错!请返回!\n");
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                continue;
            }
        }else if(choose==2){
            printf("按任意键继续!\n");
            getchar();
            system("clear");
            continue;
        }
    }
    
    while(1)
    {
        menu1();
        scanf("%d",&choose);
        getchar();
        switch(choose){
            case 1://私聊
            {
                send_bag->type=3;
                chat_single(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                
                break;
            }
            case 2://加好友
            {
                send_bag->type=4;
                add_fri(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
    
                break;
            }
            case 3://删好友
            {
                send_bag->type=5;
                del_fri(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                
                break;
            }
            case 4://显示好友列表
            {
                send_bag->type=6;
                display_fri(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                
                break;
            }
            case 5://查看聊天记录
            {
                send_bag->type=7;
                check_fri(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
            
                break;
            }
            case 6://拉黑好友
            {
                send_bag->type=8;
                black_fri(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
        
                break;
            }
            case 7://移出好友
            {
                send_bag->type=9;
                white_fri(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
        
                break;
            }
            case 8://开始群聊
            {
                send_bag->type=10;
                chat_double(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                break;
            }
            case 9://创建群聊
            {
                send_bag->type=11;
                create_gro(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                
                break;
            }
            case 10://解散群聊
            {
                send_bag->type=12;
                dis_gro(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                
                break;
            }
            case 11://申请加群
            {
                send_bag->type=13;
                add_gro(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
            
                break;
            }
            case 12://退出群聊
            {
                send_bag->type=14;
                exit_gro(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                break;
            }
            case 13://查看群聊天记录
            {
                send_bag->type=15;
                check_gro(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
            
                break;
            }
            case 14://管理群事务
            {
                send_bag->type=16;
                deal_gro(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                break;
            } 
            case 0://退出
            {
                send_bag->type=0;
                send(fd,send_bag,sizeof(bag),0);
                pthread_exit(0);
                return 0;
            }
            case 15://修改信息
            {
                send_bag->type=17;
                xiugai(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
    
                break;
            }
            case 16://处理消息
            {
                send_bag->type=18;
                deal(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                
                break;
            }
            case 17://发送文件
            {
                send_bag->type=21;
                send_file(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
        
                break;
            }   
            case 18://接收文件
            {
                send_bag->type=23;
                recv_file(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                
                break;
            }
            case 19://查看群好友列表
            {
                send_bag->type=24;
                check_gro_fri(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                break;
            }
            case 20://查看个人信息
            {
                send_bag->type=25;
                check_info(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                break;
            }
            case 21://查看群列表
            {
                send_bag->type=26;
                check_group(fd);
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                break;
            }
            default:
            {
                printf("输入错误!重新输入!\n");
                printf("按任意键继续!\n");
                getchar();
                system("clear");
                continue;
            }
        }
    }
}

void *recv_box(void *arg)
{
    int fd=*(int *)arg;
    recv(fd,box,sizeof(BOX),MSG_WAITALL);
    pthread_exit(0);
}

void *recv_fri(void *arg)
{
    int fd=*(int *)arg;
    recv(fd,list,sizeof(fri),MSG_WAITALL);
    pthread_exit(0);
}

void *recv_frimes(void *arg)
{
    int fd=*(int *)arg;
    if(strcmp(recv_bag->send_id,send_bag->recv_id)==0)
    {
        printf("\033[34mid:%s     %s\n\033[0m",recv_bag->send_id,recv_bag->read_buf);
    }else{
        printf("来了一条消息!\n");
        box->send_id[box->talk_number]=atoi(recv_bag->send_id);
        strcpy(box->read_buf[box->talk_number],recv_bag->read_buf);
        box->talk_number++;
    }
    pthread_exit(0);
}

void *display_frimes(void *arg)
{
    int fd=*(int *)arg;
    recv(fd,mes,sizeof(fri_mes),MSG_WAITALL);
    pthread_exit(0);
}

void *recv_gromes(void *arg)
{
    int fd=*(int *)arg;
    if(strcmp(recv_bag->write_buf,send_bag->write_buf)==0)
    {
        ;
    }else if(strcmp(recv_bag->read_buf,send_bag->read_buf)==0)
    {
        printf("\033[34mid:%s      %s\n\033[0m",recv_bag->send_id,recv_bag->write_buf);
    }else{
        printf("来了一条群消息!\n");
        box->send_id1[box->number]=atoi(recv_bag->send_id);
        box->group_id[box->number]=atoi(recv_bag->read_buf);
        strcpy(box->message[box->number],recv_bag->write_buf);
        box->number++;
    }
    pthread_exit(0);
}

void *display_gromes(void *arg)
{
    int fd=*(int *)arg;
    recv(fd,message,sizeof(gro_mes),MSG_WAITALL);
    pthread_exit(0);
}

void *recv_group(void *arg)
{
    int fd=*(int *)arg;
    recv(fd,lis,sizeof(group),MSG_WAITALL);
    pthread_exit(0);
}

void *thread_recv(void *arg)
{
    int ret;
    int fd=*(int *)arg;

    recv_bag=(bag *)malloc(sizeof(bag));
    box=(BOX *)malloc(sizeof(BOX));
    list=(fri *)malloc(sizeof(fri));
    mes=(fri_mes *)malloc(sizeof(fri_mes));
    message=(gro_mes *)malloc(sizeof(gro_mes));
    lis=(group *)malloc(sizeof(group));

    while(1)
    {
        memset(recv_bag,0,sizeof(bag));
        ret=recv(fd,recv_bag,sizeof(bag),MSG_WAITALL);
    
        if(ret<0)
        {
            perror("recv failed");
            exit(1);
        }
        
        switch(recv_bag->type)
        {
            case 0://退出
            {
                printf("退出成功!\n");
                pthread_exit(0);
                return 0;
            }
            case 1://登陆
            {
                strcpy(send_bag->send_name, recv_bag->send_name);
                memset(send_bag->write_buf, 0, sizeof(send_bag->write_buf));
                strcpy(send_bag->write_buf, recv_bag->write_buf);
                send_bag->send_fd = recv_bag->recv_fd;

                if(strcmp(send_bag->write_buf,"login successfully")==0)
                {
                pthread_create(&tid,NULL,recv_box,(void *)&fd);
                pthread_join(tid,NULL);
                printf("离线时好友信息数:%d\n",box->talk_number);
                printf("离线时好友请求数:%d\n",box->friend_number);
                printf("离线时群聊信息数:%d\n",box->number);
                }
                pthread_mutex_lock(&mutex_cli);
                sing=1;
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                
                break;
            }
            case 2://注册
            {
                strcpy(send_bag->send_id,recv_bag->send_id);
                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 3://私聊
            {
                strcpy(send_bag->write_buf,recv_bag->write_buf);
                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 19://在线时私聊收消息
            {
                pthread_create(&tid,NULL,recv_frimes,(void *)&fd);
                pthread_join(tid,NULL);
                break;
            }
            case 4://加好友
            {
                strcpy(send_bag->write_buf,recv_bag->write_buf);
                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 5://删好友
            {
                strcpy(send_bag->write_buf,recv_bag->write_buf);
                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 6://显示好友
            {
                memset(send_bag->write_buf, 0, sizeof(send_bag->write_buf));
                strcpy(send_bag->write_buf, recv_bag->write_buf);
                memset(list,0,sizeof(fri));

                pthread_create(&tid,NULL,recv_fri,(void *)&fd);
                pthread_join(tid,NULL);
                
                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 7://查看聊天记录
            {
                pthread_create(&tid,NULL,display_frimes,(void *)&fd);
                pthread_join(tid,NULL);

                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 8://拉黑好友
            {
                strcpy(send_bag->write_buf,recv_bag->write_buf);
                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 9://移出好友
            {
                strcpy(send_bag->write_buf,recv_bag->write_buf);
                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 10://开始群聊
            {
                strcpy(send_bag->buf,recv_bag->buf);
                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 20://收群聊消息
            {
                pthread_create(&tid,NULL,recv_gromes,(void *)&fd);
                pthread_join(tid,NULL);
                break;
            }
            case 11://创建群聊
            {
                memset(send_bag->write_buf,0,sizeof(send_bag->write_buf));
                strcpy(send_bag->write_buf,recv_bag->write_buf);
                strcpy(send_bag->recv_id,recv_bag->recv_id);
                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 12://解散群聊
            {
                memset(send_bag->write_buf,0,sizeof(send_bag->write_buf));
                strcpy(send_bag->write_buf,recv_bag->write_buf);
                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 13://加入群聊
            {
                memset(send_bag->write_buf,0,sizeof(send_bag->write_buf));
                strcpy(send_bag->write_buf,recv_bag->write_buf);

                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 14://退出群聊
            {
                memset(send_bag->write_buf,0,sizeof(send_bag->write_buf));
                strcpy(send_bag->write_buf,recv_bag->write_buf);

                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 15://查看群聊天记录
            {
                pthread_create(&tid,NULL,display_gromes,(void *)&fd);
                pthread_join(tid,NULL);

                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 16://管理群事务
            {
                memset(send_bag->write_buf,0,sizeof(send_bag->write_buf));
                strcpy(send_bag->write_buf,recv_bag->write_buf);

                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 17://修改
            {
                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 18://处理消息
            {
                if(recv_bag->type1==1)
                {
                    pthread_mutex_lock(&mutex_cli);
                    box->plz_id[box->friend_number]=atoi(recv_bag->send_id);
                    box->friend_number++;
                    printf("有一条好友申请!\n");
                    pthread_mutex_unlock(&mutex_cli);
                }
                break;
            }
            case 21://传送文件
            {
                strcpy(send_bag->buf,recv_bag->buf);
                 
                pthread_mutex_lock(&mutex_cli);
                sing=1;
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 22://收到文件
            {
                strcpy(send_bag->recv_id,recv_bag->send_id);
                strcpy(send_bag->read_buf,recv_bag->read_buf);
                send_bag->size=recv_bag->size;
                send_bag->t=recv_bag->t;

                printf("%s给你发送了一个文件%s,快去接收吧!\n",send_bag->recv_id,send_bag->read_buf);
                box->file_id[box->file_number]=atoi(send_bag->recv_id);
                strcpy(box->file_name[box->file_number],send_bag->read_buf);
                box->file_number++;

                pthread_mutex_lock(&mutex_cli);
                sing=1;
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 23://接收文件
            {
                char file[100];

                memset(send_bag->buf,0,sizeof(send_bag->buf));
                memset(send_bag->write_buf,0,sizeof(send_bag->write_buf));

                strcpy(file,send_bag->read_buf);
                strcpy(send_bag->write_buf,recv_bag->write_buf);
                strcpy(send_bag->buf,recv_bag->buf);

                send_bag->size=recv_bag->size;

                int pd=open(file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IXUSR);
                write(pd,send_bag->write_buf,send_bag->size);
                close(pd);

                pthread_mutex_lock(&mutex_cli);
                sing=1;
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 24://查看群好友列表
            {
                memset(send_bag->write_buf, 0, sizeof(send_bag->write_buf));
                strcpy(send_bag->write_buf, recv_bag->write_buf);
                memset(list,0,sizeof(fri));

                pthread_create(&tid,NULL,recv_fri,(void *)&fd);
                pthread_join(tid,NULL);
                
                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 25://查看个人信息
            {
                memset(send_bag->write_buf,0,sizeof(send_bag->write_buf));
                memset(send_bag->send_name,0,sizeof(send_bag->send_name));
                strcpy(send_bag->send_name,recv_bag->send_name);
                strcpy(send_bag->write_buf,recv_bag->write_buf);

                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
            case 26://查看群列表
            {
                memset(send_bag->write_buf, 0, sizeof(send_bag->write_buf));
                strcpy(send_bag->write_buf, recv_bag->write_buf);
                memset(lis,0,sizeof(group));

                pthread_create(&tid,NULL,recv_group,(void *)&fd);
                pthread_join(tid,NULL);
                
                pthread_mutex_lock(&mutex_cli);
                pthread_cond_signal(&cond_cli);
                pthread_mutex_unlock(&mutex_cli);
                break;
            }
        }
    }
}

int main()
{
    struct sockaddr_in client_addr;
    int sockfd=socket_init(client_addr);
    if(sockfd<0) return 0;
    pthread_t tid1,tid2;
    
    sing=0;
    pthread_mutex_init(&mutex_cli,NULL);
    pthread_cond_init(&cond_cli,NULL);

    pthread_create(&tid1,NULL,thread_send,(void *)&sockfd);
    pthread_create(&tid2,NULL,thread_recv,(void *)&sockfd);
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    return 0;
}

编译命令

$ gcc client.c -lpthread -o client
$./client

如有问题,希望可以指出。


版权声明:本文为m0_50331127原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。