Ubuntu环境下基于Socket通信的网络聊天系统

在Linux环境下,利用Socket通信实现网络聊天程序,主要包括以下功能:

(1)系统各菜单功能界面、聊天界面的显示

(2)用户的注册、登录(手机号注册,合格性检测,重复性检测),注册后创建用户文件夹

(3)可支持好友管理(好友列表在线显示、增删查,网络传输文件),账户管理(修改信息,权限变更(创新可调用MD5库文件)

(3)聊天方式分群聊和私聊两种方式,群聊可管理员设置禁言,代码实现禁言单用户,全员禁言代码类同(创新可加入自然语言检测,实现敏感词监督)

(4)保存聊天记录,代码实现保存私聊记录,群聊记录保存类同

(5)实现客户端之间网络传输文件

服务器每接上一个客户端,启动一个线程;

客户端创建收发线程与服务器交互。

Server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <memory.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <time.h>
#include <malloc.h>
#include <sys/stat.h>
#include <termios.h>

#define NUM 1024
#define SIZE sizeof(cliMesg)  //结构体cliMesg的大小
typedef long long ll;


//账户类
typedef struct client_message
{
    char id[20];         //每个账号唯一id,  手机号
    char passwd[20];	 //账号密码
    char name[50];		 //账号昵称
    char hy[100][20];	 //好友列表,最大100个
    int hys;             //好友数量
    int online;          //0不在线, 1在线
    int fd;              //存放客户端成功连接后accept产生的新的套接字,  不在线为-5
    int chatroom;		 //存放是否打开了双人聊天室,打开为1 ,  没打开为0
    int admin;          //管理员权限  -1禁言 - 踢出不能再进
    //bMesg status;  //禁言
    long ed_time;
    struct client_message *next;	 //下一条链表的首地址

}cliMesg;

//信息类
typedef struct friend_message
{
    char rid[20];               //收信息的人
    char sid[20];               //发信息的人
    int type;                   //信息类型 ,  好友请求1 ,  私聊信息 2 , 好友请求回复信息3 ,  文件传输4 , 文件回复5
    char mesg[1024];            //信息
    char fname[1024];           //文件名
    struct friend_message * next;//下一条信息的首地址
}friMesg;

cliMesg *head=NULL;
friMesg *head1=NULL; 
int count =0;   //账号数量
int urev_count=0;   //未发送的信息

//创建账号信息的头指针
cliMesg *create_count()
{
    cliMesg *p1;
    p1=(cliMesg *)malloc(SIZE);
    if(p1==NULL)
    {
        printf("create error\n");
        return NULL;
    }
    p1->next=NULL;

    //记录账户
    FILE *fp;
    fp=fopen("counterMsg","a+");       //打开文件
    if(fp==NULL)
    {
        printf("open error\n");
        return NULL;
    }

    //文件为空
    if(fgetc(fp)==EOF)
    {
        fclose(fp);
        return p1;
    }

    //文件有内容
    rewind(fp);          //文件指针重返文件头

    //获取账号数量
    int counter_num;
    fread(&counter_num,sizeof(int),1,fp);
    printf("counter_num=%d\n",counter_num);
    count=counter_num;

    //建立好友链表
    cliMesg t;
    cliMesg *tmp,*p;
    int i;
    for(i=0;i<counter_num;i++)
    {
        fread(&t,sizeof(cliMesg),1,fp);
        p=p1;
        while(p->next)
        {
            p=p->next;
        }
        tmp=(cliMesg *)malloc(sizeof(cliMesg));
        tmp->next=NULL;
        strcpy(tmp->id,t.id);
        strcpy(tmp->name,t.name);
        strcpy(tmp->passwd,t.passwd);
        tmp->admin=t.admin;
        tmp->hys=t.hys;
        tmp->ed_time=t.ed_time;
        //有好友将数据存入好友链表
        int j;
        for(j=0;j<tmp->hys;j++)
        {
            strcpy(tmp->hy[j],t.hy[j]);
        }

        tmp->fd= -5;  //初始未登录
        tmp->chatroom=0; //初始未私聊
        tmp->online=0;  //初始未在线
        //tmp->admin=0;  //初始为普通用户
        p->next=tmp;

    }

    fclose(fp);
    return p1;

}

//创建未查看信息的头指针
friMesg *create_buffmsg()
{
    friMesg *x;
    x=(friMesg *)malloc(sizeof(friMesg));
    if(x==NULL)
    {
        printf("create error\n");
        return NULL;
    }
    x->next=NULL;

    FILE *fp;
    fp=fopen("buffMsg","a+");
    if(fp==NULL)
    {
        printf("open error\n");
        return NULL;
    }

    //如果为空文件关闭文件直接返回头指针
    if(fgetc(fp)==EOF)
    {
        fclose(fp);
        return x;
    }

    rewind(fp);

    int n;
    fread(&n,sizeof(int),1,fp);
    printf("urev_num=%d\n",n);
    urev_count=n;

    friMesg t;
    friMesg *p,*p1;
    //创建未查看信息链表
    int i;
    for(i=0;i<n;i++)
    {
        fread(&t,sizeof(friMesg),1,fp);
        p1=x;
        while(p1->next)
        {
            p1=p1->next;
        }
        p=(friMesg *)malloc(sizeof(friMesg));
        p->next=NULL;
        strcpy(p->rid,t.rid);
        strcpy(p->sid,t.sid);
        p->type=t.type;
        strcpy(p->mesg,t.mesg);
        p1->next=p;
    }
    fclose(fp);
    return x;
}

//获取系统时间
char **get_time()
{
    char **str=(char **)malloc(NUM*sizeof(char *));
    time_t t;
    struct tm * lt;
    time (&t);//获取Unix时间戳。
    lt = localtime (&t);//转为时间结构。
    sprintf ( str,"%04d/%02d/%02d %02d:%02d:%02d\n",lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec);//输出结果
    return str;
}

//保存账户信息
void saveclient()
{
    FILE *fp;
    fp=fopen("counterMsg","w");       //打开文件
    if(fp==NULL)
    {
        printf("open error\n");
        return;
    }
    printf("账户个数=%d",count);
    fwrite(&count,sizeof(int),1,fp);		//先保存账号个数

    cliMesg* p;
    p=head;
    if(p->next==NULL) 		//如果账号列表为空 ,  关闭文件并退出函数
    {
        fclose(fp);
        return ;
    }

    p=p->next;
    //按结构体大小保存账号信息
    while(p)
    {
        fwrite(p,sizeof(cliMesg),1,fp);
        p=p->next;
    }
    printf("账号信息保存成功\n");

    fclose(fp);

}

//保存未查看的消息
void savefile()
{
    FILE  *fp;
    fp=fopen("buffMsg","w");
    if(fp==NULL)
    {
        printf("open error\n");
        return;
    }
    printf("未查看信息个数=%d\n",urev_count);
    fwrite(&urev_count,sizeof(int),1,fp);

    friMesg *p;
    p=head1;
    if(p->next==NULL)
    {
        fclose(fp);
        return;
    }

    p=p->next;
    while(p)
    {
        fwrite(p,sizeof(cliMesg),1,fp);
        p=p->next;
    }
    printf("信息保存成功");
    fclose(fp);

}

//服务器上当前客户端id.txt保存聊天记录
void savefile2(char str[1024],char id[20])
{
    FILE *fp;
    char ch[1024];
    sprintf(ch,"./%s/%s.txt",id,id);
    fp=fopen(ch,"a+");
    if(fp==NULL)			//打开错误关闭程序
        return ;
    memset(ch,0,1024);
    strcat(str,"\n");      //txt文档每行句末尾加特殊换行符
    strcpy(ch,str);
    fwrite(ch,strlen(ch),1,fp);
    printf("聊天记录保存成功\n");
    fclose(fp);
}

//帐号合格性检查
int isnum1(char s[20])
{
    int i=0;
    while(s[i])
    {
        if(!isdigit(s[i]))
        {
            return 0;
        }
        i++;
    }
    if(i<11)
    {
        return 0;
    }
    return 1;
}

//用户注册
void add(int fd)
{
    cliMesg *p1,*p,*p2;

    int leap=0;                                    //标识符,账号是否能正确注册
    p=(cliMesg *)malloc(SIZE);			
    if(p==NULL)
        return;
    char str[256];
    char str1[256];
    memset(str,0,sizeof(str));
    memset(str1,0,sizeof(str1));
    strcpy(str,"请输入您要注册的手机号");
    send(fd,str,strlen(str),0);
    memset(str,0,sizeof(str));
    recv(fd,str,sizeof(str),0);
    strcpy(str1,str);
    if(!isnum1(str))                 //判断是否纯数字账号
    {
        memset(str,0,sizeof(str));
        strcpy(str,"请输入正确的手机号\n");
        send(fd,str,strlen(str),0);
        return;
    }
    p1=head;
    //判断注册账户是否存在
    while(p1->next)
    {
        if(strcmp(p1->next->id,str)==0)
        {
            leap=1;
            break;
        }
        p1=p1->next;
    }
    if(leap==1)
    {
        memset(str,0,sizeof(str));
        strcpy(str,"账号重复\n");
        send(fd,str,strlen(str),0);
        return;
    }
    //正常注册
    strcpy(p->id,str1);
    memset(str,0,sizeof(str));
    strcpy(str,"请输入密码");
    send(fd,str,strlen(str),0);

    memset(str,0,sizeof(str));
    recv(fd,str,sizeof(str),0);
    strcpy(p->passwd,str);

    memset(str,0,sizeof(str));
    strcpy(str,"请输入昵称");
    send(fd,str,strlen(str),0);

    memset(str,0,sizeof(str));
    recv(fd,str,sizeof(str),0);
    strcpy(p->name,str);
    p1=head;
    while(p1->next)
    {
        p1=p1->next;
    }
    p1->next=p;
    p->hys=0;
    p->online=0;
    p->fd=-5;
    p->next=NULL;
    memset(str,0,sizeof(str));
    strcpy(str,"注册成功,您可以登录了\n");
    send(fd,str,strlen(str),0);
    count++;                                 //全局变量账号数量+1
    //保存账户信息
    saveclient();
    memset(str,0,sizeof(str));
    sprintf(str,"mkdir ./%s",p->id);
    system(str);

}

//账户匹配检查
int check_iscount(char id[20])
{
    cliMesg *p;
    if(head->next==NULL)
    {
        return 0;
    }
    p=head->next;
    while(p)
    {
	if(strcmp(id,p->id)==0)
	{
            return 1;
	}
        p=p->next;
    }
    return 0;
}

//密码匹配检查
int check_countpasswd(char id[20],char passwd[20])
{
    cliMesg *p;
    if(head->next==NULL)
    {
        return 0;
    }
    p=head->next;

    while(p)
    {

        if(strcmp(id,p->id)==0 && strcmp(passwd,p->passwd)==0)
        {
            return 1;
        }
        p=p->next;
    }
    return 0;
}

//判断是否在线
int countOnline(char id[20])
{
    cliMesg *p;
    p=head;
    while(p)
    {
        if((strcmp(p->id,id)==0) && p->online==1)
        {
            return 1;
        }
        p=p->next;
    }
    return 0;
}

//好友列表
void list_friends(int fd,char id[20])
{
    char sendbuf[1024]={0};
    cliMesg *p,*p1;
    int cnt=0;
    p=head;
    p=p->next;
    while(p)
    {
        if(strcmp(p->id,id)==0)
        {
            break;
        }
        p=p->next;
    }
    int num=p->hys;
    if(num==0)
    {
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"好友列表为空");
        send(fd,sendbuf,strlen(sendbuf),0);
        return;
    }
    memset(sendbuf,0,sizeof(sendbuf));
    strcpy(sendbuf,"***************好友列表***************");
    send(fd,sendbuf,strlen(sendbuf),0);
    int i;
    for(i=0;i<num;i++)
    {
        p1=head->next;
        char str[20]={0};
        while(p1)
        {
            if(strcmp(p1->id,p->hy[i])==0)
            {
                strcpy(str,p1->name);
                break;
            }
            p1=p1->next;
        }
        memset(sendbuf,0,sizeof(sendbuf));
        if(p1->online==1)
            cnt++;
        sprintf(sendbuf,"%d 好友账号[%s],昵称[%s],[%d]\n",i+1,p->hy[i],str,p1->online);
        send(fd,sendbuf,strlen(sendbuf),0);
    }
    memset(sendbuf,0,sizeof(sendbuf));
    sprintf(sendbuf,"在线好友个数=%d\n",cnt);
    send(fd,sendbuf,strlen(sendbuf),0);
    memset(sendbuf,0,sizeof(sendbuf));
    strcpy(sendbuf,"**************************************");
    send(fd,sendbuf,strlen(sendbuf),0);

}

