菜鸟学习历程【24】select 实现 聊天室( Server / Client 模式)

聊天室项目实战

项目要求:

  1. 采用client/server架构
  2. client A登录聊天服务器前,需要注册自己的ID和密码
  3. 注册成功后,client A就可以通过自己的ID和密码登录聊天服务器
  4. 多个 Client X 可以同时登陆聊天服务器之后,与其他用户进行通讯聊天
  5. Client A 成功登陆后可以查看当前聊天室内其他在线用户 Client x
  6. Client A 可以选择发消息给某个特定的 Client X,即” 悄悄话” 功能
  7. Client A 可以选择发消息全部的在线用户,即” 群发消息” 功能
  8. Client A 在退出时需要保存聊天记录
  9. Server 可以内建一个特殊权限的账号 admin,用于管理聊天室
  10. Admin 可以将某个 Client X “提出聊天室”
  11. Admin 可以将某个 Client X ” 设为只能旁听,不能发言”
  12. Client 端发言增加表情符号,可以设置某些自定义的特殊组合来表达感情.如输入:),则会自动发送” XXX 向大家做了个笑脸”

项目分析:
1.需要创建一个数据库用来保存用户的账号,密码,昵称,手机号码,禁言标志位,会员标志位等信息,手机号码用来忘记密码功能中找回密码使用,而昵称是为了聊天时寻找对象使用;
2.创建一个在线用户的链表,保存在线用户的信息。
3.创建一个结构体用来保存发送的信息,包括通信协议,昵称,端口号,聊天内容等等……
4.使用select来写代码时,服务器并不需要创建线程,服务器会对所有的文件描述符进行检测,发现有状况发生时,立即响应处理。
5.在进行聊天时,要将所有的信息保存在文件中,作为聊天记录,在收到与发送的位置对文件进行读写操作即可。
本项目实现了,客户端之间信息的连续的发送

chatroom.h

#ifndef _CHATROOM_H_
#define _CHATROOM_H_

/*************库函数****************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sqlite3.h>
#include <signal.h>

/*************宏定义*******************/

#define   PORT           8888
#define   SUCCESS        10001
#define   FAILURE        10002

#define   REGISTER          1000          
#define   LOGIN             2000
#define   QUIT              3000
#define   EXIST             4000
#define   NOTEXIST          5000
#define   ACCOUNTEXIT       6000
#define   ACCOUNTNOTEXIT    7000
#define   REGFAILURE        8000
#define   REGSUCCESS        9000
#define   ALLOWLOGIN        10000
#define   REFUSELOGIN       11000
#define   CHATREQUST        12000
#define   ALLOWCHAT         13000
#define   ACCEPTCHAT        13100
#define   REFUSECHAT        14000
#define   INSERT            15000
#define   CHANGEPASS        16000
#define   CHANGESUCCESS     17000
#define   CHANGEFAILURE     18000
#define   CONFIRMACCOUNT    19000
#define   CHECKONLINE       20000
#define   RETONLINE         21000
#define   CHECKDONE         21100
#define   PRECHATTING       22000
#define   CHATTING          23000
#define   CHECKHISTORY      24000
#define   ALLOWCHECK        24001
#define   CHECKHISDONE      25000
#define   SENDGROUP         26000 
#define   RECVGROUP         27000
#define   ACCEPTGROUNP      27001
#define   EMOJONLINECHICK   28000
#define   EMOJNOTONLINE     29000
#define   EMOJONLINE        30000
#define   SENDEMOJ          31000
#define   PRERECVEMOJ       32000
#define   RECVEMOJ          33000
#define   OFFLINE           34000
#define   FORRBIDDEN        35000
#define   FUCKOUT           36000
#define   DISMISS           37000
#define   MEMBER            38000
#define   NOTMEMBER         39000
#define   NOTDISMISS        40000
#define   NOTFUCK           41000
#define   NOTONLINE         42000
#define   FILESENDREQUST    43000
#define   REFUSESEND        44000
#define   ACCEPTSEND        45000
#define   FILESEND          46000
#define   RECVFILE          46001
#define   SENDDONE          47000
#define   SIGNAL            48000
#define   PEOPLECHAT        49000

/*************结构体声明****************/

struct usernode
{
    char name[10];
    char TarName[10];
    char password[20];
    char account[10];
    char telephone[20];
    char onlinefriend[20][20];
    char ChatBuf[20];
    char Forbname[10];
    char FileBuf[100];
    char FilePath[40];
    int cmd;
    int OnlineFlag;
    int Tofd;
    int TargFd;
    int num;
};

typedef struct usernode Node;

struct onlineInfo
{
    char name[10];
    char account[10];
    int Flag;
    int SelfFd;
    int ForbFlag;
    struct onlineInfo *next;
};

typedef struct onlineInfo OnlineInfo;
typedef OnlineInfo *Online;

struct info
{
    char buf[30];
    int Tofd;
};

struct chathistory
{
    char name[10];
    char cont[10];
    int year;
    int month;
    int day;
    int hour;
    int min;
    int sec;
};

typedef struct chathistory ChatHist;

/*************信息链表函数声明****************/

int OnlineInit(Online *Info);
int InsertLink(Online Info, int fd,  int flag, char *name,  char *account);
int OnlineJudge(Online l, char *Targname);
char *GetLinkName(Online l, int fd, char *n);

/*************界面函数声明****************/

void PrintTime();
void Loginshow(int sockfd);
void Registershow(int sockfd);
int loadshow(int sockfd);
void LogSuccshow(int sockfd);
int JudgeLog(char *Myacc, char *Mypass);

/*************数据库函数声明****************/

int InsertDb(char *n, char *a, char *p, int fd, char *t);
int Select(void *para, int columnCount, char **columnValue, char **columnName);
int JudgeInfo1(char *acc, char *pass, int tarfd);
int ConfirmInfo(void *para, int columnCount, char **columnValue, char **columnName);
int JudgeInfo2(char *acc, char *tele);
int ResetPass(int fd, char *acc);
int ChangePass(char *account, char *password);
char *GetName(char *acc, char *pass, char *n);
int Getname(void *para, int columnCount, char **columnValue, char **columnName);
int AddMember(char *acc);
int JudgeMember(char *acc);
int Judgemember(void *para, int columnCount, char **columnValue, char **columnName);

/*************聊天界面功能函数声明****************/

int PriChat(int sockfd);
int SendGroup(int sockfd);
int CheckOnline(int sockfd);
int SearChatHis(int sockfd);
void ForbidMod();
int PrintOnlineFriend(Online l, int fd);
int ChattingShow(int sockfd, int TargFd, char *name, char *Tarame);
int SendEmoj(int sockfd);
void Fuck(int sockfd);
void HiddenShow();
void Offline(int sockfd);
void Dismiss(int sockfd);
void member(int sockfd);
void FuckOffline();
int RecvChat(int sockfd);
void Transform(int sockfd);
void Exit(int sockfd);

/*************聊天记录函数声明****************/

int AddChatHist(char *Targname, char *chat);
void ShowChatHist();

/*************信号处理函数声明****************/

void hand(int tmp);


#endif

服务器部分:

服务器函数实现

#include "chatroom.h"


/*************数据库函数****************/


int InsertDb(char *a, char *n, char *p, int fd, char *t)
{
    int ret;
    char sql[200] = {0};    
    extern sqlite3 *ppdb;
    char Tmp1[3] = "no";

    sprintf(sql, "insert into chatroom (account, name, password, Tofd, telephone, member, forbid) values('%s', '%s', '%s', '%d', '%s', '%s', '%s');", a, n, p, fd, t, Tmp1, Tmp1);
    ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_exec");
        return FAILURE;
    }

    return SUCCESS;
}

char *GetName(char *acc, char *pass, char *n)
{
    int ret;
    extern sqlite3 *ppdb;
    char sql[100] = {0};
    extern char Tmpname[10];

    memset(&Tmpname, 0, sizeof(Tmpname));
    Node Tmp = {0};
    strcpy(Tmp.account, acc);
    strcpy(Tmp.password, pass);

    sprintf(sql, "select *from chatroom;");
    ret = sqlite3_exec(ppdb, sql, Getname, (void *)&Tmp, NULL);
    if(SQLITE_OK != ret)   
    {
        perror("sqlite3_exec");
        exit(1);
    }
    strcpy(n, Tmpname);
    return n;
}

int Getname(void *para, int columnCount, char **columnValue, char **columnName)
{
    int ret;
    char buf[10] = {0};
    extern sqlite3 *ppdb;
    Node Tmp = *((Node *)para);
    extern char Tmpname[10];    

    if(!strcmp(columnValue[0], Tmp.account)  &&  !strcmp(columnValue[2], Tmp.password))
    {
        strcpy(Tmpname, columnValue[1]);
    }
    return 0;
}