//查找已加好友
void find_friends(int fd,char id[20])
{
    cliMesg *p,*p1;
    p=head;
    char sendbuf[1024]={0};
    char recvbuf[1024]={0};
    char find_id[1024]={0};

    strcpy(sendbuf,"请输入您要查找的手机号");
    send(fd,sendbuf,strlen(sendbuf),0);
    recv(fd,find_id,sizeof(find_id),0);
    //查找手机号是否存在
    if(check_iscount(find_id)==0)
    {
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"此号码不存在");
        send(fd,sendbuf,strlen(sendbuf),0);
        return;
    }
    //查找自己是否有该好友
    p=p->next;
    while(p)
    {
        if(strcmp(p->id,id)==0)
        {
            break;
        }
        p=p->next;
    }
    if(p->hys==0)
    {
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"没有此好友");
        send(fd,sendbuf,strlen(sendbuf),0);
    }
    int i;
    int num=p->hys;
    for(i=0;i<num;i++)
    {
        //如果找到
        if(strcmp(p->hy[i],find_id)==0)
        {
            //将其昵称取出
            p1=head->next;
            char str[20]={0};
            while(p1)
            {
                if(strcmp(p1->id,find_id)==0)
                {
                    strcpy(str,p1->name);
                    break;
                }
                p1=p1->next;
            }
            memset(sendbuf,0,sizeof(sendbuf));
            sprintf(sendbuf,"该好友账户为%s,昵称为%s",find_id,str);	
            send(fd,sendbuf,strlen(sendbuf),0);			
        }

    }
}

//删除好友
void del_friends(int fd,char id[20])
{
    cliMesg *p,*p1;
    int i,leap=0;
    char sendbuf[1024]={0};
    char recvbuf[1024]={0};

    p=head->next;
    while(p)
    {
        if(strcmp(p->id,id)==0)
        {
            break;
        }
        p=p->next;
    }
    if(p->hys==0)
    {
        strcpy(sendbuf,"您的好友列表为空");
        send(fd,sendbuf,strlen(sendbuf),0);
        return;
    }
    //好友列表含有信息
    memset(sendbuf,0,sizeof(1024));
    strcpy(sendbuf,"输入你想删除的好友账户");
    send(fd,sendbuf,strlen(sendbuf),0);
    recv(fd,recvbuf,sizeof(recvbuf),0);
    for(i=0;i<(p->hys);i++)
    {
        if(strcmp(p->hy[i],recvbuf)==0)
        {
            //删除中间节点
            while(i<(p->hys-1))
            {
                strcpy(p->hy[i],p->hy[i+1]);
                i++;
            }
            memset(p->hy[i],0,sizeof(p->hy[i]));
            p->hys--;
            memset(sendbuf,0,sizeof(sendbuf));
            sprintf(sendbuf,"删除成功");
            send(fd,sendbuf,strlen(sendbuf),0);
            leap=1;
            saveclient();
            break;
        }
    }
    //本地删除了,对方列表也要删除
    if(leap==1)
    {
        p1=head->next;
        while(p1)
        {
            if(strcmp(p1->id,recvbuf)==0)
            {
                break;
            }
            p1=p1->next;
        }
        for(i=0;i<(p1->hys);i++)
        {
            if(strcmp(p1->hy[i],p->id)==0)
            {
                while(i<(p1->hys-1))
                {
                    strcpy(p1->hy[i],p1->hy[i+1]);
                    i++;
                }
                memset(p1->hy[i],0,sizeof(p1->hy[i]));
                p1->hys--;
                memset(sendbuf,0,sizeof(sendbuf));
                sprintf(sendbuf,"对方那也删除");
                send(fd,sendbuf,strlen(sendbuf),0);
                saveclient();
                break;
            }

        }
    }
    else
    {
        memset(sendbuf,0,sizeof(sendbuf));
        sprintf(sendbuf,"删除失败,您没有此好友");
        send(fd,sendbuf,strlen(sendbuf),0);
    }
}

//添加好友 
void add_friends(int fd,char id[20])
{
    cliMesg *p,*p1;
    int i;
    char sendbuf[1024]={0};
    char recvbuf[1024]={0};
    //找到自己的账户节点
    p=head->next;
    while(p)
    {
        if(strcmp(p->id,id)==0)
        {
            break;
        }
        p=p->next;
    }

    strcpy(sendbuf,"输入添加的好友手机号");
    send(fd,sendbuf,strlen(sendbuf),0);
    recv(fd,recvbuf,sizeof(recvbuf),0);
    memset(sendbuf,0,sizeof(sendbuf));
    strcpy(sendbuf,"消息已发送");
    send(fd,sendbuf,strlen(sendbuf),0);
    if(check_iscount(recvbuf)==0)
    {
	memset(sendbuf,0,sizeof(sendbuf));
	strcpy(sendbuf,"没有此账号");
	send(fd,sendbuf,strlen(sendbuf),0);
	return;
    }
    if(strcmp(recvbuf,p->id)==0)
    {
	memset(sendbuf,0,sizeof(sendbuf));
	strcpy(sendbuf,"不能添加自己为好友");
	send(fd,sendbuf,strlen(sendbuf),0);
	return ;
    }
    //查看自己好友列表里是否有该好友
    for(i=0;i<p->hys;i++)
    {
        if(strcmp(recvbuf,p->hy[i])==0)
        {
            memset(sendbuf,0,sizeof(sendbuf));
            strcpy(sendbuf,"此好友已添加");
            send(fd,sendbuf,strlen(sendbuf),0);
            return;
        }
    }
    //如果没有该好友,得向对方发送请求
    p1=head->next;
    time_t timep;
    while(p1)
    {
        if(strcmp(p1->id,recvbuf)==0)
        {
            friMesg *m,*m1;
            m=(friMesg *)malloc(sizeof(friMesg));
            m->type=1;
            strcpy(m->rid,recvbuf);   //收消息的人
            strcpy(m->sid,p->id);     //发消息的人
            memset(sendbuf,0,sizeof(sendbuf));
            time(&timep);
            sprintf(sendbuf,"%s\n%s想添加您为好友,y同意,n不同意",ctime(&timep),p->id);
            strcpy(m->mesg,sendbuf);
            m->next=NULL;
            m1=head1;
            while(m1->next)
            {
                m1=m1->next;
            }
            m1->next=m;
            urev_count++;
            //如果对方在线
            if(countOnline(p1->id)==1)
            {
                memset(sendbuf,0,sizeof(sendbuf));
                strcpy(sendbuf,"您有新消息,请输入open查看");
                send(p1->fd,sendbuf,strlen(sendbuf),0);
            }
            savefile();  //保存未发送的信息

        }
        p1=p1->next;
    }
}

char filename[1024]={0};
char fname[1024]={0};

//文件传输
void send_file(int fd,char id[20])
{
    cliMesg *p,*p1;
    int i;
    char sendbuf[1024]={0};
    char recvbuf[1024]={0};
    memset(filename,0,sizeof(filename));
    memset(fname,0,sizeof(fname));

    //找到自己的账户节点
    p=head->next;
    while(p)
    {
        if(strcmp(p->id,id)==0)
        {
            break;
        }
        p=p->next;
    }

    strcpy(sendbuf,"输入好友账户");
    send(fd,sendbuf,strlen(sendbuf),0);
    recv(fd,recvbuf,sizeof(recvbuf),0);

    if(isnum1(recvbuf)==0)
    {
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"输入格式不正确,应为11位数字!!!");
        send(fd,sendbuf,strlen(sendbuf),0);
        return;
    }

    if(check_iscount(recvbuf)==0)
    {
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"没有此账号");
        send(fd,sendbuf,strlen(sendbuf),0);
        return;
    }

    strcpy(sendbuf,"传输文件名(完整路径)  " );
    send(fd,sendbuf,strlen(sendbuf),0);
    recv(fd,filename,sizeof(recvbuf),0);
    // printf("filename=%s\n",filename);
    memset(sendbuf,0,sizeof(sendbuf));


    //printf("111\n");
    //printf("fname=%s\n",fname);



    int f=0;
    //查看自己好友列表里是否有该好友
    for(i=0;i<p->hys;i++)
    {
        if(strcmp(recvbuf,p->hy[i])==0)//找到
        {

            memset(sendbuf,0,sizeof(sendbuf));
            strcpy(sendbuf,"存在此好友\n");
            send(fd,sendbuf,strlen(sendbuf),0);
            f=1; break;
        }
    }
    if(i==p->hys&&f==0)
    {
        if(strcmp(recvbuf,p->id)==0) //自己
        {
            memset(sendbuf,0,sizeof(sendbuf));
            strcpy(sendbuf,"不能给自己发送文件");
            send(fd,sendbuf,strlen(sendbuf),0);
            return ;
        }
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"不存在此好友");
        send(fd,sendbuf,strlen(sendbuf),0);
        return ;
    }

    strcpy(sendbuf,"消息已发送");
    send(fd,sendbuf,strlen(sendbuf),0);

    //printf("dhgahga\n");
    //向对方发送请求
    p1=head->next;
    time_t timep;
    while(p1)
    {
        if(strcmp(p1->id,recvbuf)==0)
        {
            friMesg *m,*m1;
            m=(friMesg *)malloc(sizeof(friMesg));
            m->type=4;
            strcpy(m->rid,recvbuf);   //收文件的人
            strcpy(m->sid,p->id);     //发文件的人
            strcpy(m->fname,filename);

            char tmp[1024]={0};
            int pos;
            for(pos=strlen(filename)-1;filename[pos]!='/';pos--);
            strncpy(tmp,filename+pos+1,strlen(filename)-pos);

            memset(sendbuf,0,sizeof(sendbuf));
            time(&timep);
            sprintf(sendbuf,"%s\n%s正给您发文件%s,y接收,n拒绝",ctime(&timep),p->id,tmp);
            strcpy(m->mesg,sendbuf);
            m->next=NULL;
            m1=head1;
            while(m1->next)
            {
                m1=m1->next;
            }
            m1->next=m;
            urev_count++;
            //如果对方在线
            if(countOnline(p1->id)==1)
            {
                memset(sendbuf,0,sizeof(sendbuf));
                strcpy(sendbuf,"您有新消息,请输入open查看");
                send(p1->fd,sendbuf,strlen(sendbuf),0);
            }
            savefile();  //保存未查看的信息

        }
        p1=p1->next;
    }

}

//文件保存
void save_file(char id[1024],char f[1024])
{
    //printf("save_file :  %s\n",f);
    FILE *p1,*p2;
    p1=fopen(f,"r");
    if(p1==NULL)
    {
        printf("%s can not read!\n",f);
        return ;
    }

    int pos;
    //printf("222\n");
    for(pos=strlen(f)-1;f[pos]!='/';pos--);
    strncpy(fname,f+pos+1,strlen(f)-pos);

    //printf("read ok\n");
    char s_path[1024]={0};
    sprintf(s_path,"./%s/%s",id,fname);
    printf("%s\n",s_path);
    p2=fopen(s_path,"wb+");
    if(p2==NULL)
    {
        printf("%s can not open!\n",s_path);
        return ;
    }

    char buf[1024];
    int r_len;
    while((r_len=fread(buf,sizeof(char),1024,p1))>0)
    {
        printf("write ok\n");
        fwrite(buf,sizeof(char),r_len,p2);
    }

    fclose(p1);
    fclose(p2);
}