int AddMember(char *acc)
{
    int ret;
    char sql[200] = {0};    
    extern sqlite3 *ppdb;
    char Tmp[4] = "yes";

    sprintf(sql, "update chatroom set member = '%s' where account = '%s';", Tmp, acc);
    ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_exec");
        return FAILURE;
    }

    return SUCCESS; 
}

int JudgeMember(char *acc)
{
    int ret;
    char sql[200] = {0};    
    extern sqlite3 *ppdb;
    extern int MEMBERFLAG;
    sprintf(sql, "select * from chatroom;");
    ret = sqlite3_exec(ppdb, sql, Judgemember, (void *)acc, NULL);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_exec");
        return FAILURE;
    }

    if(MEMBERFLAG == 1) 
    {
        MEMBERFLAG = 0;
        return SUCCESS;
    }
    else 
    {
        return FAILURE;
    }

}

int Judgemember(void *para, int columnCount, char **columnValue, char **columnName)
{
    extern int MEMBERFLAG;

    if(!strcmp(columnValue[0], (char *)para) && !strcmp(columnValue[5], "yes"))
    {
        MEMBERFLAG = 1;
    }
    return 0;
}

int JudgeInfo1(char *acc, char *pass, int tarfd)
{
    int ret;
    char sql[200] = {0};
    Node Tmp = {0};
    extern sqlite3 *ppdb;
    extern int FLAG;
    char name[10];

    FLAG = 0;
    GetName(acc, pass, name);

    Tmp.Tofd = tarfd;  //客户端的fd
    strcpy(Tmp.account, acc);
    strcpy(Tmp.password, pass);
    strcpy(Tmp.name, name);

    sprintf(sql, "select * from chatroom;");

    ret = sqlite3_exec(ppdb, sql, ConfirmInfo, (void *)&Tmp, NULL);
    if(SQLITE_OK != ret)   
    {
        perror("sqlite3_exec");
        exit(1);
    }

    if(FLAG == 0)
    {
        Tmp.cmd = REFUSELOGIN;
        ret = send(Tmp.Tofd, &Tmp, sizeof(Tmp), 0);
        if(-1 == ret)
        {
            perror("ConfirmInfo send");
            return FAILURE;
        }
    }
    else if(FLAG == 1)
    {
        Tmp.cmd = ALLOWLOGIN;
        ret = send(Tmp.Tofd, &Tmp, sizeof(Tmp), 0);
        if(-1 == ret)
        {
            perror("ConfirmInfo send");
            return FAILURE;
        }

    }

}

int ConfirmInfo(void *para, int columnCount, char **columnValue, char **columnName)
{
    int ret;
    char buf[10] = {0};
    extern sqlite3 *ppdb;
    extern int FLAG;
    Node Tmp = *((Node *)para);

    strcpy(buf, columnValue[0]);

    if(!strcmp(columnValue[0], Tmp.account)  &&  !strcmp(columnValue[2], Tmp.password))
    {
        FLAG = 1;
    }

    return 0;
}

int JudgeInfo2(char *acc, char *tele)
{
    int ret;
    char sql[200] = {0};
    char *errmsg = NULL;
    char **dbresult;
    int row, column;
    extern sqlite3 *ppdb;

    printf("444444444\n");
    memset(sql, 0, sizeof(sql));

    sprintf(sql, "select account, telephone from chatroom where account = '%s' and telephone = '%s';", acc, tele);
    ret = sqlite3_get_table(ppdb, sql, &dbresult, &row, &column, &errmsg);
    if(SQLITE_OK == ret)
    {
        if(1 == row)    
        {
            sqlite3_free_table(dbresult);
            return SUCCESS;
        }
    }

    sqlite3_free_table(dbresult);
    return FAILURE;;
}

int ChangePass(char *account, char *password)
{
    int ret;
    char sql[200] = {0};
    extern sqlite3 *ppdb;


    sprintf(sql, "update chatroom set password = '%s' where account = '%s';", password, account);
    ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
    if(SQLITE_OK != ret)
    {
        perror("ChangePass sqlite3_exec");
        return FAILURE;
    }
    return SUCCESS;
}

int JudgeLog(char *Myacc, char *Mypass)
{
    int ret, i;
    char sql[100] = {0};
    extern sqlite3 *ppdb;


    sprintf(sql, "select account from chatroom where password = '%s';", Mypass);

    ret = sqlite3_exec(ppdb, sql, Select, Myacc, NULL);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_execD");
        exit(1);
    }

}

int Select(void *para, int columnCount, char **columnValue, char **columnName)
{
    int j;
    for(j = 0; j < columnCount; j++)
    {
        if(!strcmp(para, columnValue[j]))
        {
            EXISTFLAG = EXIST;
            return SUCCESS;
        }
    }
    EXISTFLAG = NOTEXIST;
    return FAILURE;
}

/*************信息链表初始化****************/

int OnlineInit(Online *Info)
{
    (*Info) = (Online)malloc(sizeof(OnlineInfo));
    if(NULL == (*Info))
    {
        return FAILURE;
    }
    (*Info)->next = NULL;
    return SUCCESS;
}

int InsertLink(Online Info, int fd,  int flag, char *name,  char *account)
{
    Online p = Info->next;

    Online n = (Online)malloc(sizeof(OnlineInfo));
    if(NULL == n)
    {
        return FAILURE;
    }

    while(p)
    {
        if(strcmp(p->account, account) == 0)
        {
            p->SelfFd = fd;
            return SUCCESS;
        }
        else
        {
            p = p->next;
        }

    }

    Online q = Info;
    strcpy(n->name, name);
    printf("%s\n", name);
    printf("%s\n", n->name);
    strcpy(n->account, account);
    n->Flag = flag;
    n->SelfFd = fd;

    n->next = q->next;
    q->next = n;
}

int OnlineJudge(Online l, char *Targname)
{
    Online p = l->next;

    while(p)
    {
        if(!(strcmp(p->name, Targname)) && p->Flag == 1)
        {
            return p->SelfFd;   //聊天对象的fd
        }
        else
        {
            p = p->next;
        }

        if(NULL == p)
        {
            return REFUSECHAT;
        }
    }
}

int PrintOnlineFriend(Online l, int fd)
{
    int i = 0, ret;
    Online p = l->next;
    Node Tmp = {0};
    Tmp.cmd = RETONLINE;
    Tmp.num = 0;

    while(p)
    {
        if(p->Flag == 1)
        {

            strcpy(Tmp.onlinefriend[i], p->name);
            i++;
            Tmp.num = i;            
        }
        p = p->next;
    }

    ret = send(fd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("PrintOnlineFriend send");
        exit(1);
    }       
    return SUCCESS;
}

char *GetLinkName(Online l, int fd, char *n)
{
    Online p = l->next;

    while(p)
    {
        if(p->SelfFd == fd)
        {
            strcpy(n, p->name);
            return n;
        }
        else
        {
            p = p->next;
        }
    }
}

服务器部分

#include "chatroom1.h"

sqlite3 *ppdb;
Node Send = {0};
Node Recv = {0};
int FLAG = 0;
char Tmpname[10] = {0};
int TMPFD = 0;
char TMPCHATBUF[30] = {0};
int MEMBERFLAG = 0;
int PeopleChatFd[10] = {0};

int main()
{
    int sockfd, fd[10] = {0}, i = 0, j, length, ret, opt = 1, MaxFd;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    fd_set ReadFd, TmpFd;
    char sql[200] = {0};
    Node RecvBuf = {0};
    Node Tmp = {0};
    Online LinkNode;

    ret = OnlineInit(&LinkNode);
    if(FAILURE == ret)
    {
        printf("Init FAILURE\n");
        return FAILURE;
    }

    ret = sqlite3_open("chatroom.db", &ppdb);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_open");
        exit(1);
    }

    sprintf(sql, "create table if not exists chatroom(account text primary key, name text, password text, Tofd integer, telephone text, member text, forbid text);");
    ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
    if(SQLITE_OK != ret)
    {
        perror("sqlite3_exec1A");
        exit(1);
    }

    sockfd = socket(PF_INET, SOCK_STREAM, 0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }

    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = PF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if(-1 == ret)
    {
        perror("bind");
        exit(1);
    }

    ret = listen(sockfd, 100);
    if(-1 == ret)
    {
        perror("listen");
        exit(1);
    }

    printf("Listening...\n");

    FD_ZERO(&ReadFd);
    FD_ZERO(&TmpFd);
    FD_SET(sockfd, &ReadFd);
    MaxFd = sockfd + 1;

    while(1)
    {
        TmpFd = ReadFd;
        ret = select(MaxFd, &TmpFd, NULL, NULL, NULL);
        if(-1 == ret)
        {
            perror("select");
            exit(1);
        }

        if(FD_ISSET(sockfd, &TmpFd))
        {
            length = sizeof(client_addr);
            fd[i] = accept(sockfd, (struct sockaddr *)&client_addr, &length);
            if(-1 == fd[i])
            {
                perror("accept");
                exit(1);
            }

            printf("Accept %d, Port %d\n", fd[i], client_addr.sin_port);

            FD_SET(fd[i], &ReadFd);
            MaxFd = fd[i] + 1;
            i++;
        }
        else
        {
            for(j = 0; j < i; j++)
            {
                if(FD_ISSET(fd[j], &TmpFd))
                {
                    memset(&RecvBuf, 0, sizeof(RecvBuf));

                    ret = recv(fd[j], &RecvBuf, sizeof(RecvBuf), 0);
                    if(-1 == ret)
                    {
                        perror("recv");
                        exit(1);
                    }

/************************************注册*************************************/

                    if(REGISTER == RecvBuf.cmd)
                    {
                        RecvBuf.Tofd = fd[j];

                        ret = InsertDb(RecvBuf.account, RecvBuf.name, RecvBuf.password, RecvBuf.Tofd, RecvBuf.telephone);
                        if(FAILURE == ret)
                        {
                            RecvBuf.cmd = REGFAILURE;
                            ret  = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                            if(-1 == ret)
                            {
                                perror("Regsend");
                                exit(1);
                            }

                        }
                        else if(SUCCESS == ret)
                        {
                            RecvBuf.cmd = REGSUCCESS;
                            ret  = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                            if(-1 == ret)
                            {
                                perror("Regsend");
                                exit(1);
                            }
                        }
                        RecvBuf.cmd = 0;
                    }

/************************************登录*************************************/

                    if(LOGIN == RecvBuf.cmd)
                    {   
                        RecvBuf.Tofd = fd[j];
                        JudgeInfo1(RecvBuf.account, RecvBuf.password, RecvBuf.Tofd);
                        RecvBuf.cmd = 0;
                    }
                    if(INSERT == RecvBuf.cmd)
                    {
                        RecvBuf.OnlineFlag = 1;
                        RecvBuf.Tofd = fd[j];

                            //插入链表时,将自己的端口号一起插入,以便进行聊天
                        ret = InsertLink(LinkNode, RecvBuf.Tofd, RecvBuf.OnlineFlag, RecvBuf.name, RecvBuf.account);
                        if(FAILURE == ret)
                        {
                            printf("Insert Failure");
                            exit(1);
                        }
                        RecvBuf.cmd = 0;

                    }                   

/**********************************验证账号***********************************/

                    if(CONFIRMACCOUNT == RecvBuf.cmd)
                    {
                        printf("11111111\n");
                        RecvBuf.Tofd = fd[j];

                        ret = JudgeInfo2(RecvBuf.account, RecvBuf.telephone);
                        if(SUCCESS == ret)
                        {
                            RecvBuf.cmd = EXIST;

                            ret = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                            if(-1 == ret)
                            {
                                perror("CONFIRMACCOUNT send");
                                exit(1);
                            }
                        }
                        else if(NOTEXIST == ret)
                        {
                            RecvBuf.cmd = NOTEXIST;

                            ret = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                            if(-1 == ret)
                            {
                                perror("CONFIRMACCOUNT send");
                                exit(1);
                            }
                        }
                        RecvBuf.cmd = 0;
                    }

/**********************************修改密码***********************************/

                    if(CHANGEPASS == RecvBuf.cmd)
                    {
                        RecvBuf.Tofd = fd[j];

                        ret = ChangePass(RecvBuf.account, RecvBuf.password);
                        if(SUCCESS == ret)
                        {
                            RecvBuf.cmd = CHANGESUCCESS;
                            ret = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                            if(-1 == ret)
                            {
                                perror("CHANGEPASS  send");
                                exit(1);
                            }
                        }
                        RecvBuf.cmd = 0;
                    }

/************************************聊天*************************************/

                    if(CHATREQUST == RecvBuf.cmd)
                    {
                        RecvBuf.Tofd = fd[j];  //客户端的fd

                        Online l = LinkNode->next;

                        while(l)               //判断是否被禁言
                        {
                            if(l->SelfFd == fd[j] && l->ForbFlag == 1)
                            {
                                RecvBuf.cmd = FORRBIDDEN;

                                ret = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                                if(-1 == ret)
                                {
                                    perror("Forbid send");
                                    exit(1);
                                }
                                break;
                            }
                            else
                            {
                                l = l->next;
                            }
                        }

                        if(NULL == l)       
                        {
                            ret = OnlineJudge(LinkNode, RecvBuf.TarName);
                            if(REFUSECHAT == ret)
                            {
                                RecvBuf.cmd = REFUSECHAT;

                                ret = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                                printf("%d\n", RecvBuf.Tofd);
                                if(-1 == ret)
                                {
                                    perror("Chat send");
                                    return FAILURE;
                                }
                            }
                            else
                            {
                                RecvBuf.TargFd = ret;  //聊天对象的fd
                                printf("%d\n", RecvBuf.TargFd);

                                Recv.Tofd = ret;              //接收方的fd
                                Send.Tofd = RecvBuf.Tofd;     //发送方的fd

                                GetLinkName(LinkNode, Recv.Tofd, Recv.name);
                                GetLinkName(LinkNode, Send.Tofd, Send.name);

                                GetLinkName(LinkNode, fd[j], RecvBuf.name);
                                RecvBuf.cmd = ALLOWCHAT;

                                ret = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                                if(-1 == ret)
                                {
                                    perror("Chat send");
                                    return SUCCESS;
                                }

                                RecvBuf.cmd = ACCEPTCHAT;
                                ret = send(RecvBuf.TargFd, &RecvBuf, sizeof(RecvBuf), 0);
                                if(-1 == ret)
                                {
                                    perror("Chat send");
                                    return SUCCESS;
                                }
                            }
                        }
                        RecvBuf.cmd = 0;
                    }
/*
                    if(PRECHATTING == RecvBuf.cmd)
                    {
                        RecvBuf.Tofd = RecvBuf.TargFd;  //接受信息对象的fd;
                        RecvBuf.TargFd = fd[j];         //发送信息对象的fd;
                        strcpy(Recv.name, RecvBuf.TarName);//此时,RecvBuf.name  是发送方的,RecvBuf.TarName是接收方
                        strcpy(Send.name, RecvBuf.name);
                        printf("Recv %s  Send %s\n", Recv.name, Send.name);
                        ret = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                        if(-1 == ret)
                        {
                            perror("PRECHATTING send");
                            exit(1);
                        }

                    }  */
                    if(CHATTING == RecvBuf.cmd)
                    {
                        RecvBuf.Tofd = fd[j];
                        RecvBuf.cmd = CHATTING;
                        if(RecvBuf.Tofd != Send.Tofd)
                        {
                            strcpy(RecvBuf.name, Recv.name);
                            ret = send(Send.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                            if(-1 == ret)
                            {
                                perror("CHATTING send");
                                exit(1);
                            }
                        }
                        else
                        {
                            strcpy(RecvBuf.name, Send.name);
                            ret = send(Recv.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                            if(-1 == ret)
                            {
                                perror("CHATTING send");
                                exit(1);
                            }

                        }
                    }

/********************************查看在线好友*********************************/

                    if(CHECKONLINE == RecvBuf.cmd)
                    {
                        RecvBuf.Tofd = fd[j];

                        ret = PrintOnlineFriend(LinkNode, RecvBuf.Tofd);
                        if(FAILURE == ret)
                        {
                            perror("CHECKONLINE");
                            exit(1);
                        }
                    }

/********************************查看聊天记录*********************************/

                    if(CHECKHISTORY == RecvBuf.cmd)
                    {
                        RecvBuf.Tofd = fd[j];
                        RecvBuf.cmd = CHECKHISDONE;

                        ret = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                        if(-1 == ret)
                        {
                            perror("CHECKHISTORY  send");
                            exit(1);
                        }
                    }
/********************************群发*********************************/

                    if(SENDGROUP == RecvBuf.cmd)
                    {
                        RecvBuf.cmd = RECVGROUP;
                        Online l = LinkNode->next;
                        GetLinkName(LinkNode, fd[j], RecvBuf.name);

                        while(l)
                        {
                            if(l->SelfFd == fd[j] && l->ForbFlag == 1)
                            {
                                RecvBuf.cmd = FORRBIDDEN;

                                ret = send(fd[j], &RecvBuf, sizeof(RecvBuf), 0);
                                if(-1 == ret)
                                {
                                    perror("send");
                                    exit(1);
                                }
                                break;
                            }
                            else
                            {
                                l = l->next;
                            }
                        }
                        if(NULL == l)
                        {
                            l = LinkNode->next;

                            while(l != NULL && l->Flag == 1)
                            {
                                if(l->SelfFd != fd[j])
                                {
                                    ret = send(l->SelfFd, &RecvBuf, sizeof(RecvBuf), 0);
                                    if(-1 == ret)
                                    {
                                        perror("SENDGROUP send");
                                        exit(1);
                                    }
                                }
                                l = l->next;
                            }
                        }
                        RecvBuf.cmd = 0;
                    }

/********************************表情、常用语*********************************/

                    if(EMOJONLINECHICK == RecvBuf.cmd)
                    {
                        Online l = LinkNode->next;

                        while(l)
                        {
                            if(l->SelfFd == fd[j] && l->ForbFlag == 1)
                            {
                                RecvBuf.cmd = FORRBIDDEN;

                                ret = send(fd[j], &RecvBuf, sizeof(RecvBuf), 0);
                                if(-1 == ret)
                                {
                                    perror("send");
                                    exit(1);
                                }
                                break;
                            }
                            else
                            {
                                l = l->next;
                            }
                        }

                        if(NULL == l)
                        {
                            RecvBuf.Tofd = fd[j];

                            ret = OnlineJudge(LinkNode, RecvBuf.name);
                            if(REFUSECHAT == ret)
                            {
                                RecvBuf.cmd = EMOJNOTONLINE;

                                ret = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                                if(-1 == ret)
                                {
                                    perror("EMOJONLINECHICK send");
                                    exit(1);
                                }
                            }
                            else
                            {
                                RecvBuf.TargFd = ret;

                                RecvBuf.cmd = RECVEMOJ;
                                GetLinkName(LinkNode, fd[j], RecvBuf.name);

                                ret = send(RecvBuf.TargFd, &RecvBuf, sizeof(RecvBuf), 0);
                                if(-1 == ret)
                                {
                                    perror("EMOJONLINECHICK send");
                                    exit(1);
                                }
                            }
                        }
                    }

/************************************退出************************************/

                    if(QUIT == RecvBuf.cmd)
                    {
                        FD_CLR(fd[j], &ReadFd);
                        close(fd[j]);
                    }

                    if(SIGNAL == RecvBuf.cmd)
                    {
                        FD_CLR(fd[j], &ReadFd);
                        close(fd[j]);
                    }

/************************************下线************************************/

                    if(OFFLINE == RecvBuf.cmd)
                    {
                        RecvBuf.Tofd = fd[j];

                        Online l = LinkNode;
                        Online m;

                        while(l)
                        {
                            if(l->next->SelfFd == fd[j])
                            {
                                m = l->next;
                                l->next = m->next;
                                free(m);
                                break;
                            }
                            else
                            {
                                l = l->next;
                            }
                        }

                        ret = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                        if(-1 == ret)
                        {
                            perror("OFFLINE send");
                            exit(1);
                        }
                    }
/************************************会员************************************/                    

                    if(MEMBER == RecvBuf.cmd)
                    {
                        Online l = LinkNode->next;

                        while(l)
                        {
                            if(l->SelfFd == fd[j])
                            {
                                AddMember(l->account);
                                break;
                            }
                            else
                            {
                                l = l->next;
                            }
                        }

                    }
/************************************禁言************************************/

                    if(FORRBIDDEN == RecvBuf.cmd)
                    {
                        Online l = LinkNode->next;

                        while(l)
                        {
                            printf("4444\n");
                            if(l->SelfFd == fd[j])
                            {
                                ret = JudgeMember(l->account);
                                break;
                            }
                            else
                            {
                                l = l->next;
                            }
                        }
                        if(SUCCESS == ret)
                        {
                            l = LinkNode->next;
                            while(l)
                            {
                                if(!(strcmp(l->name, RecvBuf.Forbname)))
                                {
                                    l->ForbFlag = 1;
                                    break;
                                }
                                else
                                {
                                    l = l->next;
                                }
                            }
                        }
                        else
                        {           
                            RecvBuf.cmd = NOTMEMBER;

                            ret = send(fd[j], &RecvBuf, sizeof(RecvBuf), 0);
                            if(-1 == ret)
                            {
                                perror("send");
                                exit(1);
                            }
                        }
                    }
/**********************************解除禁言************************************/

                    if(DISMISS == RecvBuf.cmd)
                    {
                        Online l = LinkNode->next;

                        while(l)
                        {
                            if(l->SelfFd == fd[j])
                            {
                                ret = JudgeMember(l->account);
                                break;
                            }
                            else
                            {
                                l = l->next;
                            }

                        }

                        if(SUCCESS == ret)
                        {
                            l = LinkNode->next;

                            while(1)
                            {
                                if(!strcmp(l->name, RecvBuf.Forbname))
                                {
                                    l->ForbFlag = 0;
                                    break;
                                }
                                else
                                {
                                    l = l->next;
                                }
                            }
                        }
                        else
                        {
                            RecvBuf.cmd = NOTDISMISS;

                            ret = send(fd[j], &RecvBuf, sizeof(RecvBuf), 0);
                            if(-1 == ret)
                            {
                                perror("send");
                                exit(1);
                            }
                        }
                    }
/************************************踢人************************************/
                    if(FUCKOUT == RecvBuf.cmd)
                    {
                        RecvBuf.Tofd = fd[j];
                        Online l = LinkNode->next;

                        while(1)
                        {
                            if(l->SelfFd == fd[j])
                            {
                                ret = JudgeMember(l->account);
                                break;
                            }
                            else
                            {
                                l = l->next;
                            }
                        }

                        if(SUCCESS == ret)
                        {
                            l = LinkNode->next;

                            while(1)
                            {
                                if(!strcmp(l->name, RecvBuf.name))
                                {
                                    ret = send(l->SelfFd, &RecvBuf, sizeof(RecvBuf), 0);
                                    if(-1 == ret)
                                    {
                                        perror("FUCKOUT send");
                                        exit(1);
                                    }
                                    break;
                                }
                                else
                                {
                                    l = l->next;
                                }
                            }
                            if(NULL == l)
                            {
                                RecvBuf.cmd = NOTONLINE;

                                ret = send(fd[j], &RecvBuf, sizeof(RecvBuf), 0);
                                if(-1 == ret)
                                {
                                    perror("send");
                                    exit(1);
                                }
                            }
                        }
                        else
                        {
                            RecvBuf.cmd = NOTFUCK;

                            ret = send(fd[j], &RecvBuf, sizeof(RecvBuf), 0);
                            if(-1 == ret)
                            {
                                perror("send");
                                exit(1);
                            }
                        }
                    }

                }

/************************************文件传输********************************/

                if(FILESENDREQUST == RecvBuf.cmd)
                {
                    RecvBuf.Tofd = fd[j];

                    ret = OnlineJudge(LinkNode, RecvBuf.TarName);
                    if(REFUSECHAT == ret)
                    {
                        RecvBuf.cmd = REFUSESEND;

                        ret = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                        if(-1 == ret)
                        {
                            perror("send");
                            exit(1);
                        }       
                    }
                    else
                    {
                        RecvBuf.TargFd = ret;

                        RecvBuf.cmd = ACCEPTSEND;

                        ret = send(RecvBuf.Tofd, &RecvBuf, sizeof(RecvBuf), 0);
                        if(-1 == ret)
                        {
                            perror("send");
                            exit(1);
                        }       
                    }
                    RecvBuf.cmd = 0;
                }

                if(FILESEND == RecvBuf.cmd)
                {
                    printf("%d\n", RecvBuf.TargFd);
                    RecvBuf.cmd = RECVFILE;
                    ret = send(RecvBuf.TargFd, &RecvBuf, sizeof(RecvBuf), 0);
                    if(-1 == ret)
                    {
                        perror("send");
                        exit(1);
                    }
                }
                else if(SENDDONE == RecvBuf.cmd)
                {
                    printf("%d\n", RecvBuf.TargFd);
                    ret = send(RecvBuf.TargFd, &RecvBuf, sizeof(RecvBuf), 0);
                    if(-1 == ret)
                    {
                        perror("send");
                        exit(1);
                    }
                }

/****************************************************************************/
            }
        }
    }


    return 0;
}

客户端部分

客户端接口函数

#include "chatroom1.h"

int ACCOUNTFLAG = 0;
int EXISTFLAG = 0;

void hand(int tmp)
{
    extern pthread_t tid[3];
    extern int sockfd;
    int ret;
    Node Tmp ={0};

    Tmp.cmd = SIGNAL;

    ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("Exit send");
        exit(1);
    }

    system("clear");
    printf("\n\n\n\n\n\n");
    printf("\t\t\t\t异常退出,正在保存后台数据,请稍等...\n\n\n");   

    sleep(2);
    pthread_cancel(tid[0]);
    close(sockfd);
    exit(1);
}