char a[100][20];   //存放聊天室人的id
int len=0;         //聊天室人数
//多人聊天
void multi_chat(int fd,char id[20])
{
    char sendbuf[1024]={0};
    char recvbuf[1024]={0};
    strcpy(sendbuf,"您已进入聊天室,输入quit退出,输入look查看当前人");
    send(fd,sendbuf,sizeof(sendbuf),0);
    strcpy(a[len],id);
    len++;
    int i;
    cliMesg *p;
    time_t timep,bt;
    time(&timep);
    printf("id为%s 用户进入群聊 %s",id,get_time());
    int bflag=0; //禁言消息
    while(1)
    {
        memset(recvbuf,0,sizeof(recvbuf));
        recv(fd,recvbuf,sizeof(recvbuf),0);
        //退出群聊室
        if(strcmp(recvbuf,"quit")==0)
        {
            for(i=0;i<len;i++)
            {
                if(strcmp(a[i],id)==0)
                {
                    while(i<len-1)
                    {
                        strcpy(a[i],a[i+1]);
                        i++;
                    }

                }
            }
            len--;
            for(i=0;i<len;i++)
            {
                p=head->next;
                while(p)
                {
                    if(strcmp(p->id,a[i])==0)
                    {
                        //向还在群里的人发送通知
                        memset(sendbuf,0,sizeof(sendbuf));
                        sprintf(sendbuf,"%s退出聊天室",id);
                        send(p->fd,sendbuf,strlen(sendbuf),0);
                        break;
                    }
                    p=p->next;
                }

            }
            return ;
        }
        //查看当前群里有多少人
        if(strcmp(recvbuf,"look")==0)
        {
            memset(sendbuf,0,sizeof(sendbuf));
            sprintf(sendbuf,"当前聊天室有%d人,他们是:\n",len);
            send(fd,sendbuf,strlen(sendbuf),0);
            for(i=0;i<len;i++)
            {
                p=head->next;
                while(p)
                {
                    if(strcmp(p->id,a[i])==0)
                    {
                        memset(sendbuf,0,sizeof(sendbuf));
                        sprintf(sendbuf,"昵称是%s 账户是%s admin=%d",p->name,p->id,p->admin);
                        send(fd,sendbuf,strlen(sendbuf),0);
                        break;
                    }
                    p=p->next;
                }
            }
            continue;
        }
        //printf("!!p12123123123\n");
        cliMesg *p1;
        p1=head->next;
        while(p1)  //匹配发消息用户
        {
            if(strcmp(p1->id,id)==0)
            {
                break;
            }
            p1=p1->next;
        }
        //printf("!!p11111->admin\n");
        //设置全员禁言
        if(strcmp(recvbuf,"total silence"))
        {

        }

        //设置单用户禁言
        if(strcmp(recvbuf,"silence+")==0)
        {

            if(p1->admin==1)//是管理员
            {
                memset(sendbuf,0,sizeof(sendbuf));
                strcpy(sendbuf,"输入禁言用户帐号");
                send(fd,sendbuf,strlen(sendbuf),0);

                memset(recvbuf,0,sizeof(sendbuf));
                recv(fd,recvbuf,sizeof(recvbuf),0);

                //printf("recvbuf=%s\n",recvbuf);

                int f=0;
                for(i=0;i<len;i++) //匹配禁言在群聊室用户
                {
                    p=head->next;
                    while(p)
                    {
                        if(strcmp(p->id,a[i])==0 &&strcmp(p->id,recvbuf)==0)
                        {
                            f=1;break;
                        }
                        p=p->next;
                    }
                    if(f) break;
                }

                //printf("p->admin=%d\n",p->admin);
                //printf("p->id=%s\n",p->id);
                if(p->admin==1)  //同级不能禁言对方
                {
                    memset(sendbuf,0,sizeof(sendbuf));
                    strcpy(sendbuf,"同等级不能禁言");
                    send(fd,sendbuf,strlen(sendbuf),0);
                    continue;
                }
                else //被禁言
                {

                    memset(sendbuf,0,sizeof(sendbuf));
                    strcpy(sendbuf,"禁言时长[单位/分]");
                    send(fd,sendbuf,strlen(sendbuf),0);

                    memset(recvbuf,0,sizeof(recvbuf));
                    recv(fd,recvbuf,strlen(sendbuf),0);
//                    printf("sendbuf==%s\n",sendbuf);
//                    printf("recvbuf==%s\n",recvbuf);
                    int tmp;
                    sscanf(recvbuf,"%d",&tmp);
                    printf("tmp==%d\n",tmp);
                    //tmp*=60; //时间转换


                    bt=time(NULL);
                    //printf("bt=%ld\n",bt);
                    //printf("p->admin=%d\n",p->admin);
                    p->admin=-1;
                    //p->status.st=bt;
                    printf("st=%ld\n",bt);

                    //p->status.ed=(bt+tmp*60);
                    printf("ed=%ld\n",bt+tmp*60);
                    p->ed_time=bt+tmp*60;
                    printf("已禁言用户%s\n",p->id);

                    memset(sendbuf,0,sizeof(sendbuf));
                    strcpy(sendbuf,"禁言成功");
                    send(fd,sendbuf,strlen(sendbuf),0);

                    memset(sendbuf,0,sizeof(sendbuf));
                    strcpy(sendbuf,"您已被禁言,无法与群友交流!");
                    send(p->fd,sendbuf,strlen(sendbuf),0);
                    saveclient();
                    //continue;

                    memset(sendbuf,0,sizeof(sendbuf));
                    sprintf(sendbuf,"\t%s\t[%s用户被你禁言%d分钟]",get_time(),p->name,tmp);
                    strcpy(recvbuf,sendbuf);
                    send(p1->fd,sendbuf,strlen(sendbuf),0);

                    memset(sendbuf,0,sizeof(sendbuf));
                    sprintf(sendbuf,"\t%s\t[%s用户被%s禁言%d分钟]",get_time(),p->name,p1->name,tmp);
                    strcpy(recvbuf,sendbuf);
                    //send(p->fd,sendbuf,strlen(sendbuf),0);
                    bflag=1;
                }
            }
            else  //不是管理员
            {
                memset(sendbuf,0,sizeof(sendbuf));
                strcpy(sendbuf,"普通用户无禁言权限");
                send(fd,sendbuf,strlen(sendbuf),0);
                continue;
            }
        }

        //printf("!!p->admin=%d\n",p->admin);

        if(p1->admin==-1) //发消息用户处于禁言状态
        {
            printf("now bt=%ld\n",time(NULL));
            if((bt=time(NULL))<p1->ed_time)
            {
                memset(sendbuf,0,sizeof(sendbuf));
                strcpy(sendbuf,"处于禁言状态");
                send(p1->fd,sendbuf,strlen(sendbuf),0);
                continue ;
            }
            else
            {
                p1->admin=0;
                memset(sendbuf,0,sizeof(sendbuf));
                strcpy(sendbuf,"解禁");
                send(p1->fd,sendbuf,strlen(sendbuf),0);
                saveclient();
            }
        }


        //printf("bflag=%d\n",bflag);
        //printf("recvbuf=%s\n",recvbuf);
        if(bflag) //群发禁言消息
        {
            for(i=0;i<len;i++)
            {
                p=head->next;
                while(p)
                {
                    if(strcmp(p->id,a[i])==0&&strcmp(p->id,id)!=0)
                    {
                        //printf("id====%s\n",p->id);
                        //memset(sendbuf,0,sizeof(sendbuf));
                        send(p->fd,recvbuf,strlen(recvbuf),0);
                        break;
                    }
                    p=p->next;
                }

            }
            bflag=0;
            continue;
        }

        //群发普通消息
        for(i=0;i<len;i++)
        {
            p=head->next;
            while(p)
            {
                if(strcmp(p->id,a[i])==0&&strcmp(p->id,id)!=0)
                {               
                    memset(sendbuf,0,sizeof(sendbuf));
                    sprintf(sendbuf,"%s  %s   %s",p1->name,get_time(),recvbuf);
                    send(p->fd,sendbuf,strlen(sendbuf),0);
                    break;
                }
                p=p->next;
            }

        }
    }

}