void PrintTime()
{
    time_t t;
    struct tm *pt;
    time(&t);
    pt = localtime(&t);
    printf("\t\t\t\t%d年%d月%d日%d:%d\n", pt->tm_year + 1900, pt->tm_mon, pt->tm_mday, pt->tm_hour, pt->tm_min);
}

void *Recv(void *arg)
{
    int ret, sockfd, i;
    char FileName[50] = {0};
    FILE *fp;
    extern pthread_t tid[3];
    Node RecvBuf = {0};

    sockfd = *(int *)arg;

    while(1)
    {
        memset(&RecvBuf, 0, sizeof(RecvBuf));

        ret = recv(sockfd, &RecvBuf, sizeof(RecvBuf), 0);
        if(-1 == ret)
        {
            perror("recv");
            exit(1);
        }

        switch(RecvBuf.cmd)
        {
            case RECVGROUP:     //群发
                system("clear");
                printf("\t\t\t\t****************************************************\n\n");
                printf("\t\t\t\t收到一条来自%s群发消息:%s\n", RecvBuf.name, RecvBuf.ChatBuf); 
                printf("\t\t\t\t输入 q 返回主界面\n\n");
                break;
            case  RETONLINE:   //在线好友
                printf("\n");
                printf("\t\t\t\t****************************************************\n\n");
                printf("\t\t\t\t在线好友如下:\n\n");
                for(i = 0; i <= RecvBuf.num; i++)   
                {
                    printf("\t\t\t\t%s\n\n", RecvBuf.onlinefriend[i]);
                }
                break;
            case CHECKHISDONE: //聊天记录
                system("clear");
                ShowChatHist();
                break;
            case NOTMEMBER:    //非会员
                system("clear");
                printf("\t\t\t\t****************************************************\n\n");
                printf("\t\t\t\t您不是会员,无法这么做\n\n");
                printf("\t\t\t\t\t\t\t\t输入 q 返回主界面\n\n");
                break;
            case NOTDISMISS:   //无法解禁
                system("clear");
                printf("\t\t\t\t****************************************************\n\n");
                printf("\t\t\t\t您不是会员,无法这么做\n\n");
                printf("\t\t\t\t\t\t\t\t输入 q 返回主界面\n\n");
                break;
            case NOTFUCK:
                system("clear");
                printf("\t\t\t\t****************************************************\n\n");
                printf("\t\t\t\t您不是会员,无法这么做\n\n");
                printf("\t\t\t\t\t\t\t\t输入 q 返回主界面\n\n");
                break;
            case EMOJNOTONLINE:
                system("clear");
                printf("\t\t\t\t****************************************************\n\n");
                printf("\t\t\t\t对方并不在线,无法接收到信息.\n\n");
                break;
            case RECVEMOJ:
                system("clear");
                printf("\t\t\t\t****************************************************\n\n");
                printf("\t\t\t\t收到一条来自%s表情或常用语消息\n\n", RecvBuf.name);
                printf("\t\t\t\t%s\n", RecvBuf.ChatBuf);
                printf("\t\t\t\t\t\t\t\t\t输入 q 返回主界面\n\n");
                break;
            case FORRBIDDEN:
                system("clear");
                printf("\t\t\t\t****************************************************\n\n");
                printf("\t\t\t\t您已被禁言,无法发送信息,成为会员解除禁言\n\n");
                sleep(1);
                system("clear");
                break;
            case NOTONLINE:
                system("clear");
                printf("\t\t\t\t****************************************************\n\n");
                printf("\t\t\t\t对方已下线\n\n");
                sleep(1);
                system("clear");
                break;
            case FUCKOUT:
                system("clear");
                printf("\t\t\t\t****************************************************\n\n");
                printf("\t\t\t\t您已被踢下线,输入r返回登录界面,成为会员报复Ta\n\n");
                break;
            case REFUSECHAT:
                system("clear");
                printf("\t\t\t\t****************************************************\n\n");
                printf("\t\t\t\t对方并不在线\n\n");
                printf("\t\t\t\t\t\t\t\t\t输入 q 返回主界面\n\n");
                break;
            case ALLOWCHAT:
                system("clear");
                printf("\t\t\t\t****************************************************\n\n");
                printf("\t\t\t\t%s\n\n", RecvBuf.ChatBuf);
                break;
            case ACCEPTCHAT:
                system("clear");
                printf("\t\t\t\t\t\t\t\t输入k进行回复\n");
                printf("\t\t\t\t****************************************************\n\n");
                printf("\t\t\t\t\t\t\t\t%s\n", RecvBuf.name);
                printf("\t\t\t\t\t\t\t\t%s\n\n", RecvBuf.ChatBuf);
                break;
            case CHATTING:
                printf("\n");
                printf("\t\t\t\t\t\t\t\t%s\n", RecvBuf.name);
                printf("\t\t\t\t\t\t\t\t%s\n\n", RecvBuf.ChatBuf);
                ret = AddChatHist(RecvBuf.name, RecvBuf.ChatBuf);
                if(FAILURE == ret)
                {
                    printf("Insert Failure\n");
                    exit(1);
                }
                if(!strcmp(RecvBuf.ChatBuf, "bye"))
                {
                    pthread_cancel(tid[1]);
                }
                break;
            case REFUSESEND:
                system("clear");
                printf("\t\t\t\t对方不在线,无法接收文件\n\n");
                sleep(1);
                system("clear");
                break;
            case ACCEPTSEND:
                fp = fopen(RecvBuf.FilePath, "r");

                RecvBuf.cmd = FILESEND;

                while(ret = fread(RecvBuf.FileBuf, 1, sizeof(RecvBuf.FileBuf), fp))
                {
                    send(sockfd, &RecvBuf, sizeof(RecvBuf), 0);
                    memset(RecvBuf.FileBuf, 0, sizeof(RecvBuf.FileBuf));
                }

                RecvBuf.cmd = SENDDONE;
                send(sockfd, &RecvBuf, sizeof(RecvBuf), 0);

                fclose(fp);
                break;
            case RECVFILE:
                fp = fopen("myhello.txt", "a");

                ret = fwrite(RecvBuf.FileBuf, 1, strlen(RecvBuf.FileBuf), fp);
                if(0 == ret)
                {
                    perror("fwrite");
                    exit(1);
                }

                fclose(fp);
                break;
            case SENDDONE:
                printf("\t\t\t\t收到一个文件\n\n");
                break;
        }

    }
}

void *Send(void *arg)
{
    int ret, sockfd, oldtype;
    extern pthread_t tid[3];
    extern char filename[15];
    extern char Myname[10];

    FILE *fp;
    Node Tmp = {0};

    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);

    sockfd = *(int *)arg;

    fp = fopen(filename, "a");

    while(1)
    {
        scanf("%s", Tmp.ChatBuf);

        Tmp.cmd = CHATTING;
        ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
        if(-1 == ret)
        {
            perror("send");
            exit(1);
        }

        ret = AddChatHist(Myname, Tmp.ChatBuf);
        if(FAILURE == ret)
        {
            printf("Insert Failure\n");
            exit(1);
        }

        if(!strcmp(Tmp.ChatBuf, "bye"))
        {
            close(tid[1]);
            break;

        }
    }

    fclose(fp);
}

int loadshow(int sockfd)
{   
    system("clear");
    PrintTime();
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t***                  简易聊天室                  ***\n\n");
    printf("\t\t\t\t***                                   1.登录     ***\n\n");
    printf("\t\t\t\t***                                   2.注册     ***\n\n");
    printf("\t\t\t\t***                                   3.忘记密码 ***\n\n");
    printf("\t\t\t\t***                                   4.退出     ***\n\n");
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t请输入你的选择 : \n");
}

void Exit(int sockfd)
{
    int ret;
    extern pthread_t tid[3];
    Node Tmp = {0};

    Tmp.cmd = QUIT;

    ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("Exit send");
        exit(1);
    }

    pthread_cancel(tid[0]);
    close(sockfd);
    exit(1);
}