//修改个人信息
void modify(int fd,char id[20])
{
    cliMesg *p,*p1;
    int i;
    char sendbuf[1024]={0};
    char recvbuf[1024]={0};
    p=head->next;
    while(1)
    {
        if(strcmp(p->id,id)==0)
        {
            break;
        }
        p=p->next;
    }
    sprintf(sendbuf,"我的昵称:%s\n我的账户:%s\n我的密码:%s\n我的身份:%s\n",p->name,p->id,p->passwd,p->admin==1?"管理员":"普通用户");
    send(fd,sendbuf,strlen(sendbuf),0);
    memset(sendbuf,0,sizeof(sendbuf));
    strcpy(sendbuf,"\t\t*********功能选项************\n\t\t\t1.修改昵称\n\n\t\t\t2.修改密码\n\n\t\t\t3.权限变更\n\n\t\t\t0.退出\n\t\t*****************************");
    send(fd,sendbuf,strlen(sendbuf),0);
    recv(fd,recvbuf,sizeof(recvbuf),0);
    if(strcmp(recvbuf,"1")==0)
    {
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"请输入新的昵称");
        send(fd,sendbuf,strlen(sendbuf),0);
        memset(recvbuf,0,sizeof(recvbuf));
        recv(fd,recvbuf,sizeof(recvbuf),0);
        strcpy(p->name,recvbuf);

        saveclient();
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"昵称修改成功");
        send(fd,sendbuf,strlen(sendbuf),0);
        return;
    }
    else if(strcmp(recvbuf,"2")==0)		//输入2修改密码
    {
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"请输入新的密码");
        send(fd,sendbuf,strlen(sendbuf),0);
        memset(recvbuf,0,sizeof(recvbuf));
        recv(fd,recvbuf,sizeof(recvbuf),0);
        strcpy(p->passwd,recvbuf);

        saveclient();
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"密码修改成功");
        send(fd,sendbuf,strlen(sendbuf),0);
        return ;
    }
    else if(strcmp(recvbuf,"3")==0)
    {
        if(p->admin==1)
        {
            memset(sendbuf,0,sizeof(sendbuf));
            strcpy(sendbuf,"已是最高权限,无需变更");
            send(fd,sendbuf,strlen(sendbuf),0);
            return;
        }

        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"请输入授权码");
        send(fd,sendbuf,strlen(sendbuf),0);
        memset(recvbuf,0,sizeof(recvbuf));
        recv(fd,recvbuf,sizeof(recvbuf),0);

        if(strcmp(recvbuf,"linux")!=0)
        {
            memset(sendbuf,0,sizeof(sendbuf));
            strcpy(sendbuf,"授权码有误!!");
            send(fd,sendbuf,strlen(sendbuf),0);
            return ;
        }

        p->admin=1;
        saveclient();
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"授权成功, 已变更为管理员");
        send(fd,sendbuf,strlen(sendbuf),0);
        return ;
    }
    else if(strcmp(recvbuf,"0")==0)
    {
        return;
    }
    else
    {
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"输入非法");
        send(fd,sendbuf,strlen(sendbuf),0);
    }
}

//双人聊天
void double_chat(int fd,char id[20])
{
    int flags=1;
    cliMesg *p;

    p=head->next;
    time_t timep;
    time(&timep);
    char recvbuf[1024]={0};
    char sendbuf[1024]={0};
    char str[1024]={0};
    int ret=0;
    strcpy(sendbuf,"输入你想聊天的好友账户");
    send(fd,sendbuf,strlen(sendbuf),0);

    recv(fd,recvbuf,sizeof(recvbuf),0);
    strcpy(str,recvbuf);

    if(isnum1(str)==0){
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"输入格式不正确,应为11位数字!!!");
        send(fd,sendbuf,strlen(sendbuf),0);
        return;
    }

    //查找账户是否存在
    if(check_iscount(str)==0)
    {
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"此号码不存在");
        send(fd,sendbuf,strlen(sendbuf),0);
        return;
    }

    if(strcmp(recvbuf,id)==0)		//不能与自己聊天
    {
        memset(sendbuf,0,1024);
        strcpy(sendbuf,"不能与自己聊天");
        send(fd,sendbuf,strlen(sendbuf),0);
        return;
    }

    cliMesg *p1;
    p1=head->next;
    while(p1)
    {
        if(strcmp(p1->id,str)==0)
        {
            break;
        }
        p1=p1->next;
    }
    /*
    memset(sendbuf,0,1024);
	sprintf(sendbuf,"flags=%d",p1->chatroom);
    send(fd,sendbuf,strlen(sendbuf),0);
	*/
    if(p1->chatroom==0)
    {

	while(p)
	{
            if(strcmp(p->id,id)==0)
            {
                break;
            }
            p=p->next;
	}

        if(p->hys==0)
        {
            memset(sendbuf,0,sizeof(sendbuf));
            strcpy(sendbuf,"没有此好友");
            send(fd,sendbuf,strlen(sendbuf),0);
            return;
        }

        /*cliMesg *p1;
	p1=head->next;
	while(p1)
	{
            if(strcmp(p1->id,recvbuf)==0)
            {
                break;
            }
            p1=p1->next;
        }*/


	
        if(p1->fd==-5)			//判断好友在不在线和有没有打开聊天窗口
	{
            memset(sendbuf,0,1024);
            strcpy(sendbuf,"好友不在线");
            send(fd,sendbuf,1024,0);
            return;
	}

        int i;
        int num=p->hys;
	for(i=0;i<num;i++)
	{
            if(strcmp(p->hy[i],str)==0)
            {
                flags=0;
                memset(sendbuf,0,1024);
                //p->chatroom=1;
                p1->chatroom=1;
	        strcpy(sendbuf,"连接成功");
	        send(fd,sendbuf,strlen(sendbuf),0);

            }

	}
        if(flags==1)
	{
            memset(sendbuf,0,1024);
	    strcpy(sendbuf,"请先添加该好友");
	    send(fd,sendbuf,strlen(sendbuf),0);
            return;
	}

	//进入聊天室
        while(1)					//进入聊天,输入quit退出
        {
            memset(recvbuf,0,1024);
            memset(sendbuf,0,1024);
            recv(fd,recvbuf,1024,0);
            if(strcmp(recvbuf,"quit")==0)
            {
                p->chatroom=0;
                memset(sendbuf,0,1024);
                if(p1->chatroom!=0)
                    sprintf(sendbuf,"%s 已退出,请您输入quit退出",id);
                send(p1->fd,sendbuf,1024,0);
                break;
            }
            memset(sendbuf,0,1024);
            sprintf(sendbuf,"%s  %s   %s",p->name,get_time(),recvbuf);
            savefile2(sendbuf,id);//保存聊天记录
            savefile2(sendbuf,p1->id);
            send(p1->fd,sendbuf,1024,0);
            memset(recvbuf,0,1024);
            memset(sendbuf,0,1024);

            // recv(p1->fd,recvbuf,1024,0);
            // sprintf(sendbuf,"%s$$$$$%s say:%s",ctime(&timep),p1->id,recvbuf);
            // savefile2(sendbuf,id);//保存聊天记录
            //savefile2(sendbuf,p1->id);
            //send(fd,sendbuf,1024,0);
	}	
    }else
    {
        memset(sendbuf,0,sizeof(sendbuf));
        strcpy(sendbuf,"该好友正在聊天");
        send(fd,sendbuf,strlen(sendbuf),0);
    }
}

//好友管理
void manage_friends(int fd,char id[20])
{
    char sendbuf[1024]={0};
    char recvbuf[1024]={0};
    strcpy(sendbuf,"\n\t\t*********功能选项***********\n\n\t\t1.好友列表\t2.查找好友\n\n\t\t3.删除好友\t4.添加好友\n\n\t\t5.文件传输\t0.退出\n\t\t****************************\n");
    send(fd,sendbuf,strlen(sendbuf),0);
    recv(fd,recvbuf,sizeof(recvbuf),0);
    if(strcmp(recvbuf,"1")==0)
    {
        //好友列表
        list_friends(fd,id);
    }
    if(strcmp(recvbuf,"2")==0)
    {
        find_friends(fd,id);
    }
    /*
	if(strcmp(recvbuf,"2")==0)
	{
		display_friends(fd,id);
	}
	*/
    if(strcmp(recvbuf,"3")==0)
    {
        del_friends(fd,id);
    }
    if(strcmp(recvbuf,"4")==0)
    {
        //添加朋友消息
        add_friends(fd,id);
    }
    if(strcmp(recvbuf,"5")==0)
    {
        //文件传输
        send_file(fd,id);
    }

    if(strcmp(recvbuf,"0")==0)
    {
        return;
    }
}

//在线从服务器查看聊天记录
void jilu(int fd,char id[20])
{
    int fp;      //文件标识符
    char str[1024];
    sprintf(str,"./%s/%s.txt",id,id); //打开相应人的聊天记录文本文件
    fp=open(str,O_RDONLY);    //只读方式打开
    if(fp==-1)
    {
        memset(str,0,1024);
        strcpy(str,"您没有聊天记录");
        send(fd,str,strlen(str),0);
        return;
    }
    int ret;
    memset(str,0,1024);
    while(ret=read(fp,str,1024))	//ret读的长度,为0退出while
    {
        write(fd,str,strlen(str));	//读出来发送给客户端
        memset(str,0,1024);
    }
    close(fp);
}

//下载聊天记录
void load(int fd,char id[20])
{
    int fp;
    char sendbuf[1024];
    char recvbuf[1024]={0};
    char str[1024]={0};
    sprintf(sendbuf,"./%s/%s.txt",id,id);
    fp=open(sendbuf,O_RDONLY);
    if(fp==-1)							//先判断有没有聊天记录文件
    {
        memset(sendbuf,0,1024);
        strcpy(sendbuf,"您没有聊天记录");
        send(fd,sendbuf,strlen(sendbuf),0);
        return;
    }

    int ret;
    memset(sendbuf,0,1024);
    strcpy(sendbuf,"xiazai");
    send(fd,sendbuf,strlen(sendbuf),0);

    recv(fd,recvbuf,sizeof(recvbuf),0);

    memset(sendbuf,0,1024);
    sprintf(sendbuf,"%s",id);
    send(fd,sendbuf,strlen(sendbuf),0);

    memset(sendbuf,0,1024);
    while(ret=read(fp,sendbuf,1024))
    {
        send(fd,&ret,sizeof(int),0);		//先发送内容字节数,再发送内容
        send(fd,sendbuf,ret,0);
        memset(sendbuf,0,1024);
    }
    memset(sendbuf,0,1024);
    strcpy(sendbuf,"endend");
    ret = strlen(sendbuf);						//结束后发送消息告诉客户端发送完毕

    send(fd,&ret,sizeof(int),0);
    send(fd,sendbuf,strlen(sendbuf),0);
    //memset(sendbuf,0,1024);
    // sprintf(str,"    存储在./%s.txt中",id);
    //strcpy(sendbuf,str);
    //send(fd,sendbuf,strlen(sendbuf),0);
    close(fp);
}