void Loginshow(int sockfd)           //登录
{
    int ret;
    FILE *fp;
    Node LogInfo = {0};
    extern char Myname[10];
    extern char filename[15];

    PrintTime();
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t请输入账号:\n\n");
    printf("\t\t\t\t");
    scanf("%s", LogInfo.account);
    printf("\n");
    printf("\t\t\t\t请输入密码:\n\n");
    printf("\t\t\t\t");
    scanf("%s", LogInfo.password);
    LogInfo.cmd = LOGIN;

    ret = send(sockfd, &LogInfo, sizeof(LogInfo), 0);
    if(-1 == ret)
    {
        perror("Logsend");
        exit(1);
    }

    memset(&LogInfo, 0, sizeof(LogInfo));
    ret = recv(sockfd, &LogInfo, sizeof(LogInfo), 0);
    if(-1 == ret)
    {
        perror("recv");
        exit(1);
    }

    if(ALLOWLOGIN == LogInfo.cmd)
    {
        int ret;
        LogInfo.cmd = INSERT;
        ret = send(sockfd, &LogInfo, sizeof(LogInfo), 0);
        if(-1 == ret)
        {
            perror("Logsend");
            exit(1);
        }

        system("clear");
        PrintTime();
        printf("\t\t\t\t****************************************************\n\n");
        printf("\t\t\t\t登录成功,正在跳转聊天界面。\n\n\n");
        sleep(1);
        printf("\t\t\t\t\t\t欢迎回来      ");
        printf("%s\n\n", LogInfo.name);
        sleep(1);
        system("clear");

        strcpy(Myname, LogInfo.name);
        strcpy(filename, LogInfo.name);
        strcat(filename, ".txt");
        fp = fopen(filename, "a");

        fclose(fp);

        LogSuccshow(sockfd);
    }
    else if(REFUSELOGIN == LogInfo.cmd)
    {
        system("clear");
        PrintTime();
        printf("\t\t\t\t****************************************************\n\n");
        printf("\t\t\t\t登录失败,请检查你的账号与密码。\n");
        printf("\t\t\t\t跳转登录界面中,请稍候...\n");
        sleep(1);
    }
}

void Registershow(int sockfd)   //注册
{
    Node RegInfo = {0};
    int ret, length1, length2;
    char TmpPass[20] = {0};

    PrintTime();
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t请输入账号:\n\n");
    printf("\t\t\t\t");
    scanf("%s", RegInfo.account);
    printf("\n");
    printf("\t\t\t\t请输入密码(16字节以内):\n\n");
    printf("\t\t\t\t");
    scanf("%s", RegInfo.password);
    printf("\n");
    printf("\t\t\t\t请确认密码(16字节以内):\n\n");
    printf("\t\t\t\t");
    scanf("%s", TmpPass);
    printf("\n");
    printf("\t\t\t\t请输入昵称:\n\n");
    printf("\t\t\t\t");
    scanf("%s", RegInfo.name);
    printf("\n");
    printf("\t\t\t\t请输入绑定手机号:\n\n");
    printf("\t\t\t\t");
    scanf("%s", RegInfo.telephone);

    length1 = strlen(RegInfo.password);
    length2 = strlen(RegInfo.telephone);

    if(length1 > 16)
    {
        printf("\t\t\t\t密码长度不符合,请重新注册。\n");
        sleep(1);
        system("clear");
    }
    else if(strcmp(RegInfo.password, TmpPass) != 0)
    {
        printf("\t\t\t\t两次密码不一致,请重新注册.\n");
        sleep(1);
        system("clear");
    }
    else if(length2 != 11)
    {
        printf("\t\t\t\t手机号码无效,请重新输入。\n");
        sleep(1);
        system("clear");
    }
    else
    {
        RegInfo.cmd = REGISTER;

        ret = send(sockfd, &RegInfo, sizeof(RegInfo), 0);
        if(-1 == ret)
        {
            perror("Regsend");
            exit(1);
        }

        memset(&RegInfo, 0, sizeof(RegInfo));
        ret  = recv(sockfd, &RegInfo, sizeof(RegInfo), 0);
        if(REGFAILURE == RegInfo.cmd)
        {
            system("clear");
            PrintTime();
            printf("\t\t\t\t****************************************************\n\n");
            printf("\t\t\t\t您使用的账号已存在,请重新选择账号进行注册!!\n");
            printf("\t\t\t\t跳转中,请稍后!\n");
            sleep(1);
            system("clear");
        }
        else if(REGSUCCESS == RegInfo.cmd)
        {
            system("clear");
            PrintTime();
            printf("\t\t\t\t****************************************************\n\n");
            printf("\t\t\t\t注册成功,正在跳转登录界面。\n");
            sleep(2);
            system("clear");
        }

    }

}

void ForgetPass(int sockfd)   //忘记密码
{
    char account[10] = {0};
    char tele[12] = {0};
    int length, ret;
    Node Tmp = {0};

    PrintTime();
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t请输入您的账号:\n\n");
    printf("\t\t\t\t");
    scanf("%s", account);
    printf("\n");
    printf("\t\t\t\t请输入绑定的手机号码:\n\n");
    printf("\t\t\t\t");
    scanf("%s", tele);

    length = strlen(tele);
    if(length != 11)
    {
        printf("\t\t\t\t输入的手机号码无效,请重新输入。\n");
        sleep(1);
        system("clear");
    }
    else
    {
        Tmp.cmd = CONFIRMACCOUNT;
        strcpy(Tmp.account, account);
        strcpy(Tmp.telephone, tele);

        ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
        if(-1 == ret)
        {
            perror("CONFIRMACCOUNT send");
            exit(1);
        }

        memset(&Tmp, 0, sizeof(Tmp));
        ret = recv(sockfd, &Tmp, sizeof(Tmp), 0);
        if(-1 == ret)
        {
            perror("rcv");
            exit(1);
        }

        if(EXIST == Tmp.cmd)
        {
            printf("\t\t\t\t正在为您跳转修改密码界面,请稍后...\n");
            sleep(1);
            system("clear");
            ResetPass(sockfd, Tmp.account);
        }
        else if(NOTEXIST == Tmp.cmd)
        {
            printf("\t\t\t\t此账号不存在,跳转注册界面中...\n\n");
            sleep(1);
            system("clear");
        }

    }
}

int ResetPass(int sockfd, char *account)    //密码重置
{
    char password[20] = {0};
    char Tmppass[20] = {0};
    int length, ret;
    Node Tmp = {0};

    PrintTime();
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t请输入密码(16字节以内):\n\n");
    printf("\t\t\t\t");
    scanf("%s", password);
    printf("\n");
    printf("\t\t\t\t请确认密码(16字节以内):\n\n");
    printf("\t\t\t\t");
    scanf("%s", Tmppass);
    printf("\n");

    length = strlen(password);

    while(length > 16 ||  strcmp(password, Tmppass) != 0)
    {
        if(length > 16)
        {
            printf("\t\t\t\t密码长度不符合,请重新输入\n");
            sleep(1);
            system("clear");

            PrintTime();
            printf("\t\t\t\t****************************************************\n\n");
            printf("\t\t\t\t请输入密码(16字节以内):\n\n");
            printf("\t\t\t\t");
            scanf("%s", password);
            printf("\n");
            printf("\t\t\t\t请确认密码(16字节以内):\n\n");
            printf("\t\t\t\t");
            scanf("%s", Tmppass);
            printf("\n");
            length = strlen(password);

        }
        else if(strcmp(password, Tmppass) != 0)
        {
            printf("\t\t\t\t两次密码不一致,请重新输入.\n");
            sleep(1);
            system("clear");

            PrintTime();
            printf("\t\t\t\t****************************************************\n\n");
            printf("\t\t\t\t请输入密码(16字节以内):\n\n");
            printf("\t\t\t\t");
            scanf("%s", password);
            printf("\n");
            printf("\t\t\t\t请确认密码(16字节以内):\n\n");
            printf("\t\t\t\t");
            scanf("%s", Tmppass);
            printf("\n");
            length = strlen(password);

        }
    }

    strcpy(Tmp.account, account);
    strcpy(Tmp.password, password);
    Tmp.cmd = CHANGEPASS;

    ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("send");
        return FAILURE;
    }

    memset(&Tmp, 0, sizeof(Tmp));
    ret = recv(sockfd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("recv");
        return FAILURE;
    }

    if(CHANGESUCCESS == Tmp.cmd)
        {
            printf("\t\t\t\t修改密码成功,跳转登录界面中...\n\n");
            sleep(1);
            system("clear");
        }
}