//处理客户端的信息
void *handlerClient(void *arg)
{
    int fd=*(int *)arg;
    char recvbuf[1024]={0};
    char recvbuf1[1024]={0};
    char  sendbuf[1024]={0};
    int ret;

    //接受数据
    if((ret=recv(fd,recvbuf,sizeof(recvbuf),0))==-1)
    {
        perror("recv");
        return NULL;
    }

    printf("client say:%s\n",recvbuf);

    while(1)
    {
        //system("clear");
        memset(sendbuf,0,sizeof(sendbuf));
        //登录界面
        strcpy(sendbuf,"\n\t\t*****欢迎使用网络聊天系统*****\n\t\t\t菜单选项\n\n\t\t\t1.登录\n\n\t\t\t2.注册\n\n\t\t\t0.退出\n\t\t******************************\n");
        send(fd,sendbuf,strlen(sendbuf),0);
        memset(recvbuf,0,sizeof(recvbuf));
        memset(recvbuf1,0,sizeof(recvbuf1));
        //接受客户端的数据
        if(recv(fd,recvbuf,sizeof(recvbuf),0)==-1)
        {
            perror("recv");
            return NULL;
        }
        if(strcmp(recvbuf,"1")==0)  //登录
        {
            memset(sendbuf,0,sizeof(sendbuf));
            strcpy(sendbuf,"请输入账号");
            if(send(fd,sendbuf,strlen(sendbuf),0)==-1)
            {
                perror("send");
                return NULL;
            }

            if(recv(fd,recvbuf,sizeof(recvbuf),0)==-1)
            {
                perror("recv");
                return NULL;
            }

            memset(sendbuf,0,sizeof(sendbuf));
            strcpy(sendbuf,"请输入密码");
            if(send(fd,sendbuf,strlen(sendbuf),0)==-1)
            {
                perror("send");
                return NULL;
            }

            //struct termios settings;
            //char tmppwd[50];
            //tcgetattr(fileno(stdin),&settings);
            //settings.c_lflag&=~ECHO;
            // tcsetattr(fileno(stdin),TCSANOW,&settings);
            // fgets(tmppwd,50,stdin);
            // strcpy(recvbuf1,tmppwd);

            if(recv(fd,recvbuf1,sizeof(recvbuf1),0)==-1)
            {
                perror("recv");
                return NULL;
            }
            //else{
            //   printf("@recvbuf1=%s",recvbuf1);
            // }
            //匹配账号密码是否存在且正确
            //printf("!!recvbuf=%s\n",recvbuf);

            if(check_iscount(recvbuf)==0 ||check_countpasswd(recvbuf,recvbuf1)==0)
            {
                //printf("recvbuf1=%s",recvbuf1);
                //printf("recvbuf=%s\n",recvbuf);
                memset(sendbuf,0,sizeof(sendbuf));
                strcpy(sendbuf,"输入账号或密码不正确");
                send(fd,sendbuf,strlen(sendbuf),0);
                continue;
            }
            //判断该账号是否在线
            else if(countOnline(recvbuf)==1)
            {
                memset(sendbuf,0,sizeof(sendbuf));
                strcpy(sendbuf,"此账号已在线");
                send(fd,sendbuf,strlen(sendbuf),0);
                continue;
            }
            else
            {
                strcpy(recvbuf1,recvbuf);
                memset(sendbuf,0,sizeof(sendbuf));
                strcpy(sendbuf,"登录成功     ");

                cliMesg *p;
                p=head;
                char str[50];
                while(p->next)
                {
                    if((strcmp((p->next)->id,recvbuf1)==0))
                    {
                        (p->next)->online=1;
                        (p->next)->fd=fd;
                        (p->next)->chatroom=0;
                        strcpy(str,(p->next)->name);
                    }
                    p=p->next;

                }
                send(fd,sendbuf,strlen(sendbuf),0);
                memset(sendbuf,0,sizeof(sendbuf));
                sprintf(sendbuf,"\n\n%s , 你好!  ",str);
                send(fd,sendbuf,strlen(sendbuf),0);

                //登录时判断是否有新消息
                friMesg *p9;
                p9=head1;
                int len=0;
                while(p9)
                {
                    if(strcmp(p9->rid,recvbuf1)==0)
                    {
                        len=1;
                        memset(sendbuf,0,sizeof(sendbuf));
                        strcpy(sendbuf,"您有新消息,请输入open查看\n");
                        send(fd,sendbuf,strlen(sendbuf),0);
                        break;
                    }
                    p9=p9->next;
                }


                //主界面
                memset(recvbuf,0,sizeof(recvbuf));
                while(1)
                {
                    memset(sendbuf,0,sizeof(sendbuf));
                    strcpy(sendbuf,"\n\n\t\t*********菜单选项************\n\t\t1.好友管理\t2.账户管理\n\n\t\t3.群聊世界\t4.私聊世界\n\n\t\t5.查看记录\t6.下载记录\n\n\t\t\t  0.退出\n\t\t*****************************\n");
                    send(fd,sendbuf,strlen(sendbuf),0);
                    memset(recvbuf,0,sizeof(recvbuf));					
                    if(recv(fd,recvbuf,sizeof(recvbuf),0)==-1)
                    {
                        perror("recv");
                        return NULL;
                    }
                    //printf("buf=%s",recvbuf);

                    //对主界面进行分析
                    if(strcmp(recvbuf,"1")==0)
                    {
                        //好友管理
                        manage_friends(fd,recvbuf1);
                    }
                    if(strcmp(recvbuf,"2")==0)
                    {
                        //账户管理
                        modify(fd,recvbuf1);
                    }
                    if(strcmp(recvbuf,"3")==0)
                    {
                        //群聊
                        multi_chat(fd,recvbuf1);
                    }
                    if(strcmp(recvbuf,"4")==0)
                    {
                        //私聊
                        double_chat(fd,recvbuf1);
                    }
                    if(strcmp(recvbuf,"5")==0)
                    {
                        jilu(fd,recvbuf1);
                    }
                    if(strcmp(recvbuf,"6")==0)
                    {
                        load(fd,recvbuf1);
                    }
                    //打开信息
                    if(strcmp(recvbuf,"open")==0)
                    {
                        friMesg *m;
                        int flags=0;
                        m=head1->next;
                        printf("urev_count=%d\n",urev_count);
                        while(m)
                        {
                            if(strcmp(m->rid,recvbuf1)==0)
                            {
                                flags=1;
                                if(m->type==1)    //1为好友请求消息
                                {
                                    memset(sendbuf,0,sizeof(sendbuf));
                                    strcpy(sendbuf,m->mesg);
                                    send(fd,sendbuf,strlen(sendbuf),0);
                                    //有两种情况 同意或不同意
                                    while(1)
                                    {
                                        memset(recvbuf,0,sizeof(recvbuf));
                                        recv(fd,recvbuf,sizeof(recvbuf),0);

                                        if(strcmp(recvbuf,"y")==0)
                                        {
                                            m->type=3;     //好友请求回复
                                            strcpy(m->rid,m->sid);
                                            strcpy(m->sid,recvbuf1);

                                            memset(sendbuf,0,sizeof(sendbuf));
                                            sprintf(sendbuf,"%s已同意添加,添加成功",recvbuf1);
                                            strcpy(m->mesg,sendbuf);

                                            cliMesg *p1;
                                            p=head->next;
                                            p1=head->next;
                                            //收消息的人
                                            while(p)
                                            {
                                                if(strcmp(p->id,m->rid)==0)
                                                {
                                                    break;
                                                }
                                                p=p->next;
                                            }
                                            //发消息的人
                                            while(p1)
                                            {
                                                if(strcmp(p1->id,m->sid)==0)
                                                {
                                                    break;
                                                }
                                                p1=p1->next;
                                            }
                                            //同意往好友列表添信息
                                            strcpy(p->hy[p->hys],p1->id);
                                            p->hys++;
                                            strcpy(p1->hy[p1->hys],p->id);
                                            p1->hys++;
                                            if(countOnline(m->rid)==1)
                                            {
                                                memset(sendbuf,0,sizeof(sendbuf));
                                                strcpy(sendbuf,"您有新消息,请输入open查看");
                                                send(p->fd,sendbuf,strlen(sendbuf),0);
                                            }
                                            saveclient();
                                            savefile();
                                            break;
                                        }else if(strcmp(recvbuf,"n")==0)
                                        {
                                            cliMesg *p;
                                            p=head->next;
                                            while(p)
                                            {
                                                if(strcmp(p->id,m->sid)==0)
                                                {
                                                    break;
                                                }
                                                p=p->next;												
                                            }
                                            m->type=3;    //发消息
                                            strcpy(m->rid,m->sid);
                                            strcpy(m->sid,recvbuf1);
                                            memset(sendbuf,0,sizeof(sendbuf));
                                            sprintf(sendbuf,"%s已拒绝添加请求,添加失败",recvbuf1);
                                            strcpy(m->mesg,sendbuf);
                                            if(countOnline(m->rid)==1)
                                            {
                                                memset(sendbuf,0,sizeof(sendbuf));
                                                strcpy(sendbuf,"您有新消息,请输入open查看");
                                                send(p->fd,sendbuf,strlen(sendbuf),0);
                                            }
                                            savefile();
                                            break;

                                        }

                                    }
                                }
                                else if(m->type==2)  //好友消息
                                {

                                }
                                else if(m->type==3)//好友请求回复
                                {
                                    flags=1;
                                    memset(sendbuf,0,sizeof(sendbuf));
                                    strcpy(sendbuf,m->mesg);
                                    send(fd,sendbuf,strlen(sendbuf),0);

                                    friMesg *m1,*m2;
                                    m1=head1;
                                    while(m1->next)
                                    {
                                        if(strcmp(m1->next->rid,recvbuf1)==0)
                                        {
                                            m2=m1->next;
                                            m1->next=m2->next;
                                            free(m2);
                                            break;
                                        }
                                        m1=m1->next;
                                    }
                                    urev_count--;
                                    savefile();

                                    if(m==NULL);
                                    break;
                                }
                                else if(m->type==4)//好友文件传输请求
                                {
                                    memset(sendbuf,0,sizeof(sendbuf));
                                    strcpy(sendbuf,m->mesg);
                                    send(fd,sendbuf,strlen(sendbuf),0);
                                    //有两种情况 接收或拒绝
                                    while(1)
                                    {
                                        memset(recvbuf,0,sizeof(recvbuf));
                                        recv(fd,recvbuf,sizeof(recvbuf),0);

                                        if(strcmp(recvbuf,"y")==0)
                                        {
                                            memset(sendbuf,0,sizeof(sendbuf));
                                            strcpy(sendbuf,m->fname);
                                            send(fd,sendbuf,strlen(sendbuf),0);
                                            save_file(recvbuf1,m->fname);

                                            m->type=5; //回复
                                            strcpy(m->rid,m->sid);
                                            strcpy(m->sid,recvbuf1);



                                            memset(sendbuf,0,sizeof(sendbuf));
                                            sprintf(sendbuf,"%s已同意接收文件",recvbuf1);
                                            strcpy(m->mesg,sendbuf);

                                            cliMesg *p1;
                                            p=head->next;
                                            p1=head->next;
                                            //收文件的人
                                            while(p)
                                            {
                                                if(strcmp(p->id,m->rid)==0)
                                                {
                                                    break;
                                                }
                                                p=p->next;
                                            }



                                            //发文件的人
                                            while(p1)
                                            {
                                                if(strcmp(p1->id,m->sid)==0)
                                                {
                                                    break;
                                                }
                                                p1=p1->next;
                                            }
                                            memset(sendbuf,0,sizeof(sendbuf));
                                            sprintf(sendbuf,"文件已存储在./%s/%s\n",p1->id,fname);
                                            //strcpy(sendbuf,"文件已存储");
                                            send(p1->fd,sendbuf,strlen(sendbuf),0);

                                            if(countOnline(m->rid)==1)
                                            {
                                                memset(sendbuf,0,sizeof(sendbuf));
                                                strcpy(sendbuf,"您有新消息,请输入open查看");
                                                send(p->fd,sendbuf,strlen(sendbuf),0);
                                            }
                                            saveclient();
                                            savefile();
                                            break;

                                        }
                                        else if(strcmp(recvbuf,"n")==0)
                                        {
                                            cliMesg *p;
                                            p=head->next;
                                            while(p)
                                            {
                                                if(strcmp(p->id,m->sid)==0)
                                                {
                                                    break;
                                                }
                                                p=p->next;
                                            }
                                            m->type=5;    //发消息
                                            strcpy(m->rid,m->sid);
                                            strcpy(m->sid,recvbuf1);
                                            memset(sendbuf,0,sizeof(sendbuf));
                                            sprintf(sendbuf,"%s已拒绝接收文件",recvbuf1);
                                            strcpy(m->mesg,sendbuf);
                                            if(countOnline(m->rid)==1)
                                            {
                                                memset(sendbuf,0,sizeof(sendbuf));
                                                strcpy(sendbuf,"您有新消息,请输入open查看");
                                                send(p->fd,sendbuf,strlen(sendbuf),0);
                                            }
                                            savefile();
                                            break;
                                        }
                                    }
                                }
                                else if(m->type==5)//文件请求回复
                                {
                                    flags=1;
                                    memset(sendbuf,0,sizeof(sendbuf));
                                    strcpy(sendbuf,m->mesg);
                                    send(fd,sendbuf,strlen(sendbuf),0);

                                    friMesg *m1,*m2;
                                    m1=head1;
                                    while(m1->next)
                                    {
                                        if(strcmp(m1->next->rid,recvbuf1)==0)
                                        {
                                            m2=m1->next;
                                            m1->next=m2->next;
                                            free(m2);
                                            break;
                                        }
                                        m1=m1->next;
                                    }
                                    urev_count--;
                                    savefile();

                                    if(m==NULL);
                                    break;
                                }
                            }
                            if(m==NULL)
                            {
                                break;
                            }
                            m=m->next;
                        }

                    }
                    //退出
                    if(strcmp(recvbuf,"0")==0)
                    {

                        p=head;
                        while(p->next)
                        {
                            if(strcmp(p->next->id,recvbuf1)==0)
                            {
                                p->next->online=0;
                                p->next->fd=-5;
                                p->next->chatroom=0;
                                break;
                            }
                            p=p->next;
                        }
                        break;
                    }

                }
            }

        }
        else if(strcmp(recvbuf,"2")==0)
        {
            //注册添加账户
            add(fd);
        }
        else if(strcmp(recvbuf,"0")==0)
        {
            memset(sendbuf,0,sizeof(sendbuf));
            strcpy(sendbuf,"欢迎下次再来");
            send(fd,sendbuf,strlen(sendbuf),0);
            printf("client say:bye bye\n");

            break;
        }
        else
        {
            continue;
        }
    }
    close(fd);
}