void LogSuccshow(int sockfd)
{
    system("clear");
    char choice[10] = {0};
    extern char Myname[10];
    extern pthread_t tid[3];
    int ret, oldtype;
    int i = 0;

    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);

    ret = pthread_create(&tid[0],NULL, Recv, (void *)&sockfd);
    if(0 != ret)
    {
        perror("pthread_creat");
        exit(1);
    }

    while(1)
    {
        PrintTime();
        printf("\t\t\t\t**********************************************************\n\n");
        printf("\t\t\t\t\t\t\t%s\n", Myname);
        printf("\t\t\t\t\t                            a.私聊            \n\n");
        printf("\t\t\t\t\t                            b.群发            \n\n");
        printf("\t\t\t\t\t                            c.查看在线好友    \n\n");
        printf("\t\t\t\t\t                            d.查看聊天记录    \n\n");
        printf("\t\t\t\t\t                            e.开通会员        \n\n");
        printf("\t\t\t\t\t                            f.禁言模式(会员)\n\n");
        printf("\t\t\t\t\t                            g.解除禁言(会员)\n\n");
        printf("\t\t\t\t\t                            h.表情、常用语    \n\n");
        printf("\t\t\t\t\t                            i.踢人(会员)    \n\n");
        printf("\t\t\t\t\t                            j.下线            \n\n");
        printf("\t\t\t\t\t                            t.文件传输        \n\n");
        printf("\t\t\t\t***********************************************************\n\n");
        printf("\t\t\t\t请输入你的选择:\n");
        printf("\t\t\t\t");
        scanf("%s", choice);
        switch(choice[0])
        {
            case 'a':
                system("clear");
                PriChat(sockfd);
                break;
            case 'b':
                SendGroup(sockfd);
                break;
            case 'c':
                system("clear");
                CheckOnline(sockfd);
                break;
            case 'd':
                system("clear");
                SearChatHis(sockfd);
                break;
            case 'e':
                system("clear");
                member(sockfd);
                break;
            case 'f':
                system("clear");
                ForbidMod(sockfd);
                break;
            case 'g':
                system("clear");
                Dismiss(sockfd);
                break;
            case 'h':
                system("clear");
                SendEmoj(sockfd);
                break;
            case 'i':
                system("clear");
                Fuck(sockfd);
                break;
            case 'j':
                system("clear");
                Offline(sockfd);
                i = 9;
                break;
            case 'k':    
                RecvChat(sockfd);
                break;
            case 't':
                Transform(sockfd);
                break;
            case 'q':
                system("clear");
                break;
            case 'r':
                FuckOffline();
                i = 9;
                break;
            default:
                printf("Unkown choice\n");
                sleep(1);
                system("clear");
        }
        if(i == 9)
        {
            printf("1 = %d\n", i);
            break;
        }
    }

}


/*************聊天功能函数****************/

int PriChat(int sockfd)
{
    int ret;
    Node SendBuf = {0};
    extern pthread_t tid[3];

    PrintTime();
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t请输入你想私聊的对象:\n");
    printf("\t\t\t\t");
    scanf("%s",SendBuf.TarName);
    printf("\n\n");
    printf("\t\t\t\t请输入你想说的话:\n");
    printf("\t\t\t\t");
    scanf("%s",SendBuf.ChatBuf);

    SendBuf.cmd = CHATREQUST;

    ret = send(sockfd, &SendBuf, sizeof(SendBuf), 0);
    if(-1 == ret)
    {
        perror("PriChat send");
        return FAILURE;
    }

    ret = pthread_create(&tid[1], NULL, Send, (void *)&sockfd);
    if(0 != ret)
    {
        perror("pthread_create");
        exit(1);
    }

    pthread_join(tid[1], NULL);
    return SUCCESS;
}

int RecvChat(int sockfd)
{
    int ret;
    extern pthread_t tid[3];

    system("clear");
    PrintTime();
    printf("\t\t\t\t****************************************************\n\n");
    ret = pthread_create(&tid[1], NULL, Send, (void *)&sockfd);
    if(0 != ret)
    {
        perror("pthread_create");
        exit(1);
    }

    pthread_join(tid[1], NULL);

}

int ChattingShow(int sockfd, int TargFd, char *name, char *Tarname)
{
    int ret;
    Node Tmp = {0};
    extern char filename[15];
    FILE *fp;

    Tmp.TargFd = TargFd;
    Tmp.Tofd = sockfd;
    strcpy(Tmp.TarName, Tarname);
    strcpy(Tmp.name, name);

    printf("%s  %s \n", Tarname, name);
    PrintTime();
    printf("\t\t\t\t简易聊天室\n");
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t");
    scanf("%s", Tmp.ChatBuf);  //聊天内容

    fp = fopen(filename, "a");
    if(NULL == fp)
    {
        perror("fopen");
        return FAILURE;
    }

    ret = AddChatHist(name, Tmp.ChatBuf);
    if(FAILURE == ret)
    {
        printf("Add Failure");
        exit(1);
    }

    fclose(fp);

    Tmp.cmd = PRECHATTING;
    ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("ChattingShow send");
        return FAILURE;
    }

    return SUCCESS;
}

int ChattingShow2(int sockfd, int TargFd, char *name, char *Tarname)
{
    int ret;
    Node Tmp = {0};
    Tmp.TargFd = TargFd;
    Tmp.Tofd = sockfd;
    strcpy(Tmp.TarName, Tarname);
    strcpy(Tmp.name, name);

    system("clear");
    PrintTime();
    printf("\t\t\t\t简易聊天室                              回复请输入'k'\n");
    printf("\t\t\t\t****************************************************\n\n");

    return SUCCESS;
}

int SendGroup(int sockfd)
{
    int ret;
    Node Tmp = {0};
    system("clear");
    PrintTime();
    printf("\t\t\t\t简易聊天室                                           \n");
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t请输入群发的信息内容:");
    scanf("%s", Tmp.ChatBuf);

    Tmp.cmd = SENDGROUP;

    ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("SendGroup send");
        exit(1);
    }

    sleep(2);
    system("clear");
}

int CheckOnline(int sockfd)
{
    int ret;
    Node Tmp = {0};

    Tmp.cmd = CHECKONLINE;
    ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("CheckOnline");
        exit(1);
    }

    sleep(2);

}

int SearChatHis(int sockfd)
{   
    int ret;

    Node Tmp = {0};

    Tmp.cmd = CHECKHISTORY;

    printf("11111\n");
    ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("SearChatHis send");
        exit(1);
    }

}

void ShowChatHist()
{
    char choice[10] = {0};
    extern char filename[15];
    FILE *fp;
    ChatHist HisTmp = {0};
    int ret;

    PrintTime();
    printf("\t\t\t\t****************************************************\n\n");
    ret = 1;

    fp = fopen(filename, "r");

    while(ret)
    {
        ret = fread(&HisTmp, 1, sizeof(HisTmp), fp);
        printf("\t\t\t\t%d年%d月%d日%d:%d:%d\n", HisTmp.year, HisTmp.month, HisTmp.day, HisTmp.hour, HisTmp.min,HisTmp.sec);
        printf("\t\t\t\t%s\n", HisTmp.name);
        printf("\t\t\t\t%s\n\n", HisTmp.cont);
    }

    printf("\t\t\t\t\t\t\t输入q返回上一级菜单\n\n");

    fclose(fp);
}

void member(int sockfd)
{
    int ret;
    Node Tmp = {0};
    char choice[10] = {0};

    PrintTime();
    printf("\t\t\t\t简易聊天室                                           \n");
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t你愿意誓死守护皇家的荣誉吗?\n\n");
    printf("\t\t\t\tyes or no \n\n");
    printf("\t\t\t\t");
    scanf("%s", choice);

    if(!strcmp(choice, "yes"))
    {
        Tmp.cmd = MEMBER;

        ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
        if(-1 == ret)
        {
            perror("sned");
            exit(1);
        }

        printf("\t\t\t\t恭喜你成为尊贵的会员,拥有踢人,禁言等功能\n\n");
        sleep(2);
        system("clear");
    }
    else
    {
        printf("\t\t\t\t注定与荣耀无缘\n\n");
        sleep(2);
    }
}

void ForbidMod(int sockfd)
{
    char name[10] = {0};
    Node Tmp = {0};
    int ret;

    printf("\t\t\t\t请输入你想禁言的昵称\n\n");
    printf("\t\t\t\t");
    scanf("%s", Tmp.Forbname);

    Tmp.cmd = FORRBIDDEN;

    ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("ForbidMod send");
        exit(1);
    }

    system("clear");
}

void Dismiss(int sockfd)
{
    char name[10] = {0};
    Node Tmp = {0};
    int ret;

    printf("\t\t\t\t请输入你想解除禁言的昵称\n\n");
    printf("\t\t\t\t");
    scanf("%s", Tmp.Forbname);

    Tmp.cmd = DISMISS;

    ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("ForbidMod send");
        exit(1);
    }

    system("clear");

}

void Offline(int sockfd)
{
    int ret;
    Node Tmp = {0};

    Tmp.cmd = OFFLINE;

    ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("OFFLINE send");
        exit(1);
    }
}

void FuckOffline()
{
    extern pthread_t tid[3];

    pthread_cancel(tid[0]);

}

void Fuck(int sockfd)
{
    int ret;
    Node Tmp = {0};

    printf("\t\t\t\t请输入你想踢下线的用户\n");
    printf("\t\t\t\t");
    scanf("%s", Tmp.name);

    Tmp.cmd = FUCKOUT;

    ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("Fuck send");
        exit(1);
    }

    sleep(1);
    system("clear");
}


void LogSuccshow1()
{
    PrintTime();
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t\t                                a.私聊            \n\n");
    printf("\t\t\t\t\t                                b.群发            \n\n");
    printf("\t\t\t\t\t                                c.查看在线好友    \n\n");
    printf("\t\t\t\t\t                                d.查看聊天记录    \n\n");
    printf("\t\t\t\t\t                                e.禁言模式        \n\n");
    printf("\t\t\t\t\t                                f.表情、常用语    \n\n");
    printf("\t\t\t\t\t                                g.踢人            \n\n");
    printf("\t\t\t\t\t                                h.下线            \n\n");
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t请输入你的选择:\n");

}

void Transform(int sockfd)
{
    int ret;
    char filepath[30] = {0};
    FILE *fp;

    Node Tmp = {0};

    printf("\t\t\t\t请输入接收方的昵称\n\n");
    printf("\t\t\t\t");
    scanf("%s", Tmp.TarName);

    printf("\t\t\t\t请输入文件名\n\n");
    printf("\t\t\t\t");
    scanf("%s", Tmp.FilePath);

    Tmp.cmd = FILESENDREQUST;

    ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
    if(-1 == ret)
    {
        perror("send");
        exit(1);
    }

    usleep(1000);
    system("clear");
}

int AddChatHist(char *Targname, char *chat)
{
    int ret;
    time_t t;
    struct tm *pt;
    extern char filename[15];
    FILE *fp;

    time(&t);
    pt = localtime(&t);
    ChatHist Tmp = {0};

    Tmp.year = pt->tm_year + 1900;
    Tmp.month = pt->tm_mon;
    Tmp.day = pt->tm_mday;
    Tmp.hour = pt->tm_hour;
    Tmp.min = pt->tm_min;
    Tmp.sec = pt->tm_sec;

    strcpy(Tmp.name, Targname);
    strcpy(Tmp.cont, chat);

    fp = fopen(filename, "a");
    if(NULL == fp)
    {
        perror("fopen");
        return FAILURE;
    }

    ret = fwrite(&Tmp, 1, sizeof(ChatHist), fp);
    if(0 == ret)
    {
        perror("fwrite");
        return FAILURE;
    }

    fclose(fp);
    return SUCCESS;
}

int SendEmoj(int sockfd)
{
    char choice[10] = {0};
    int ret;
    extern char *Emoj[8];
    extern char *languae[5];
    Node Tmp = {0};

    PrintTime();
    printf("\t\t\t\t简易聊天室\n");
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t请输入发送对象的昵称:\n\n");
    printf("\t\t\t\t");
    scanf("%s", Tmp.name);

    system("clear");
    PrintTime();
    printf("\t\t\t\t简易聊天室\n");
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t***  1.表情                           2.常用语   ***\n\n");
    printf("\t\t\t\t****************************************************\n\n");
    printf("\t\t\t\t请输入你的选择:\n\n");
    printf("\t\t\t\t");
    scanf("%s", choice);

    while(!(atoi(&choice[0]) == 1 ||  atoi(&choice[0]) == 2))
    {
        printf("\t\t\t\t你输入有误,请重新输入\n\n");
        printf("\t\t\t\t");
        memset(choice, 0, sizeof(choice));
        scanf("%s", choice);
    }

    if(atoi(&choice[0]) == 1)
    {

        memset(choice, 0, sizeof(choice));

        system("clear");
        PrintTime();
        printf("\t\t\t\t简易聊天室\n");
        printf("\t\t\t\t****************************************************\n\n");
        printf("\t\t\t\t***                           1.<( ̄︶ ̄)>     ***\n\n");
        printf("\t\t\t\t***                           2.<( ̄︶ ̄)/     ***\n\n");
        printf("\t\t\t\t***                           3.(# ̄▽ ̄#)      ***\n\n");
        printf("\t\t\t\t***                           4.b( ̄▽ ̄)d      ***\n\n");
        printf("\t\t\t\t***                           5.  ~>_<~        ***\n\n");
        printf("\t\t\t\t***                           6.  (>﹏<)       ***\n\n");
        printf("\t\t\t\t***                           7.  (┬_┬)        ***\n\n");
        printf("\t\t\t\t***                           8.(︶^︶)=凸     ***\n\n");
        printf("\t\t\t\t****************************************************\n\n");
        printf("\t\t\t\t请输入你的选择:\n\n");
        printf("\t\t\t\t");
        scanf("%s", choice);
        switch(atoi(&choice[0]))
        {
            case 1:
                strcpy(Tmp.ChatBuf, Emoj[0]);
                break;
            case 2:
                strcpy(Tmp.ChatBuf, Emoj[1]);
                break;
            case 3:
                strcpy(Tmp.ChatBuf, Emoj[2]);
                break;
            case 4:
                strcpy(Tmp.ChatBuf, Emoj[3]);
                break;
            case 5:
                strcpy(Tmp.ChatBuf, Emoj[4]);
                break;
            case 6:
                strcpy(Tmp.ChatBuf, Emoj[5]);
                break;
            case 7:
                strcpy(Tmp.ChatBuf, Emoj[6]);
                break;
            case 8:
                strcpy(Tmp.ChatBuf, Emoj[7]);
                break;
            default:
                printf("\t\t\t\tUnkown choose\n");
                sleep(1);
                system("clear");
        }

        printf("%s\n", Tmp.ChatBuf);
        Tmp.cmd = EMOJONLINECHICK;
        ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
        if(-1 == ret)
        {
            perror("EMOJ  send");
            exit(1);
        }
    }
    else if(atoi(&choice[0]) == 2)
    {

        memset(choice, 0, sizeof(choice));

        system("clear");
        PrintTime();
        printf("\t\t\t\t简易聊天室\n");
        printf("\t\t\t\t****************************************************\n\n");
        printf("\t\t\t\t***                           1.祝               ***\n\n");
        printf("\t\t\t\t***                           2.大家             ***\n\n");
        printf("\t\t\t\t***                           3.圣诞节           ***\n\n");
        printf("\t\t\t\t***                           4.元旦节           ***\n\n");
        printf("\t\t\t\t***                           5.快乐             ***\n\n");
        printf("\t\t\t\t****************************************************\n\n");
        printf("\t\t\t\t请输入你的选择:\n\n");
        printf("\t\t\t\t");
        scanf("%s", choice);
        switch(atoi(&choice[0]))
        {
            case 1:
                strcpy(Tmp.ChatBuf, languae[0]);
                break;
            case 2:
                strcpy(Tmp.ChatBuf, languae[1]);
                break;
            case 3:
                strcpy(Tmp.ChatBuf, languae[2]);
                break;
            case 4:
                strcpy(Tmp.ChatBuf, languae[3]);
                break;
            case 5:
                strcpy(Tmp.ChatBuf, languae[4]);
                break;
            default:
                printf("\t\t\t\tUnkown choose\n");
                sleep(1);
                system("clear");
        }

        Tmp.cmd = EMOJONLINECHICK;
        ret = send(sockfd, &Tmp, sizeof(Tmp), 0);
        if(-1 == ret)
        {
            perror("EMOJ  send");
            exit(1);
        }
    }
    sleep(1);
    system("clear");
}
#include "chatroom1.h"

pthread_t tid[3];
char Myname[10];
char filename[15];
char GroupMsg[10];
int sockfd;
char *Emoj[8] = {"<( ̄︶ ̄)>", "<( ̄︶ ̄)/", "(# ̄▽ ̄#)", "b( ̄▽ ̄)d", "~>_<~", "(>﹏<)", "(┬_┬)", "(︶^︶)=凸"};
char *languae[5] = {"祝", "大家", "圣诞节", "元旦节", "快乐"};

int main()
{
    int ret;
    char choice[10] = {0};
    struct sockaddr_in server_addr;

    sockfd = socket(PF_INET, SOCK_STREAM, 0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }

    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = PF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    printf("Connecting...\n");
    ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if(-1 == ret)
    {
        perror("connect");
        exit(1);
    }

    signal(SIGINT, hand);

    while(1)
    {
        loadshow(sockfd);
        printf("\t\t\t\t");
        scanf("%s", choice);
        switch(atoi(&choice[0]))
        {
            case 1:
                system("clear");
                Loginshow(sockfd);
                break;
            case 2:
                system("clear");
                Registershow(sockfd);
                break;
            case 3:
                system("clear");
                ForgetPass(sockfd);
                break;
            case 4:
                Exit(sockfd);
                break;
            default:
                printf("\t\t\t\tUnkown Choice\n");
                sleep(1);
        }
    }


    return 0;
}

总结:
对于这个项目中,让我最为印象深刻的部分是私聊界面的实现,当主线程执行到私聊时,需要另外开辟两个线程,一个用来接收,另一个用来发送信息,这样就可以连续的发送,直到发送了指定的内容再结束,那么此时会出现一个问题,受邀请聊天方,如果直接清屏的话,输入依然是上一个界面的scanf,那么此时如若回复信息的话,并不是真正的回复信息,而是执行了上一次的scanf,我是通过提示用户输入一个字符进行回复状态,其实这个字符只是完成被“隐藏的”scanf,那么通过这个字符去调用一个发送的线程,此时就能实现两个客户端的相互通信。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值