//判断客户端是否依旧在线
void * judgeClient(void)
{
    cliMesg* p;
    char fa[1024];
    p=head;

    //判断是否断开连接 ,  如果断开将此账号置为不在线状态,监听套接字-5
    while(1)
    {
        p=head->next;
        while(p)
        {
            if(p->online==1)  //在线
            {
                struct tcp_info info;
                int len=sizeof(info);

                getsockopt(p->fd,IPPROTO_TCP,TCP_INFO,&info,(socklen_t*)&len);

                if((info.tcpi_state!=TCP_ESTABLISHED)) //已断开建立
                {
                    p->online=0;
                    p->fd=-5;
                }
            }
            p=p->next;
        }
    }

}

//主函数建立连接
int main()
{
    int sockfd=0,confd=0;    //定义并初始化
    int chlid=0;
    int ret=0;
    int len=sizeof(struct sockaddr);

    struct sockaddr_in myaddr;
    struct sockaddr_in otheraddr;
    memset(&myaddr,0,len);
    memset(&otheraddr,0,len);

    sockfd = socket(AF_INET, SOCK_STREAM,0);
    
    //初始化结构体
    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(3333);
    myaddr.sin_addr.s_addr=htonl(INADDR_ANY);//自动获取本机ip地址


    int reuse = 1;
    //重用socket
    //如果已处在established状态下的socket调用closesocket,一般不会立即关闭而经历time_wait过成后继续重用socket
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
    {
        perror("setsockopt error\n");
        return -1;
    }

    //绑定套接字
    if(bind(sockfd,(struct sockaddr*)&myaddr,len)==-1)
    {
        perror("bind");
        return -1;
    }

    //开始侦听
    if((listen(sockfd,10))==-1)
    {
        perror("listen");
        return -1;
    }
    printf("server waitting......\n");

    //创建线程
    pthread_t id1,id2;

    head=create_count();        //创建账号信息的头结点
    head1=create_buffmsg();    //创建缓存信息的头结点

    //接收客户端请求,   创建线程
    while(1)
    {
        //接受客户端信息
        if((confd=accept(sockfd,(struct sockaddr *)&otheraddr,&len))==-1)
        {
            perror("accept");
            return -1;
        }
        //输出客户端的编号 、ip和端口
        printf("client fd=%d server fd=%d\n",confd,sockfd);
        printf("client ip=%s port=%d\n",inet_ntoa(otheraddr.sin_addr),ntohs(otheraddr.sin_port));

        //处理客户端
        pthread_create(&id1,NULL,handlerClient,&confd);

        //判断客户端是否在线
        pthread_create(&id2,NULL,(void *)judgeClient,&confd);

        pthread_detach(id1);//线程结束后资源系统自动回收
        pthread_detach(id2);
    }

    //关闭网络连接
    close(sockfd);

    return 0;
}

client.c

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

//接受服务器的信息
void *recvMessage(void *arg)
{
    int fd=*(int *)arg;
    int ret=0;
    char recvbuf[1024];
    char sendbuf[1024];
    char str[1024];

    while(1)
    {
        memset(recvbuf,0,sizeof(recvbuf));
        memset(str,0,sizeof(str));
        if((ret=recv(fd,recvbuf,sizeof(recvbuf),0))==-1)
        {
            return NULL;
        }
        //printf("hhhh:%s\n",recvbuf);
        if(strcmp(recvbuf,"xiazai")==0)
        {
            strcpy(sendbuf,"enter xiazai");
            send(fd,sendbuf,strlen(sendbuf),0);
            //printf("!!!!\n");
            memset(recvbuf,0,sizeof(recvbuf));
            recv(fd,recvbuf,sizeof(recvbuf),0);
            //printf("recvbuf:%s\n",recvbuf);
            sprintf(str,"rm -f ./%s/mesg.txt",recvbuf);
            //printf("str:%s\n",str);
            system(str);//确保本地没有此文件
            int fp;		//文件标识符
            sprintf(str,"./%s/mesg.txt",recvbuf);
            //printf("!!!str:%s\n",str);
            fp=open(str,O_WRONLY|O_CREAT|O_TRUNC,0666);
            memset(recvbuf,0,1024);
            //接收数据,如果“endend”表示接收结束
            while(1)
            {
                recv(fd,&ret,sizeof(int),0);
                recv(fd,recvbuf,ret,0);
                if(strncmp(recvbuf,"endend",6)==0)
                {
                    break;
                }
                write(fp,recvbuf,ret);

            }
            close(fp);
            continue;

        }
        if(strcmp(recvbuf,"连接成功")==0)
        {
            system("clear");
        }
        puts(recvbuf);
        if(ret==0)
        {
            exit(0);
        }
    }

}

//给服务器发消息
void *sendMessage(void *arg)
{
    //发送
    int fd=*(int *)arg;
    char sendmsg[1024];
    while(1)
    {
        memset(sendmsg,0,sizeof(sendmsg));
        scanf("%s",sendmsg);
        if(send(fd,sendmsg,strlen(sendmsg),0)==-1)
        {
            return NULL;
        }

    }
}

//主函数建立连接
int main(int argc,char *argv[])
{
    int sockfd=0;
    int ret=0;
    int len=sizeof(struct sockaddr);

    struct hostent *host;
    struct sockaddr_in otheraddr;
    memset(&otheraddr,0,len);

    if(argc!=2)
    {
        fprintf(stderr,"Usage:%s hostname \a\n",argv[0]);
        exit(1);
    }

    //使用hostname查询host 名字
    if((host=gethostbyname(argv[1]))==NULL)
    {
        perror("Gethostname");
        return -1;
    }


    //tcp套接字连接
    if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
    {
        perror("sockfd");
        return -1;
    }

    //初始化结构体,把服务器ip地址和端口号
    otheraddr.sin_family = AF_INET;
    otheraddr.sin_port = htons(3333);
    otheraddr.sin_addr=*((struct in_addr *)host->h_addr);

    //连接服务器
    if(connect(sockfd,(struct sockaddr*)&otheraddr,len)==-1)
    {
        perror("connect");
        return -1;
    }
    printf("connect sucess……\n");
    //printf("connect success...client fd=%d\n",sockfd);
    printf("client ip=%s,port=%d\n",inet_ntoa(otheraddr.sin_addr),ntohs(otheraddr.sin_port));



    char recvbuf[1024]={0};
    char sendbuf[1024]={0};
    
    //给服务器 发送信息
    strcpy(sendbuf,"client connect success");
    if(send(sockfd,sendbuf,strlen(sendbuf),0)==-1)
    {
        perror("send");
        return -1;
    }
    if(recv(sockfd,recvbuf,sizeof(recvbuf),0)==-1)
    {
        perror("recv");
        return -1;
    }
    printf("server say:%s\n",recvbuf);

    //创建收发线程
    pthread_t id1,id2;
    pthread_create(&id1,NULL,sendMessage,&sockfd);
    pthread_create(&id2,NULL,recvMessage,&sockfd);

    //等待发送线程结束
    pthread_join(id1,NULL);
    return 0;
}

编译执行

gcc server.c -o server -lpthread
gcc client.c -o client -lpthread

./server

ifconfig(查看主机ip地址)

./client ip地址

猜你喜欢

转载自blog.csdn.net/lidengdengter/article/details/94553040