精华内容
下载资源
问答
  • 注意epoll的性能提升,暂时我的理解比较浅 其实服务端的数据存储并不只限于mysql 可以是数组+mysql 可以是链表+mysql 可以是数组+链表+mysql 可以是线程池+mysql 可以是很多很多。。。。...用的是看个人能力,但如果...

    注意epoll的性能提升,暂时我的理解比较浅
    其实服务端的数据存储并不只限于mysql
    可以是数组+mysql
    可以是链表+mysql
    可以是数组+链表+mysql
    可以是线程池+mysql
    可以是很多很多。。。。
    用的是看个人能力,但如果基础不行,重构的几率就变的非常大

    代码实现

    内核链表

    List.h

    #include <stdlib.h>
    #include <assert.h>
    
    /*初始化链表list。链表为带头结点的双向循环链表*/
    #define List_Init(list, list_node_t) {					\
    		list=(list_node_t*)malloc(sizeof(list_node_t)); \
    		(list)->next=(list)->prev=list;					\
    	}
    
    //释放链表list中所有数据结点。list 为链表头指针,list_node_t为链表结点类型
    #define List_Free(list, list_node_t) {			\
    		assert(NULL!=list);						\
    		list_node_t *tmpPtr;					\
    		(list)->prev->next=NULL; 				\
    		while(NULL!=(tmpPtr=(list)->next)){ 	\
    			(list)->next=tmpPtr->next;			\
    			free(tmpPtr);						\
    		}										\
    		(list)->next=(list)->prev=list;			\
    	}
    
    //销毁链表list,释放所有数据结点及头结点。 list为链表头指针,tmpPtr为链表结点临时指针变量
    #define List_Destroy(list, list_node_t) {		\
    		assert(NULL!=list);						\
    		List_Free(list, list_node_t)			\
    		free(list);								\
    		(list)=NULL;							\
    	}
    
    //链表头插法,list为头指针,new为新节点
    #define List_AddHead(list, newNode) {			\
    		(newNode)->next=(list)->next;		 	\
    		(list)->next->prev=newNode;			 	\
    		(newNode)->prev=(list);				 	\
    		(list)->next=newNode;				 	\
    	}
    
    //链表尾插法,list为头指针,new为新节点
    #define List_AddTail(list, newNode) {			\
    		(newNode)->prev=(list)->prev; 		 	\
    		(list)->prev->next=newNode;			 	\
    		(newNode)->next=list;				 	\
    		(list)->prev=newNode;				 	\
    	}
    
    //将新节点newNode加入到node之前
    #define List_InsertBefore(node, newNode) {		\
    		(newNode)->prev=(node)->prev; 		 	\
    		(newNode)->next=node;			 		\
    		(newNode)->prev->next=newNode;			\
    		(newNode)->next->prev=newNode;			\
    	}
    
    //将新节点newNode加入到node之后
    #define List_InsertAfter(node, newNode) {		\
    		(newNode)->next=node->next;			 	\
    		(newNode)->prev=node; 				 	\
    		(newNode)->next->prev=newNode;			\
    		(newNode)->prev->next=newNode;			\
    	}
    
    //判断链表是否为空,list为头指针
    #define List_IsEmpty(list)  ((list != NULL)	\
    	&& ((list)->next == list)				\
    	&& (list == (list)->prev))
    
    //从删除链表结点node,
    #define List_DelNode(node) {\
    			assert(NULL!=node && node!=(node)->next && node!=(node)->prev);				\
    			(node)->prev->next=(node)->next; 	\
    			(node)->next->prev=(node)->prev;	\
    	}
    
    //从链表中删除并释放结点node
    #define List_FreeNode(node) {	\
    		List_DelNode(node);		\
    		free(node);				\
    	}
    
    
    //使用指针curPos依次遍历链表list
    #define List_ForEach(list, curPos) 		\
    	 for (   curPos = (list)->next;  	\
    		  	  	  curPos != list;       \
    		  	  	  curPos=curPos->next	\
    	    )
    
    
    //分页数据结构体,简称分页器类型
    typedef struct
    {
    	int totalRecords;	//总记录数
    	int offset;			//当前页起始记录相对于第一条记录的偏移记录数
    	int pageSize;		//页面大小
    	void *curPos;		//当前页起始记录在链表中的结点地址
    }Pagination_t;
    
    //根据分页器paging的偏移量offset将分页器定位到链表list的对应位置
    #define List_Paging(list, paging, list_node_t) {			\
    		if(paging.offset+paging.pageSize>=paging.totalRecords){	\
    			Paging_Locate_LastPage(list, paging, list_node_t);	}\
    		else {													\
    			int i;												\
    			list_node_t * pos=(list)->next;						\
    			for( i=0; i<paging.offset && pos!=list ; i++) 		\
    			   pos=pos->next;		 							\
    			paging.curPos=(void*)pos;							\
    		}														\
    	}
    
    //将分页器paging定位到链表list的第一页
    #define Paging_Locate_FirstPage(list, paging) { \
    		paging.offset=0;						\
    		paging.curPos=(void *)((list)->next);	\
    	}
    
    //将分页器paging定位到链表list的最后一页
    #define Paging_Locate_LastPage(list, paging, list_node_t) {	\
    	int i=paging.totalRecords % paging.pageSize;	\
    	if (0==i && paging.totalRecords>0)				\
    		i=paging.pageSize;							\
    	paging.offset=paging.totalRecords-i;			\
    	list_node_t * pos=(list)->prev;					\
    	for(;i>1;i--)									\
    		pos=pos->prev;								\
    	paging.curPos=(void*)pos;						\
    													\
    }
    
    //对于链表list及分页器paging,使用指针curPos依次遍历paging指向页面中每个结点
    //这里i为整型计数器变量
    #define Paging_ViewPage_ForEach(list, paging, list_node_t, pos, i) 	\
    	for (i=0, pos = (list_node_t *) (paging.curPos);	\
    			pos != list && i < paging.pageSize; 		\
    			i++, pos=pos->next)							\
    
    
    //对于链表list,将分页器paging向前(后)移动offsetPage个页面.
    //当offsetPage<0时,向前(链表头方向)移动|offsetPage|个页面
    //当offsetPage>0时,向后(链末尾方向)移动offsetPage个页面
    #define Paging_Locate_OffsetPage(list, paging, offsetPage, list_node_t) {\
    	int offset=offsetPage*paging.pageSize;			\
    	list_node_t *pos=(list_node_t *)paging.curPos;	\
    	int i;											\
    	if(offset>0){									\
    		if( paging.offset + offset >= paging.totalRecords )	{\
    			Paging_Locate_LastPage(list, paging, list_node_t);	\
    		}else {												\
    			for(i=0; i<offset; i++ )						\
    				pos=pos->next;								\
    			paging.offset += offset;						\
    			paging.curPos= (void *)pos;						\
    		}													\
    	}else{													\
    		if( paging.offset + offset <= 0 ){					\
    			Paging_Locate_FirstPage(list, paging);			\
    		}else {												\
    			for(i=offset; i<0; i++ )						\
    				pos	= pos->prev;							\
    			paging.offset += offset;						\
    			paging.curPos= pos;								\
    		}													\
    	}														\
    }
    
    //根据分页器paging计算当前的页号
    #define Pageing_CurPage(paging) 	(0==(paging).totalRecords?0:1+(paging).offset/(paging).pageSize)
    
    //根据分页器paging计算的总的页数
    #define Pageing_TotalPages(paging) 	(((paging).totalRecords%(paging).pageSize==0)?\
    	(paging).totalRecords/(paging).pageSize:\
    	(paging).totalRecords/(paging).pageSize+1)
    
    //根据paging判断当前页面是否为第一页。结果为true表示是,否则false
    #define Pageing_IsFirstPage(paging) (Pageing_CurPage(paging)<=1)
    
    //根据paging判断当前页面是否为最后一页。结果为true表示是,否则false
    #define Pageing_IsLastPage(paging) 	(Pageing_CurPage(paging)>=Pageing_TotalPages(paging))
    

    改写的线程池

    pthreadpool.h

    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<sys/types.h>
    #include<pthread.h>
    #include<assert.h>
    
    typedef struct threadpool_task_t  
    {  
        //回调函数,任务运行时会调用此函数,也可声明成其它形式
        void *(*process) (void *arg);  
        void *arg;/*回调函数的参数*/  
        struct threadpool_task_t *next;  
      
    }threadpool_task;  
     
    
    
    //线程池结构  
    typedef struct  
    {  
        pthread_mutex_t lock;  
        pthread_cond_t cond;  
      
        //链表结构,线程池中所有等待任务  
       threadpool_task *queue_head;  
      
        //是否销毁线程池  
        int shutdown;  
        pthread_t *threads;  
        //线程池中允许的活动线程数目  
        int max_thread_num;  
        //当前等待队列的任务数目 
        int queue_size;  
      
    }threadpool_t; 
    
    threadpool_t *pool;
    
    int threadpool_add(void *(*process)(void *arg),void *arg);  
    int threadpool_destroy();
    void *thread_routine(void *arg); 
    void pool_init(int max_thread_num);  
    
    void *myfunc(void* arg);
    

    pthreadpool.c

    #include "pthreadpool.h"
    
    void pool_init(int max_thread_num)  
    {  
        
        pool=(threadpool_t *)malloc(sizeof(threadpool_t));  
      
        pthread_mutex_init(&(pool->lock),NULL);  
        pthread_cond_init(&(pool->cond),NULL);  
      
        pool->queue_head=NULL;  
      
        pool->max_thread_num=max_thread_num;  
        pool->queue_size=0;  
      
        pool->shutdown=0;  
      
        pool->threads=(pthread_t *)malloc(max_thread_num*sizeof(pthread_t));  
        int i=0;  
        for(i=0;i<max_thread_num;i++)  
        {   
            pthread_create(&(pool->threads[i]),NULL,thread_routine,NULL);  
        }  
    }  
      
      
      
    //向线程池中加入任务  
    int threadpool_add(void *(*process)(void *arg),void *arg)  
    {  
        //构造一个新任务  
        threadpool_task *newworker=(threadpool_task *)malloc(sizeof(threadpool_task));  
        newworker->process=process;  
        newworker->arg=arg;  
        //置为空
        newworker->next=NULL;
      
        pthread_mutex_lock(&(pool->lock));  
        //将任务加入到等待队列中  
        threadpool_task *member=pool->queue_head;  
        if(member!=NULL)  
        {  
            while(member->next!=NULL)  
                member=member->next;  
            member->next=newworker;  
        }  
        else  
        {  
            pool->queue_head=newworker;  
        }  
      
        assert(pool->queue_head!=NULL);  
      
        pool->queue_size++;  
        pthread_mutex_unlock (&(pool->lock));
    
        /*等待队列中有任务了,唤醒一个等待线程; 
        如果所有线程都在忙碌,这句没有任何作用*/  
        pthread_cond_signal(&(pool->cond));  
        return 0;  
    }  
      
      
      
    /*销毁线程池,等待队列中的任务不会再被执行,正在运行的线程会一直 
    把任务运行完后再退出*/  
    int threadpool_destroy()  
    {  
        if(pool->shutdown)  
            return -1;//防止两次调用  
        pool->shutdown=1;  
      
        //唤醒所有等待线程,线程池要销毁了  
        pthread_cond_broadcast(&(pool->cond));  
      
        //阻塞等待线程退出,否则就成僵尸了  
        int i;  
        for(i=0;i<pool->max_thread_num;i++)  
            pthread_join(pool->threads[i],NULL);  
        free(pool->threads);  
      
        //销毁等待队列  
        threadpool_task *head=NULL;  
        while(pool->queue_head!=NULL)  
        {  
            head=pool->queue_head;  
            pool->queue_head=pool->queue_head->next;  
            free(head);  
        }  
        //条件变量和互斥量销毁  
        pthread_mutex_destroy(&(pool->lock));  
        pthread_cond_destroy(&(pool->cond));  
          
        free(pool);  
        //指针置空  
        pool=NULL;  
        return 0;  
    }  
      
      
      
    void *thread_routine(void *arg)  
    {  
        //printf("starting thread 0x%ld\n",pthread_self());  
        while (1)  
        {  
            pthread_mutex_lock(&(pool->lock));  
            /*如果等待队列为0并且不销毁线程池,则处于阻塞状态; 
            pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁*/  
            while (pool->queue_size==0&&!pool->shutdown)  
            {  
                //printf("thread 0x%ld is waiting\n",pthread_self());  
                pthread_cond_wait(&(pool->cond), &(pool->lock));  
            }  
      
            //线程池要销毁  
            if (pool->shutdown)  
            {  
                //遇到break,continue,return等跳转语句,不要忘记先解锁  
                pthread_mutex_unlock(&(pool->lock));  
                //printf ("thread 0x%ld will exit\n",pthread_self());  
                pthread_exit(NULL);  
            }  
      
           // printf("thread 0x%ld is starting to work\n",pthread_self());  
      
      
            assert(pool->queue_size!= 0);  
            assert(pool->queue_head!=NULL);  
              
            //等待队列长度减去1,并取出链表中的头元素  
            pool->queue_size--;  
            threadpool_task *worker=pool->queue_head;  
            pool->queue_head=worker->next;  
            pthread_mutex_unlock(&(pool->lock));  
      
            //调用回调函数,执行任务  
            (*(worker->process))(worker->arg);  
            free(worker);  
            worker=NULL;  
        }  
        //这一句是不可达的  
        pthread_exit(NULL);  
    }  
    
    
    /*
    //测试
    void *myfunc(void* arg)
    {  
        printf("threadid is 0x%ld,working on task %d\n",pthread_self(),*(int *)arg);  
        
        //休息一秒,延长任务的执行时间 
        sleep(1); 
        return NULL; 
    }  
      
    int main(int argc,char **argv)  
    {  
        //static threadpool_t *pool;
        //线程池中最多三个活动线程 
        pool_init (3);
        
      
          
        //连续向池中投入10个任务
        int *workingnum=(int *)malloc(sizeof(int)*10);  
        int i;  
        for(i=0;i<10;i++)  
        {  
            workingnum[i]=i;  
            threadpool_add(myfunc,&workingnum[i]);  
        }  
        //等待所有任务完成  
        sleep (5);  
        //销毁线程池  
        pool_destroy();  
        free(workingnum);  
        return 0;  
    }*/
    

    wrang.h

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <ctype.h>
    #include <arpa/inet.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include <errno.h>
    #include <pthread.h>
    #include <netinet/in.h>
    #include <poll.h>
    #include <sys/epoll.h>
    #include <fcntl.h>
    #include <stddef.h>
    #include <sys/un.h>
    
    void sys_err(const char* s,int line);
    int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);
    int Bind(int fd, const struct sockaddr *sa, socklen_t salen);
    int Connect(int fd, const struct sockaddr *sa, socklen_t salen);
    int Listen(int fd, int backlog);
    int Socket(int family, int type, int protocol);
    ssize_t Read(int fd, void *ptr, size_t nbytes);
    ssize_t Write(int fd, const void *ptr, size_t nbytes);
    int Close(int fd);
    ssize_t Readn(int fd, void *vptr, size_t n);
    ssize_t Writen(int fd, const void *vptr, size_t n);
    static ssize_t my_read(int fd, char *ptr);
    ssize_t Readline(int fd, void *vptr, size_t maxlen);
    
    
    void sys_err(const char* s,int line)
    {
        fprintf(stderr,"line:%d",line);
        perror(s);
        exit(1);
    }
    int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
    {
        int n=0;
    
    again:
    	if ((n=accept(fd,sa,salenptr))<0) 
        {
    		if ((errno==ECONNABORTED)||(errno==EINTR))
    			goto again;
    		else
    			sys_err("accept error",__LINE__);
    	}
    	return n;
    }
    int Bind(int fd, const struct sockaddr *sa, socklen_t salen)
    {
        int n=0;
    	if((n=bind(fd,sa,salen))<0)
    		sys_err("bind error",__LINE__);
        return n;
    }
    int Connect(int fd, const struct sockaddr *sa, socklen_t salen)
    {
    
        int n=0;
    
    	if((n=connect(fd,sa,salen))<0)
    		sys_err("connect error",__LINE__);
        return n;
    }
    int Listen(int fd, int backlog)
    {
        int n;
    	if((n=listen(fd,backlog))<0)
    		sys_err("listen error",__LINE__);
        return n;
    }
    int Socket(int family, int type, int protocol)
    {
       int n;
    	if((n=socket(family,type,protocol))<0)
    		sys_err("socket error",__LINE__);
    	return n;
    }
    ssize_t Read(int fd, void *ptr, size_t nbytes)
    {
        ssize_t n;
    again:
    	if ((n=read(fd,ptr,nbytes))==-1) 
        {
    		if(errno==EINTR)
    			goto again;
    		else
    			return -1;
    	}
    	return n;
    }
    ssize_t Write(int fd, const void *ptr, size_t nbytes)
    {
        ssize_t n;
    
    again:
    	if((n=write(fd,ptr,nbytes))==-1)
        {
    		if(errno==EINTR)
    			goto again;
    		else
    			return -1;
    	}
    	return n;
    }
    int Close(int fd)
    {
        int n;
    	if((n=close(fd))==-1)
    		sys_err("close error",__LINE__);
    
        return n;
    }
    
    
    /*参三: 应该读取的字节数*/
    ssize_t Readn(int fd, void *vptr, size_t n)
    {
    	size_t  nleft;              //usigned int 剩余未读取的字节数
    	ssize_t nread;              //int 实际读到的字节数
    	char   *ptr;
    
    	ptr = vptr;
    	nleft = n;
    
    	while (nleft > 0) {
    		if ((nread = read(fd, ptr, nleft)) < 0) {
    			if (errno == EINTR)
    				nread = 0;
    			else
    				return -1;
    		} else if (nread == 0)
    			break;
    
    		nleft -= nread;
    		ptr += nread;
    	}
    	return n - nleft;
    }
    
    ssize_t Writen(int fd, const void *vptr, size_t n)
    {
    	size_t nleft;
    	ssize_t nwritten;
    	const char *ptr;
    
    	ptr = vptr;
    	nleft = n;
    	while (nleft > 0) {
    		if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
    			if (nwritten < 0 && errno == EINTR)
    				nwritten = 0;
    			else
    				return -1;
    		}
    
    		nleft -= nwritten;
    		ptr += nwritten;
    	}
    	return n;
    }
    
    static ssize_t my_read(int fd, char *ptr)
    {
    	static int read_cnt;
    	static char *read_ptr;
    	static char read_buf[100];
    
    	if (read_cnt <= 0) {
    again:
    		if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
    			if (errno == EINTR)
    				goto again;
    			return -1;
    		} else if (read_cnt == 0)
    			return 0;
    		read_ptr = read_buf;
    	}
    	read_cnt--;
    	*ptr = *read_ptr++;
    
    	return 1;
    }
    
    ssize_t Readline(int fd, void *vptr, size_t maxlen)
    {
    	ssize_t n, rc;
    	char    c, *ptr;
    
    	ptr = vptr;
    	for (n = 1; n < maxlen; n++) {
    		if ( (rc = my_read(fd, &c)) == 1) {
    			*ptr++ = c;
    			if (c  == '\n')
    				break;
    		} else if (rc == 0) {
    			*ptr = 0;
    			return n - 1;
    		} else
    			return -1;
    	}
    	*ptr  = 0;
    
    	return n;
    }
    

    server.h

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/stat.h>
    #include <time.h>
    #include <pthread.h>
    #include <mysql/mysql.h>
    #include <sys/sendfile.h>
    #include "wrang.h"
    //#include "prest.h"
    #include "List.h"
    #include "pthreadpool.h"
    
    
    
    
    //#define SERV_ADDRESS "47.94.14.45"
    //#define SERV_ADDRESS "127.0.0.1"
    #define SERV_ADDRESS "192.168.30.185"
    //#define SERV_ADDRESS "192.168.1.184"
    #define SERV_PORT 8013
    
    #define MAX 50
    #define MAX_CHAR 300
    #define SAVE 10
    
    #define REGISTER 1
    #define LOGIN 2
    #define MODIFY 3
    
    #define ADD_FRIEND 4
    #define DEL_FRIEND 5
    //#define QUERY_FRIEND 6
    #define PRIVATE_CHAT 7
    #define VIEW_FRIEND_LIST 8
    //#define SHOW_FRIEND_STATUS 9
    #define VIEW_CHAT_HISTORY 10
    #define SHIELD 11
    #define UNSHIELD 12
    #define SHOW_FRIEND 13
    //#define GET_FRIEND_STATUS 14
    
    #define CREAT_GROUP 15
    #define ADD_GROUP 16
    #define DEL_GROUP 17
    #define WITHDRAW_GROUP 18
    #define KICK 19
    #define SET_GROUP_ADMIN 20
    #define VIEW_ADD_GROUP 21
    #define VIEW_GROUP_MEMBER 22 
    #define VIEW_GROUP_RECORD 23
    #define SEND_FILE 24
    #define GROUP_CHAT 25
    
    #define ADD_FRIEND_APPLY 26
    #define DEL_FRIEND_APPLY 27
    #define PRIVATE_CHAT_APPLY 28
    #define SHIELD_APPLY 29
    #define UNSHIELD_APPLY 30
    #define VIEW_FRIEND_LIST_APPLY 31
    //#define SHOW_FRIEND_STATUS_APPLY 32
    
    #define CREAT_GROUP_APPLY 33
    #define ADD_GROUP_APPLY 34
    #define DEL_GROUP_APPLY 35
    #define WITHDRAW_GROUP_APPLY 36
    #define SET_GROUP_ADMIN_APPLY 37
    #define KICK_APPLY 38
    #define VIEW_ADD_GROUP_APPLY 39
    #define VIEW_GROUP_MEMBER_APPLY 40
    #define MESSAGE_RECORD 41
    
    
    #define REGISTER_APPLY 42
    #define LOGIN_APPLY 43
    #define PRINT_APPLY 44
    #define ADD_FRIEND_ACCEPT 45
    #define VIEW_CHAT_HISTORY_APPLY 46
    #define ADD_FRIEND_ACCEPT_APPLY 47
    #define GROUP_APPLY 48
    #define ADD_GROUP_ACCEPT 49
    #define ADD_GROUP_ACCEPT_APPLY 50
    #define VIEW_GROUP_RECORD_APPLY 51
    #define GROUP_CHAT_APPLY 52
    #define RECV_FILE 53
    //#define REGISTER_ERROR_APPLY 54
    #define EXIT 54
    //#define EXIT_APPLY 55
    #define RECV_APPLY 55
    #define UPLOAD 56
    #define DOWNLOAD 57
    
    #define DOWNLINE 0
    #define ONLINE 1
    
    
    #define OWNER 1
    #define ADMIN 2
    #define COMMON 3
    #define ADOPTER 4
    
    #define STRANGER 0
    #define PAL 1
    #define BLACK 2
    #define UNBLACK 3
    
    #define MAX_THREAD_NUM 10
    
    
    typedef struct message
    {
        int flag;
        int id;
        char message[256];
    }message;
    
    
    
    
    typedef struct apply_messgae
    {
        int flag;
        int sender;
        int recver;
        int send_fd;
        int recv_fd;
        char message[256];
    }apply_messgae;
    
    
    typedef struct chat_message
    {
        int flag;
        int sender;
        int recver;
        char message[256];
        //char time[30];
    }Chat_message;
    
    typedef struct box
    {
        int flag;
        int sender;
        int recver;
        int send_fd;
        int recv_fd;
        char message[256];
    }box_t;
    
    
    
    
    typedef struct relation_info
    {
        int flag;
        int send;
        int recv;
        int relation;
        char message[256];
    }Relation_t;
    
    typedef struct friend_info
    {
        int flag;
        int send;
        int recv;
        int status;
        int relation;
        char name[MAX];
        char message[256];
    }Friend_t;
    
    
    
    typedef struct group_info
    {
        int flag;
     
        int group_owner;
        int admin;
        char group_name[MAX];
    }Group_t;
    
    
    typedef struct group_leader
    {
        int flag;
        int sender;
        int recver;
        int admin;
        char message[256];
    }Group_leader;
    
    
    
    //服务器保存用户信息结构体
    typedef struct account
    {
        int flag;
        int id;
        char name[MAX];
        char password[MAX];
        struct sockaddr_in useraddr;
      
        
        int online;      //1:开;0:关
        int connfd;      //链接套接字
    }Account_t;         
    
    
    int user_num;
    
    typedef struct server_user
    {
        int connfd;
        int id;
        char name[MAX];
        char password[MAX];
    }server_user_t;
    
    
    typedef struct server_user_node
    {
        server_user_t data;
        struct server_user_node* next;
        struct server_user_node* prev;
    }server_user_node_t,*server_list_t;
    
    server_list_t list_ser;
    
    
    
    
    typedef struct file
    {
       
        int flag;
        int sender;
        int recver;
        int file_size;
        char file_name[100];
        char data[800];
    }file_t;
    
    
    
    
    int lfd;
    int epfd;
    int cfd;
    
    void Init_socket();
    void *Recv_pack(void* arg);
    void Turn_worker_thread();
    void *work(void* arg);
    
    void Login(int fd,char* buf);
    void Send_offline_apply(int fd,int recver);
    void Send_offline_messgae(int fd,int recver);
    void Register(int fd,char* buf);
    void Exit(int fd,char* buf);
    
    void Add_friend(int fd,char* buf);
    void Add_friend_accept(int fd,char* buf);
    void Del_friend(int fd,char* buf);
    
    
    void Shield_friend(int fd,char* buf);
    void Unshield_friend(int fd,char* buf);
    //一起实现
    //void Show_friend_status();
    void View_friend_list(int fd,char* buf);
    
    int Check_relationship(int fd,int send,int recv);
    void Private_chat(int fd,char* buf);
    void View_chat_history(int fd,char* buf);
    
    void Create_group(int fd,char* buf);
    void Add_group(int fd,char* buf);
    void Add_group_accept(int fd,char* buf);
    void Withdraw_group(int fd,char* buf);
    
    //一起实现
    void View_group_member(int fd,char* buf);
    void View_add_group(int fd,char* buf);
    
    void Group_chat(int fd,char* buf);
    void View_group_record(int fd,char* buf);
    
    
    void Set_group_admin(int fd,char* buf);
    void Kick(int fd,char* buf);
    
    
    int Check_relationship2(int fd,int send,int recv);
    void Upload(int fd,char* buf);
    void *Send_file(void *arg);
    
    void Recv_file(int fd,char* buf);
    void Download(int fd,char* buf);
    
    
    void my_err(const char* err_string,int line);
    void Connect_mysql();
    void Close_mysql(MYSQL mysql);
    
    
    int Get_connfd(int id);
    void Send_pack(int fd,int flag,char* buf);
    void Send_connfd_pack(int flag,int sender,int recver,char* buf);
    void Send_pack_name(int flag ,int sender,int recver,char *buf);
    
    
    
    
    
    void Mysql_with_error(MYSQL* mysql);
    void Signal_close(int i);
    
    
    
    void Add_node(int fd,int id,char* name);
    void Send_register_pack(int fd,int flag,char* buf,int id);
    int Get_status(int id);
    char* Get_name(int id);
    

    server.c

    #include "server.h"
    #define EPOLLEVENT 1024
    #define BUFMAX 1024
    #define BUF 2048
    
    
    char *Server_time();
    int	Set_no_block(int sfd);
    
    int sys_log;
    MYSQL mysql;
    
    /*
    void Add_node(int fd,int id,char* name);
    void Send_register_pack(int fd,int flag,char* buf,int id);
    int Get_status(int id);
    char* Get_name(int id);*/
    int main()
    {
    
       
    
    
        /*if((sys_log=open("sys_log",O_WRONLY | O_CREAT | O_APPEND,S_IRUSR|S_IWUSR))<0)
        {
            sys_err("open error",__LINE__);
            return 0;
        }
        dup2(sys_log,1);*/
    
        
        signal(SIGINT,Signal_close);
    
        //pthread_mutex_init(&mutex,NULL);
        //pthread_cond_init(&cond,NULL);
    
        Connect_mysql();
        /*printf("线程池启动\n");
        pool_init(MAX_THREAD_NUM);
        printf("线程池启动成功!\n");
        sleep(2);*/
        pool_init(50);
        //sleep(2);
        //Read_from_mysql();
        Init_socket();
    
    
        //threadpool_destroy();
    
    }
    void Signal_close(int i)
    {
        close(sys_log);
        Close_mysql(mysql);
        printf("服务器关闭\n");
        exit(1);
    }
    
    
    char *Server_time()
    {
    	time_t ctime;//服务器时间
    	struct tm *server_time;
    	time(&ctime);
    	server_time=localtime(&ctime);
    	return asctime(server_time);
    }
    
    int	Set_no_block(int sfd)
    {
    	/* 内层调用fcntl()的F_GETFL获取flag,
    	 * 外层fcntl()将获取到的flag设置为O_NONBLOCK非阻塞*/
    	if( fcntl(sfd, F_SETFL, fcntl(sfd, F_GETFL, 0) ) == -1)
    	{	
            return -1;
        }
    	return 0;
    }
    
    void Init_socket(int argc,char *argv[])
    {
        struct stat stat_buf;
    	const char* file_name=argv[1];   
        int file_fd=open(file_name,O_RDONLY);
    	fstat(file_fd,&stat_buf);
    	close(file_fd); 
    
        List_Init(list_ser,server_user_node_t);
        printf("服务端启动\n");
        struct sockaddr_in serv_addr;
        struct sockaddr_in cli_addr;
    
        socklen_t cli_addr_len;
    
        lfd=Socket(AF_INET,SOCK_STREAM,0);
    
    
        Set_no_block(lfd);
        //端口复用
        int opt=1;
        setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt));
    
        bzero(&serv_addr,sizeof(serv_addr));
    
        serv_addr.sin_family=AF_INET;
        serv_addr.sin_port=htons(SERV_PORT);
        serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    
        Bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
        Listen(lfd,128);
    
        printf("服务器启动成功!\n");
    
        epfd=epoll_create(EPOLLEVENT);
        struct epoll_event tep,ep[EPOLLEVENT];
        tep.events=EPOLLIN;
        tep.data.fd=lfd;
        epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&tep);
    
        int i;
        int ret;
        pthread_t pid;
        char buf[BUFMAX];
        //memset(buf,0,sizeof(buf));
        while(1)
        {
            ret=epoll_wait(epfd,ep,EPOLLEVENT,-1);
            for(i=0;i<ret;i++)
            {
    
                //printf("the event is %x\n",ep[i].events);
                int fd=ep[i].data.fd;
    
                if (!(ep[i].events & EPOLLIN))      //如果不是"读"事件, 继续循环
                    continue;
    
                if(ep[i].data.fd==lfd)
                {
                    cli_addr_len=sizeof(cli_addr);
                    cfd=Accept(lfd,(struct sockaddr*)&cli_addr,&cli_addr_len);
                    printf("连接到新的客户端ip:%s\n端口号:%d\n",inet_ntoa(cli_addr.sin_addr),cli_addr.sin_port);
                    
                    /*设置非阻塞io*/
    				if(Set_no_block(cfd) != 0 )
    				{
    					printf("SET_no_black\n");
    					printf("%s",Server_time());
    					close(cfd);
    					continue;
    				}
                    
                    tep.events=EPOLLIN;
                    tep.data.fd=cfd;
                    if(epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&tep)<0)
                    {
                        printf("EPOLL_CTL add client error\n");
                        printf("%s",Server_time());
    					
                        close(cfd);
    					continue;
                    }
    
                }
                /*else if(ep[i].events & EPOLLOUT) 
                {
                    printf("start to sendfile !\n");
                    printf("处理写事件\n");
                    int write;
                    write=send(fd,buf,strlen(buf),0);
                    if(write == -1)
                    {
                        my_err("write event error",__LINE__);
                        close(fd);
                    }
                    else
                    {
                        printf("发送消息成功\n");
                    }
                    memset(buf,0,BUFMAX);
                }*/
                /*else if(ep[i].events & EPOLLOUT)
                {
    
    				printf("start to sendfile !\n");
    				int send_ret=0;
                    int left=stat_buf.st_size;
    				file_fd=open(file_name,O_RDONLY);
    
    				while(left>0)
                    {
    					send_ret=sendfile(cfd,file_fd,NULL,BUF);
    					if(send_ret<0 && errno==EAGAIN)
                        {
    						continue;
    					}
                        else if(send_ret==0)
                        {
    						break;
    					}
                        else
                        {
    						left-=send_ret;
    					}
    				}
    
    				printf("sendfile over !\n");
    				close(file_fd);
    
    				tep.data.fd=cfd;
    				epoll_ctl(epfd,EPOLL_CTL_DEL,cfd,&tep);
    
    				close(cfd);
                }*/
                else if(ep[i].events & EPOLLIN)
                {
                    memset(buf,0,sizeof(buf));
                    int n=recv(ep[i].data.fd,buf,sizeof(buf),MSG_WAITALL);
                    int fd=ep[i].data.fd;
                    printf("\n");
                    /*printf("%d\n",recv_t.data.send_fd);
                    printf("%d\n",recv_t.data.recv_fd);
                    printf("server message%s\n",recv_t.data.message);
                    printf("server recv:%s\n",recv_t.data.send_name);*/
    
    
                    if(n<0)
                    {
                        close(ep[i].data.fd);
                        sys_err("recv error!",__LINE__);
                        continue;
                    }
                    else if(n==0)
                    {
                        printf("??????\n");
                        server_list_t pos;
                        List_ForEach(list_ser,pos)
                        {
                            if(pos->data.connfd==ep[i].data.fd)
                            {    
                                printf("sssssssssssss\n");
                               
                                char buf_t[BUFSIZ];
                                sprintf(buf_t,"update account set status=0 where id=%d",pos->data.id);
                                printf("buf_t:%s\n",buf_t);
                                int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
                                if(ret)
                                {
                                    Mysql_with_error(&mysql);
                                }
                                //printf("用户[%d]已经下线\n",pos->data.id);
                                printf("账号[%d]下线了:%d\n",pos->data.id,pos->data.connfd);
    
                                List_FreeNode(pos);  
                                break;
                            }
                        }
                        tep.data.fd=ep[i].data.fd;
                        printf("客户端:%d连接断开\n",tep.data.fd);
                       
                        epoll_ctl(epfd,EPOLL_CTL_DEL,ep[i].data.fd,&tep);
                        close(ep[i].data.fd);
                        continue;
                    }
    
                    int flag;
                    memcpy(&flag,buf,sizeof(int));
                    printf("flag:%d\n",flag);
                    
                    switch(flag)
                    {
                        case LOGIN:
                            Login(fd,buf);
                            break;
                        case REGISTER:
                            Register(fd,buf);
                            break;
                        case EXIT:
                            Exit(fd,buf);
                            break;
                        case ADD_FRIEND:
                            Add_friend(fd,buf);
                            break;
                        case ADD_FRIEND_ACCEPT:
                            Add_friend_accept(fd,buf);
                            break;
                        case DEL_FRIEND:
                            Del_friend(fd,buf);
                            break;
                        case PRIVATE_CHAT:
                            Private_chat(fd,buf);
                            break;
                        //写在一起比较好
                        //case SHOW_FRIEND_STATUS:
                        case VIEW_FRIEND_LIST:
                            View_friend_list(fd,buf);
                            break;
                        case SHIELD:
                            Shield_friend(fd,buf);
                            break;
                        case UNSHIELD:
                            Unshield_friend(fd,buf);
                            break;
                        case VIEW_CHAT_HISTORY:
                            View_chat_history(fd,buf);
                            break;
                        case CREAT_GROUP:
                            Create_group(fd,buf);
                            break;
                        case ADD_GROUP:
                            Add_group(fd,buf);
                            break;
                        case ADD_GROUP_ACCEPT:
                            Add_group_accept(fd,buf);
                            break;
                        case WITHDRAW_GROUP:
                            Withdraw_group(fd,buf);
                            break;
                        //一起实现
                        case VIEW_GROUP_MEMBER:
                            View_group_member(fd,buf);
                            break;
                        case VIEW_ADD_GROUP:
                            View_add_group(fd,buf);
                            break;
                        case SET_GROUP_ADMIN:
                            Set_group_admin(fd,buf);
                            break;
                        case KICK:
                            Kick(fd,buf);
                            break;
                        case GROUP_CHAT:
                            Group_chat(fd,buf);
                            break;
                        case VIEW_GROUP_RECORD:
                            View_group_record(fd,buf);
                            break;
                        /*case SEND_FILE:
                            printf("here\n");
                            {
                                printf("111111111111111\n");
                                char *buf1=(char*)malloc(sizeof(1024));
                                printf("22222222222222222\n");
                                memcpy(buf1,buf,sizeof(file_t));
                                printf("333333333333333333\n");
                                threadpool_add(Send_file,(void*)buf1);*/
                                /*printf("....\n");
                                file_t file;
                                char *str=(char*)malloc(sizeof(file));
                                memcpy(str,buf,sizeof(file));
                                pthread_t recv_file_id;
                                pthread_create(&recv_file_id,NULL,Send_file,(void*)str);
                                printf(">>>>\n");*/
                                
                                //Send_file(fd,buf);
                                //break;
                            //}
                        case SEND_FILE:
                            break;
                        case UPLOAD:
                            Upload(fd,buf);
                            break;;
                        /*case RECV_FILE:
                            //Recv_file(fd,buf);
                            break;*/
                        case DOWNLOAD:
                            Download(fd,buf);
                            break;
                        case 0:
                            break;
                    }
                }
            }
        }
        close(epfd);
        close(lfd);
    }
    
    void Register(int fd,char* buf)
    {
        Account_t account;
        memcpy(&account,buf,sizeof(account));
        printf("server name:%s\n",account.name);
        printf("server password:%s\n",account.password);
        server_user_t user;
        strcpy(user.name,account.name);
        strcpy(user.password,account.password);
        printf("server username:%s\n",user.name);
        printf("server password:%s\n",user.password);
    
        account.online=DOWNLINE;
    
       
        
        char buf_t[BUFSIZ];
        sprintf(buf_t,"insert into account values(NULL,'%s','%s','%d')",account.name,account.password,account.online);
        printf("buf_t:%s\n",buf_t);
        int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
            printf("注册失败\n");
            /*char mes[256];
            sprintf(mes,"你输入的名称[%s]有误,请重新输入",account.name);
            Send_pack(fd,REGISTER_ERROR_APPLY,mes);*/
        }
        else 
            printf("注册成功\n");
    
        memset(buf_t,0,sizeof(buf_t));
        sprintf(buf_t,"select LAST_INSERT_ID()");
        printf("buf_t:%s\n",buf_t);
        ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        int id=atoi(row[0]);
        printf("server username:%d",id);
        char str[256];
        //strcpy(str,account.username);
        sprintf(str,"账号[%d]注册成功",id);
        Send_register_pack(fd,REGISTER_APPLY,str,id);
        printf("666666666\n");   
    }               
    
    
    void Send_register_pack(int fd,int flag,char* buf,int id)
    {
        char str[BUFSIZ];
        message mes;
    
        mes.flag=flag;
        mes.id=id;
        strcpy(mes.message,buf);
        printf("server send message:%s\n",mes.message);
        memcpy(str,&mes,sizeof(mes));
        
        printf("server send id:%d\n",mes.id);
        printf("server send flag:%d\n",mes.flag);
        if(send(fd,str,sizeof(str),0)<0)
        {
            my_err("send error!",__LINE__);
            close(fd);
        }
    }
    
    
    void Login(int fd,char* buf)
    {
        Account_t account;
        memcpy(&account,buf,sizeof(account));
        printf("server id:%d\n",account.id);
        printf("server password:%s\n",account.password);
        char name[MAX];
        
        
        int send_fd=Get_connfd(account.id);
        /*server_list_t pos;
        List_ForEach(list_ser,pos)
        {
            if(pos->data.id==account.id)
            {
                send_fd=pos->data.connfd;
            }
        }*/
        if(send_fd>0)
        {
            printf("账号已登录\n");
            Send_pack(fd,LOGIN_APPLY,"a");
            return ;
        }
    
    
        char buf_t[BUFSIZ];
        sprintf(buf_t,"select *from account where id=%d",account.id);
        printf("buf_t:%s\n",buf_t);
        int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
            //printf("row[0]:%s\n",row[0]);
        if(row==NULL)
        {
            printf("/\n");
            /*char mes[256];
            sprintf(mes,"密码错误或者账号不存在!\n");
            Send_pack(fd,LOGIN_APPLY,mes);*/
            Send_pack(fd,LOGIN_APPLY,"n");
            return ;
        }
        
        else
        {
            printf("row[0]:%s\n",row[0]);
            //if(strcmp(row[0],user.username)==0)
            //{
              //  memset(buf_t,0,sizeof(buf_t));
                //sprintf(buf_t,"select username from account");
                //printf("buf_t:%s\n",buf_t);
                strcpy(name,row[1]);
                printf("name:%s\n",row[1]);
                if(strcmp(row[2],account.password)==0)
                {
                    Add_node(fd,account.id,name);
                    server_list_t p;
                    List_ForEach(list_ser,p)
                    {
                        printf("username:%d\n",p->data.id);
                        printf("connfd:%d\n",p->data.connfd);
                        printf("name:%s\n",p->data.name);
                    }
                    Send_pack(fd,LOGIN_APPLY,"y");
                    memset(buf_t,0,sizeof(buf_t));
                    sprintf(buf_t,"update account set status=1 where id=%d",account.id);
                    printf("buf_t:%s\n",buf_t);
                    int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
                    if(ret)
                    {
                        Mysql_with_error(&mysql);
                    }
                    printf("[%d]登录成功\n",account.id);
                    Send_offline_apply(fd,account.id);
                    Send_offline_messgae(fd,account.id);
    
                }
                else
                    Send_pack(fd,LOGIN_APPLY,"n");
            //}
        }
    }
    void Send_offline_apply(int fd,int recver)
    {
        char buf[BUFSIZ];
        sprintf(buf,"select *from friend where (fid=%d and  request=%d)",recver,0);
        printf("buf=%s\n",buf);
        int ret=mysql_real_query(&mysql,buf,strlen(buf));
        if(ret)
        {
            Mysql_with_error(&mysql);
            printf("您暂无离线好友申请消息\n");
        }
        MYSQL_RES *result;
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        
        while((row=mysql_fetch_row(result)))
        {
            char buf[BUFSIZ];
            sprintf(buf,"update friend set request=2 where fid=%d",atoi(row[1]));
            printf("buf=%s\n",buf);
            int ret=mysql_real_query(&mysql,buf,strlen(buf));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            char mes[256];
            int requester=atoi(row[0]);
            sprintf(mes,"用户[%d]请求加你为好友",requester);
            Send_connfd_pack(ADD_FRIEND_APPLY,requester,recver,mes);
            printf("[%d]对好友[%d]好友申请发送成功\n",requester,recver);
        }
    
    
        memset(buf,0,sizeof(buf));
        sprintf(buf,"select sid from group_request where (mid=%d and request=2)",recver);
        printf("buf=%s\n",buf);
        ret=mysql_real_query(&mysql,buf,strlen(buf));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result2;
        MYSQL_ROW  row2;
        result2=mysql_store_result(&mysql);
        //row2=mysql_fetch_row(result2);
    
       
        while((row2=mysql_fetch_row(result2)))
        {   
             printf("row2[0]:%d\n",atoi(row2[0]));
           
                char buf[BUFSIZ];
    
                char mes[256];
                int requester=atoi(row2[0]);
                sprintf(mes,"用户[%d]请求加入群聊",atoi(row2[0]));
                Send_connfd_pack(ADD_GROUP_APPLY,requester,recver,mes);
                printf("[%d]对群管理[%d]的群申请发送成功\n",requester,recver);
    
    
                sprintf(buf,"update group_member set request=1 where mid=%d",atoi(row2[0]));
                printf("buf:%s\n",buf);
                ret=mysql_real_query(&mysql,buf,strlen(buf));
                if(ret)
                {
                    Mysql_with_error(&mysql);
                }
    
    
                 memset(buf,0,sizeof(buf));
                sprintf(buf,"update group_request set request=1 where mid=%d",recver);
                printf("buf:%s\n",buf);
                ret=mysql_real_query(&mysql,buf,strlen(buf));
                if(ret)
                {
                    Mysql_with_error(&mysql);
                }
        }
    
    }
    void Send_offline_messgae(int fd,int recver)
    {
        char buf[BUFSIZ];
        memset(buf,0,sizeof(buf));
        sprintf(buf,"select *from chat_message where (fid=%d and status=%d)",recver,0);
        printf("buf=%s\n",buf);
        int ret=mysql_real_query(&mysql,buf,strlen(buf));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result;
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
    
        while((row=mysql_fetch_row(result)))
        {
    
            char str[BUFSIZ];
            sprintf(str,"select *from account where id=%d",atoi(row[0]));
            printf("str:%s\n",str);
            int ret=mysql_real_query(&mysql,str,strlen(str));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            MYSQL_RES *result1;
            MYSQL_ROW row1;
            result1=mysql_store_result(&mysql);
            row1=mysql_fetch_row(result1);
    
            char name[MAX];
            strcpy(name,row1[1]);
    
    
            char buf[BUFSIZ];
            sprintf(buf,"update chat_message set status=2 where fid=%d",recver);
            printf("buf=%s\n",buf);
            ret=mysql_real_query(&mysql,buf,strlen(buf));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            Chat_message mes_t;
            mes_t.flag=PRIVATE_CHAT_APPLY;
            mes_t.sender=atoi(row[0]);
            mes_t.recver=atoi(row[1]);
            strcpy(mes_t.message,row[2]);
            /*char str[BUFSIZ];
            memcpy(str,&mes_t,sizeof(mes_t));
            if(send(fd,buf,sizeof(buf),0)<0)
            {
                my_err("send error!",__LINE__);
            }*/
            char mes[256];
            sprintf(mes,"\033[;33m\33[1m%d\t\033[;32m\33[1m%s\t\033[;31m\33[1m%s\033[0m",mes_t.sender,name,mes_t.message);
            Send_pack(fd,PRIVATE_CHAT_APPLY,mes);
            printf("[%d]有对[%d]的离线聊天\n",mes_t.sender,mes_t.recver);
        }
    
    
        memset(buf,0,sizeof(buf));
        sprintf(buf,"select *from group_message where (recv_name=%d and status=0)",recver);
        printf("buf=%s\n",buf);
        ret=mysql_real_query(&mysql,buf,strlen(buf));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result1;
        MYSQL_ROW  row1;
        result1=mysql_store_result(&mysql);
        while((row1=mysql_fetch_row(result1)))
        {
    
            char str[BUFSIZ];
            sprintf(str,"select *from account where id=%d",atoi(row1[0]));
            printf("str:%s\n",str);
            int ret=mysql_real_query(&mysql,str,strlen(str));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            MYSQL_RES *result2;
            MYSQL_ROW row2;
            result2=mysql_store_result(&mysql);
            row2=mysql_fetch_row(result2);
    
            char name[MAX];
            strcpy(name,row2[1]);
    
    
    
    
            Chat_message mes_t;
            mes_t.flag=GROUP_CHAT_APPLY;
            mes_t.sender=atoi(row1[0]);
            mes_t.recver=atoi(row1[1]);
            strcpy(mes_t.message,row1[2]);
            /*char str[BUFSIZ];
            memcpy(str,&mes_t,sizeof(mes_t));
            if(send(fd,buf,sizeof(buf),0)<0)
            {
                my_err("send error!",__LINE__);
            }*/
             char mes[256];
             sprintf(mes,"[%d]\t%s\t%s",mes_t.sender,name,mes_t.message);
    
             Send_pack(fd,GROUP_CHAT_APPLY,mes);
            printf("[%d]有对群的离线聊天\n",mes_t.sender);
    
    
            char buf[BUFSIZ];
            sprintf(buf,"update group_message set status=1 where recv_name=%d",recver);
            printf("buf=%s\n",buf);
            ret=mysql_real_query(&mysql,buf,strlen(buf));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
        }
    
    
    }
    void Exit(int fd,char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
        printf("server recv message:%s\n",mes.message);
    
        char buf_t[BUFSIZ];
        sprintf(buf_t,"update account set status=0 where id=%d",mes.id);
        printf("buf_t:%s\n",buf_t);
        int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        printf("用户[%d]已经下线\n",mes.id);
        
        //char mes1[256];
        //sprintf(mes1,"您[%d]已退出",mes.id);
        //Send_pack(fd,EXIT_APPLY,mes1);
    
    }
    
    void Add_node(int fd,int id,char* name)
    {
        server_list_t pos=(server_list_t)malloc(sizeof(server_user_node_t));
        pos->data.connfd=fd;
        pos->data.id=id;
        strcpy(pos->data.name,name);
        printf("pos->data.connfd:%d\n",pos->data.connfd);
        printf("pos->data.id=%d\n",pos->data.id);
        printf("pos->data.name=%s\n",pos->data.name);
        List_AddTail(list_ser,pos);
    }
    void Add_friend(int fd,char* buf)
    {
    
        Relation_t relation;
        memcpy(&relation,buf,sizeof(relation));
        printf("server/ friend send:%d\n",relation.send);
        printf("server/ friend recv:%d\n",relation.recv);
        printf("server/ friend message:%s\n",relation.message);
    
        char buf_t[BUFSIZ];
        //查询有没有这两个人的账号
        sprintf(buf_t,"select request from friend where (uid=%d and fid=%d) or (uid=%d and fid=%d)",relation.send,relation.recv,relation.recv,relation.send);
        printf("buf_t:%s\n",buf_t);
        int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        //获得申请者的客户端套接字
        int send_fd;
        send_fd=Get_connfd(relation.send);
    
        //如果没有这两个的信息
        if(row==NULL)
        {
            //查看添加好友账户是否存在
            char buf[BUFSIZ];
            sprintf(buf,"select status from account where id=%d",relation.recv);
            printf("buf:%s\n",buf);
            ret=mysql_real_query(&mysql,buf,strlen(buf));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            MYSQL_RES *result1;  
            MYSQL_ROW  row1;
            result1=mysql_store_result(&mysql);
            row1=mysql_fetch_row(result1);
            if(row1==NULL)
            {
                char mes[256];
                sprintf(mes,"账号[%d]不存在",relation.recv);
                Send_pack(send_fd,PRINT_APPLY,mes);
                return;
            }
    
    
            //用户存在
            relation.relation=STRANGER;
            memset(buf_t,0,sizeof(buf_t));
            //请求为0
            //表示好友还没验证
            sprintf(buf_t,"insert into friend values('%d','%d','%d','%d')",relation.send,relation.recv,relation.relation,0);
            printf("buf_t:%s\n",buf_t);
            ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            printf("用户%d对%d发起了好友申请\n",relation.send,relation.recv);
    
            //获得被申请好友的客户端套接字
            //如果在线
            int recv_fd=Get_connfd(relation.recv);
            printf("hehehheheheh>>>>>>>>>\n");
            printf("recv_fd:%d\n",recv_fd);
            if(recv_fd<0)
            {
                printf("所申请的用户[%d]不在线\n",relation.recv);
                Send_pack(send_fd,PRINT_APPLY,"d");
                return;
            }
            else
            {
                char str[256];
                sprintf(str,"用户[%d]向你发送了好友请求",relation.send);
                Send_connfd_pack(ADD_FRIEND_APPLY,relation.send,relation.recv,str);
    
                //如果在线为request为2已经发送
                char buf[BUFSIZ];
                sprintf(buf,"update friend set request=2 where (uid=%d and fid=%d)",relation.send,relation.recv);
                printf("buf=%s\n",buf);
                int ret=mysql_real_query(&mysql,buf,strlen(buf));
                if(ret)
                {
                    Mysql_with_error(&mysql);
                }
            }
        }
        else if(row!=NULL)
        {
            if(atoi(row[0])==0)
            {
                char mes[256];
                sprintf(mes,"正在等待对方验证,请不要重复发好友申请");
                Send_pack(send_fd,PRINT_APPLY,mes);
                return;
            }
            if(atoi(row[0])==2)
            {
                char mes[256];
                sprintf(mes,"请勿重复添加好友");
                Send_pack(send_fd,PRINT_APPLY,mes);
                return;
            }
        }
    
    
    }
    /*void Add_friend(int fd,char* buf)
    {
    
        Relation_t relation;
        memcpy(&relation,buf,sizeof(relation));
        printf("server/ friend send:%d\n",relation.send);
        printf("server/ friend recv:%d\n",relation.recv);
        printf("server/ friend message:%s\n",relation.message);
    
        char buf_t[BUFSIZ];
        //查询有没有这两个人的账号
        sprintf(buf_t,"select *from friend where (uid=%d and fid=%d) or (uid=%d and fid=%d)",relation.send,relation.recv,relation.recv,relation.send);
        printf("buf_t:%s\n",buf_t);
        int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        //获得申请者的客户端套接字
        int send_fd;
        send_fd=Get_connfd(relation.send);
    
        //如果没有这两个的信息
        if(row==NULL)
        {
            //
            relation.relation=STRANGER;
            memset(buf_t,0,sizeof(buf_t));
            sprintf(buf_t,"insert into friend values('%d','%d','%d','%d')",relation.send,relation.recv,relation.relation,0);
            printf("buf_t:%s\n",buf_t);
            ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            printf("用户%d对%d发起了好友申请\n",relation.send,relation.recv);
    
            //获得被申请好友的客户端套接字
            //如果在线
            int recv_fd=Get_connfd(relation.recv);
            printf("hehehheheheh>>>>>>>>>\n");
            printf("recv_fd:%d\n",recv_fd);
            if(recv_fd<0)
            {
                printf("所申请的用户[%d]不在线\n",relation.recv);
                Send_pack(send_fd,PRINT_APPLY,"d");
                return;
            }
            else
            {
                char str[256];
                sprintf(str,"用户[%d]向你发送了好友请求",relation.send);
                Send_connfd_pack(ADD_FRIEND_APPLY,relation.send,relation.recv,str);
    
                //如果在线为request为2已经发送
                char buf[BUFSIZ];
                sprintf(buf,"update friend set request=2 where (uid=%d and fid=%d)",relation.send,relation.recv);
                printf("buf=%s\n",buf);
                int ret=mysql_real_query(&mysql,buf,strlen(buf));
                if(ret)
                {
                    Mysql_with_error(&mysql);
                }
            }
        }
        else if(row!=NULL)
        {
            Send_pack(send_fd,PRINT_APPLY,"w");
            return;
        }
    
    
    }*/
    void Send_connfd_pack(int flag,int sender,int recver,char* buf)
    {
        int recv_fd;
        server_list_t pos;
        //获得接受者套接字
        List_ForEach(list_ser,pos)
        {
            if(pos->data.id==recver)
            {
                printf("该用户的客户端套接字为:%d\n",pos->data.connfd);
                recv_fd=pos->data.connfd;
            }
        }
        int send_fd;
        send_fd=Get_connfd(sender);
    
        char str[BUFSIZ];
        box_t box;
        box.flag=flag;
        box.sender=sender;//申请者
        box.recver=recver;//被申请者
        box.send_fd=send_fd;//申请者客户端号
        box.recv_fd=recv_fd;//被申请者客户端号
    
        //buf:用户[%d]向你发送了好友请求
        strcpy(box.message,buf);
    
        memcpy(str,&box,sizeof(box));
    
        printf("server send message:%s\n",box.message);
        printf("server send flag:%d\n",box.flag);
        printf("server/ friend send id:%d\n",box.sender);
        printf("server/ friend recv id:%d\n",box.recver);
        //朋友客户端号
        printf("server/ friend recv_fd:%d\n",recv_fd);
        printf("server/ friend send_fd:%d\n",send_fd);
    
        if(send(recv_fd,str,sizeof(str),0)<0)
        {
            my_err("send error!",__LINE__);
        }
    
    }
    void Add_friend_accept(int fd,char* buf)
    {
        Relation_t relation;
        memcpy(&relation,buf,sizeof(relation));
        printf("server/ friend accpet send:%d\n",relation.send);
        printf("server/ friend accpet recv:%d\n",relation.recv);
        printf("server/ friend accpet message:%s\n",relation.message);
    
        char str1[BUFSIZ];
        char str2[BUFSIZ];
        if(strcmp(relation.message,"y")==0)
        {
            char buf[BUFSIZ];
            relation.relation=PAL;
            sprintf(buf,"update friend set status =%d where (uid=%d and fid=%d) ",relation.relation,relation.recv,relation.send);
            printf("buf:%s\n",buf);
            int ret=mysql_real_query(&mysql,buf,strlen(buf));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            printf("[%d]成为了[%d]的新朋友\n",relation.send,relation.recv);
    
            sprintf(str1,"[%d]通过了您的好友请求",relation.send);
            Send_pack_name(ADD_FRIEND_ACCEPT_APPLY,relation.send,relation.recv,str1);//发给申请者
    
            sprintf(str2,"你已经和[%d]成为了朋友",relation.recv);
            Send_pack_name(ADD_FRIEND_ACCEPT_APPLY,relation.recv,relation.send,str2);//发给被申请者
        }
        else
        {
            char buf[BUFSIZ];
            sprintf(buf,"delete from friend where (uid=%d and fid=%d)",relation.recv,relation.send);
            printf("buf:%s\n",buf);
            int ret=mysql_real_query(&mysql,buf,strlen(buf));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            printf("[%d]拒绝成为[%d]的好友\n",relation.send,relation.recv);
    
            memset(str1,0,sizeof(str1));
            sprintf(str1,"[%d]拒绝了您的好友请求",relation.send);
            Send_pack_name(ADD_FRIEND_ACCEPT_APPLY,relation.send,relation.recv,str1);//发给申请者
    
        }
    }
    
    void Send_pack_name(int flag ,int sender,int recver,char *buf)
    {
        int recv_fd=Get_connfd(recver);
        char str[BUFSIZ];
        apply_messgae mes;
    
        mes.flag=flag;
        mes.sender=sender;//被申请者
        mes.recver=recver;//申请者
        strcpy(mes.message,buf);
        printf("server/ friend accept apply send:%d\n",mes.sender);
        printf("server/ friend accept apply recv:%d\n",mes.recver);
        printf("server/ friend accept apply send message:%s\n",mes.message);
    
        memcpy(str,&mes,sizeof(mes));
        
        printf("server send message:%s\n",mes.message);
        printf("server send flag:%d\n",mes.flag);
        if(send(recv_fd,str,sizeof(str),0)<0)
        {
            my_err("send error!",__LINE__);
        }
    
    
    }
    int Get_connfd(int id)
    {
        server_list_t pos;
        List_ForEach(list_ser,pos)
        {
            if(pos->data.id==id)
            {
                printf("用户套接字:%d\n",pos->data.connfd);
                return pos->data.connfd;
            }
        }
        return -1;
    }
    
    void Del_friend(int fd,char* buf)
    {
        
        Relation_t relation;
        memcpy(&relation,buf,sizeof(relation));
        printf("server/ friend send:%d\n",relation.send);
        printf("server/ friend recv:%d\n",relation.recv);
        printf("server/ friend message:%s\n",relation.message);
    
         //获得发送者的端口号
        int send_fd=Get_connfd(relation.send);
    
        char buf_t[BUFSIZ];
        sprintf(buf_t,"select request from friend where (uid=%d and fid=%d) or (uid=%d and fid=%d)",relation.send,relation.recv,relation.recv,relation.send);
        printf("buf_t:%s\n",buf_t);
        int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result; 
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row==NULL)
        {
            char mes[256];
            sprintf(mes,"好友[%d]不存在",relation.recv);
            Send_pack(send_fd,DEL_FRIEND_APPLY,mes);
            return;
        }
        if(atoi(row[0])==0)
        {
            char mes[256];
            sprintf(mes,"你和[%d]还不是好友,无法删除",relation.recv);
            Send_pack(send_fd,DEL_FRIEND_APPLY,mes);
            return;
        }
    
    
    
        memset(buf_t,0,sizeof(buf_t));
        //更新这两个人的关系
        sprintf(buf_t,"delete from friend where (uid=%d and fid=%d) or (uid=%d and fid=%d)",relation.send,relation.recv,relation.recv,relation.send);
        printf("buf_t:%s\n",buf_t);
        ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
            printf("删除好友失败\n");
        }
        printf("[%d]删除了与[%d]的好友关系\n",relation.send,relation.recv);
    
       
        char str1[BUFSIZ];
        char str2[BUFSIZ];
        sprintf(str1,"你与[%d]的朋友关系已经解除",relation.recv);
        Send_pack(send_fd,DEL_FRIEND_APPLY,str1);
    
        //被删除者的端口号
        int recv_fd=Get_connfd(relation.recv);
    
        if(recv_fd<0)
        {
            char mes[256];
            sprintf(mes,"好友[%d]不在线",relation.recv);
            Send_pack(send_fd,DEL_FRIEND_APPLY,mes);
            return;
        }
        sprintf(str2,"你已经被[%d]删除了好友关系",relation.send);
        Send_pack(recv_fd,DEL_FRIEND_APPLY,str2);
    }
    
    
    /*void Del_friend(int fd,char* buf)
    {
        
        Relation_t relation;
        memcpy(&relation,buf,sizeof(relation));
        printf("server/ friend send:%d\n",relation.send);
        printf("server/ friend recv:%d\n",relation.recv);
        printf("server/ friend message:%s\n",relation.message);
    
        char buf_t[BUFSIZ];
        //更新这两个人的关系
        sprintf(buf_t,"delete from friend where (uid=%d and fid=%d) or (uid=%d and fid=%d)",relation.send,relation.recv,relation.recv,relation.send);
        printf("%s\n",buf_t);
        int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
            printf("删除好友失败\n");
        }
        printf("[%d]删除了与[%d]的好友关系\n",relation.send,relation.recv);
    
        //获得发送者的端口号
        int send_fd=Get_connfd(relation.send);
        char str1[BUFSIZ];
        char str2[BUFSIZ];
        sprintf(str1,"你与[%d]的朋友关系已经解除",relation.recv);
        Send_pack(send_fd,DEL_FRIEND_APPLY,str1);
    
        //被删除者的端口号
        int recv_fd=Get_connfd(relation.recv);
    
        if(recv_fd)
        {
            char mes[256];
            sprintf(mes,"好友[%d]不在线",relation.recv);
            Send_pack(send_fd,DEL_FRIEND_APPLY,mes);
            return;
        }
        sprintf(str2,"你已经被[%d]删除了好友关系",relation.send);
        Send_pack(recv_fd,DEL_FRIEND_APPLY,str2);
    
    
        //server_list_t pos;
        //server_list_t pos_friend;
    
        //pos=Find_server_user(pack_t->data.send_name);
        //Find_del_server_user(pos,pack_t->data.message);
    
        //pos_friend=Find_server_user(pack_t->data.message);
        //Find_del_server_user(pos_friend,pack_t->data.send_name);
    
        //free(pack_t);
    }*/
    int Check_relationship(int fd,int send,int recv)
    {
        char str[BUFSIZ];
        sprintf(str,"select status from friend where (uid=%d and fid=%d and request=2) or (uid=%d and fid=%d and request=2)",send,recv,recv,send);
        printf("str:%s\n",str);
        int ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
    
        MYSQL_RES *result; 
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        printf("here\n");
        if(row==NULL)
        {
            printf("why>\n");
            char mes[256];
            sprintf(mes,"[%d]还不是您的好友",recv);
            Send_pack(fd,PRIVATE_CHAT_APPLY,mes);
            //Send_pack(fd,PRIVATE_CHAT_APPLY,"0");
            return -1;
        }
        if(atoi(row[0])==2)
        {
            char mes[256];
            sprintf(mes,"[%d]已经被屏蔽",recv);
            Send_pack(fd,PRIVATE_CHAT_APPLY,mes);
            return 0;
        }
        return 1;
    }
    void Private_chat(int fd,char* buf)
    {
        Chat_message mes;
        memcpy(&mes,buf,sizeof(mes));
    
        printf("server/ friend chat send:%d\n",mes.sender);
        printf("server/ friend chat recv:%d\n",mes.recver);
        //printf("server/ friend chat time:%s\n",mes.time);
        printf("server/ friend chat message:%s\n",mes.message);
    
        int flag=Check_relationship(fd,mes.sender,mes.recver);
        if(flag>0)
        {
            //先插入mysql
            char str[BUFSIZ];
            sprintf(str,"insert into chat_message values('%d','%d','%s','%d')",mes.sender,mes.recver,mes.message,0);
            //没发前状态为0
            printf("str:%s\n",str);
            int ret=mysql_real_query(&mysql,str,strlen(str));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
    
            printf("[%d]对[%d]聊天记录以及写入mysql\n",mes.sender,mes.recver);
    
            //获取聊天对方的套接字
            int recv_fd=Get_connfd(mes.recver);
            int send_fd=Get_connfd(mes.sender);
            if(recv_fd<0)
            {
                printf("[%d]不在线\n",mes.recver);
                char mes1[256];
                sprintf(mes1,"[%d]不在线",mes.recver);
                Send_pack(send_fd,PRIVATE_CHAT_APPLY,mes1);
                return;
            }
            else
            {
            
                char buf[BUFSIZ];
                sprintf(buf,"select *from chat_message where (uid=%d and fid=%d and status=%d)",mes.sender,mes.recver,0);//0未发送
                printf("buf:%s\n",buf);
                ret=mysql_real_query(&mysql,buf,strlen(buf));
                printf("?????\n");
                if(ret)
                {
                    printf(">>>>>\n");
                    Mysql_with_error(&mysql);
                }
    
                MYSQL_RES *result;
                MYSQL_ROW row;
                result=mysql_store_result(&mysql);
    
                
                while((row=mysql_fetch_row(result)))
                {
                    //标志位改为1并且发送
                    char str[BUFSIZ];
                    sprintf(str,"update chat_message set status=%d where (uid=%d and fid=%d)",2,mes.sender,mes.recver);//2已经发送
                    printf("str:%s\n",str);
                    int ret=mysql_real_query(&mysql,str,strlen(str));
                    if(ret)
                    {
                        Mysql_with_error(&mysql);
                    }
                    else
                    {
                        char str[BUFSIZ];
                        sprintf(str,"select *from account where id=%d",atoi(row[0]));
                        printf("str:%s\n",str);
                        int ret=mysql_real_query(&mysql,str,strlen(str));
                        if(ret)
                        {
                            Mysql_with_error(&mysql);
                        }
                        MYSQL_RES *result1;
                        MYSQL_ROW row1;
                        result1=mysql_store_result(&mysql);
                        row1=mysql_fetch_row(result1);
    
                        char name[MAX];
                        strcpy(name,row1[1]);
    
                        Chat_message mes_t;
                        mes_t.flag=PRIVATE_CHAT_APPLY;
                        mes_t.sender=atoi(row[0]);
                        mes_t.recver=atoi(row[1]);
                        //strcpy(mes_t.time,mes.time);
                        printf("row[2]:%s\n",row[2]);
                        strcpy(mes_t.message,row[2]);
                        printf("mes_t.flag:%d\n",mes_t.flag);
                        printf("mes_t.sender:%d\n",mes_t.sender);
                        printf("mes_t.recver:%d\n",mes_t.recver);
                        printf("mes_t.mes:%s\n",mes_t.message);
                        //printf("mes_t.time:%s\n",mes_t.time);
                       /* char buf[BUFSIZ];
                        memcpy(buf,&mes_t,sizeof(mes_t));
                        if(send(recv_fd,buf,sizeof(buf),0)<0)
                        {
                            my_err("send error!",__LINE__);
                        }*/
                        char mes[256];
                        sprintf(mes,"\033[;33m\33[1m%d\t\033[;32m\33[1m%s\t\033[;31m\33[1m%s\033[0m",mes_t.sender,name,mes_t.message);
                        Send_pack(recv_fd,PRIVATE_CHAT_APPLY,mes);
                        printf("[%d]正在对[%d]聊天\n",mes_t.sender,mes_t.recver);
                    }  
                }  
    
    
            }
        }
        else if(flag==0)
        {
            printf("[%d]和[%d]处于屏蔽状态\n",mes.sender,mes.recver);
            char mes1[256];
            memset(&mes1,0,sizeof(mes1));
            sprintf(mes1,"你与[%d]处于屏蔽状态,无法聊天",mes.sender);
            Send_pack(fd,PRIVATE_CHAT_APPLY,mes1);
            return ;
        }
    
    }
    void View_chat_history(int fd,char* buf)
    {
        Chat_message mes;
        memcpy(&mes,buf,sizeof(mes));
    
        char str[BUFSIZ];
        sprintf(str,"select *from friend where (uid=%d and fid=%d and request=2) or (uid=%d and fid=%d and request=2)",mes.sender,mes.recver,mes.recver,mes.sender);
        printf("str:%s\n",str);
        int ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row==NULL)
        {
            Send_pack(fd,VIEW_CHAT_HISTORY_APPLY,"你们还不是好友,请先添加好友聊天");
            printf("[%d]查询聊天记录失败\n",mes.sender);
            Send_pack(fd,VIEW_CHAT_HISTORY_APPLY,"over");
        }
    
        char str2[BUFSIZ];
        sprintf(str2,"select *from chat_message where (uid=%d and fid=%d and status=2) or (uid=%d and fid=%d and status=2)",mes.sender,mes.recver,mes.recver,mes.sender);
        printf("str2:%s\n",str2);
        ret=mysql_real_query(&mysql,str2,strlen(str2));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
    
        int send_fd=Get_connfd(mes.sender);
        char str1[256];
        printf("22222222\n");
        MYSQL_RES *result2;  
        MYSQL_ROW  row2;
        result2=mysql_store_result(&mysql);
        while((row2=mysql_fetch_row(result2)))
        {
             char str1[256];
             memset(str1,0,sizeof(str1));
            printf("1111111\n");
            sprintf(str1,"[%d]对[%d]:%s",atoi(row2[0]),atoi(row2[1]),row2[2]);
            Send_pack(send_fd,VIEW_CHAT_HISTORY_APPLY,str1);
        }
        Send_pack(fd,VIEW_CHAT_HISTORY_APPLY,"over");
    
        printf("[%d]查询了与[%d]的聊天记录\n",mes.sender,mes.recver);
    
    
    }
    
    void Shield_friend(int fd,char* buf)
    {
        Relation_t relation;
        memcpy(&relation,buf,sizeof(relation));
        printf("server/ friend send:%d\n",relation.send);
        printf("server/ friend recv:%d\n",relation.recv);
        printf("server/ friend message:%s\n",relation.message);
    
    
        //获得发送者的端口号
        int send_fd=Get_connfd(relation.send);
    
        char buf_t[BUFSIZ];
        sprintf(buf_t,"select request,status from friend where (uid=%d and fid=%d) or (uid=%d and fid=%d)",relation.send,relation.recv,relation.recv,relation.send);
        printf("buf_t:%s\n",buf_t);
        int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
         MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row==NULL)
        {
            char mes[256];
            sprintf(mes,"账号[%d]不存在",relation.recv);
            Send_pack(send_fd,SHIELD_APPLY,mes);
            return;
        }
        if(atoi(row[0])==0)
        {
            char mes[256];
            sprintf(mes,"对方还不是你的好友,操作无效");
            Send_pack(send_fd,SHIELD_APPLY,mes);
            return;
        }
        if(atoi(row[1])==2)
        {
            char mes[256];
            sprintf(mes,"你已经屏蔽了好友[%d],请勿重复操作",relation.recv);
            Send_pack(send_fd,SHIELD_APPLY,mes);
            return;
        }
    
    
    
        memset(buf_t,0,sizeof(buf_t));
        //更新这两个人的关系
        relation.relation=BLACK;
        sprintf(buf_t,"update friend set status=2 where (uid=%d and fid=%d) or (uid=%d and fid=%d)",relation.send,relation.recv,relation.recv,relation.send);
        printf("buf_t:%s\n",buf_t);
        ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
            printf("屏蔽好友失败\n");
        }
        printf("[%d]屏蔽了与[%d]的好友关系\n",relation.send,relation.recv);
    
        
    
       
    
        char str1[256];
        sprintf(str1,"你已经屏蔽了[%d]",relation.recv);
        Send_pack(send_fd,SHIELD_APPLY,str1);
    
        int recv_fd=Get_connfd(relation.recv);
    
        if(recv_fd<0)
        {
            char mes[256];
            sprintf(mes,"屏蔽的好友[%d]不在线",relation.recv);
            Send_pack(send_fd,SHIELD_APPLY,mes);
            return;
        }
        printf("????\n");
        char str2[256];
        memset(str2,0,sizeof(str2));
        sprintf(str2,"你被[%d]屏蔽了",relation.send);
        Send_pack(recv_fd,SHIELD_APPLY,str2);
    
    }
    void Unshield_friend(int fd,char* buf)
    {
        Relation_t relation;
        memcpy(&relation,buf,sizeof(relation));
        printf("server/ friend send:%d\n",relation.send);
        printf("server/ friend recv:%d\n",relation.recv);
        printf("server/ friend message:%s\n",relation.message);
    
        //获得发送者的端口号
        int send_fd=Get_connfd(relation.send);
    
    
    
        char buf_t[BUFSIZ];
        sprintf(buf_t,"select request,status from friend where (uid=%d and fid=%d) or (uid=%d and fid=%d)",relation.send,relation.recv,relation.recv,relation.send);
        printf("buf_t:%s\n",buf_t);
        int ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
         MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row==NULL)
        {
            char mes[256];
            sprintf(mes,"账号[%d]不存在",relation.recv);
            Send_pack(send_fd,UNSHIELD_APPLY,mes);
            return;
        }
        if(atoi(row[0])==0)
        {
            char mes[256];
            sprintf(mes,"对方还不是你的好友,操作无效");
            Send_pack(send_fd,UNSHIELD_APPLY,mes);
            return;
        }
        if(atoi(row[1])==1)
        {
            char mes[256];
            sprintf(mes,"[%d]已经被解除了屏蔽,操作无效",relation.recv);
            Send_pack(send_fd,UNSHIELD_APPLY,mes);
            return;
        }
    
    
        memset(buf_t,0,sizeof(buf_t));
        //更新这两个人的关系
        relation.relation=PAL;
        sprintf(buf_t,"update friend set status=1 where (uid=%d and fid=%d) or (uid=%d and fid=%d)",relation.send,relation.recv,relation.recv,relation.send);
        printf("buf_t:%s\n",buf_t);
        ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
            printf("解除屏蔽失败\n");
        }
        printf("[%d]成功解除了屏蔽与[%d]的好友关系\n",relation.send,relation.recv);
    
       
        char str1[256];
        sprintf(str1,"你已经成功解除屏蔽[%d]",relation.recv);
        Send_pack(send_fd,UNSHIELD_APPLY,str1);
    
        int recv_fd=Get_connfd(relation.recv);
        if(recv_fd<0)
        {
             printf("[%d]不在线\n",relation.recv);
                char mes1[256];
                sprintf(mes1,"[%d]不在线",relation.recv);
                Send_pack(send_fd,UNSHIELD_APPLY,mes1);
            return;
        }
        char str2[256];
        sprintf(str2,"你被[%d]解除了屏蔽",relation.send);
        Send_pack(recv_fd,SHIELD_APPLY,str2);
    }
    
    //一起实现
    //void Show_friend_status();
    void View_friend_list(int fd,char* buf)
    {
        Friend_t friend;
        memcpy(&friend,buf,sizeof(friend));
    
        printf("server/ friend list send:%d\n",friend.send);
        printf("server/ friend list recv:%d\n",friend.recv);
        printf("server/ friend list message:%s\n",friend.message);
    
    
        char str[BUFSIZ];
        sprintf(str,"select *from friend where (uid=%d or fid=%d)",friend.send,friend.recv);
        printf("str:%s\n",str);
        int ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
            printf("[%d]查询好友失败\n",friend.send);
        }
    
    
    
    
        //Friend_t send_friend;
        int send_fd=Get_connfd(friend.send);
        int id;
        MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        while((row=mysql_fetch_row(result)))
        {
            if(atoi(row[0])==friend.send)
                id=atoi(row[1]);
            else
                id=atoi(row[0]);
        
            printf("id:%d\n",id);
            int status;
            /*server_list_t pos;
            List_ForEach(list_ser,pos)
            {
                if(pos->data.id==id)
                {
                    send_friend.status=ONLINE;
                    strcpy(send_friend.name,pos->data.name);
                    printf("000000000000000");
                    printf("这是在线\n");
                }
                else
                {
                    send_friend.status=DOWNLINE;
                     strcpy(send_friend.name,pos->data.name);
                     printf("1111111111111111离线\n");
                }
            }*/
           
    
            char buff[BUFSIZ];
            sprintf(buff,"select *from account where id=%d",id);
            printf("buff:%s\n",buff);
            int ret=mysql_real_query(&mysql,buff,strlen(buff));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
           MYSQL_RES *result1;  
            MYSQL_ROW  row1;
            result1=mysql_store_result(&mysql);
            row1=mysql_fetch_row(result1);
            status=atoi(row1[3]);
            char name[MAX];
            strncpy(name,row1[1],sizeof(row[1]));
            
    
    
            printf("1111111111111111111name:%s\n",name);
            if(atoi(row[2])==1)
            {
                printf("row[2]:%d\n",atoi(row[2]));
                if(status==1)
                {
                    sprintf(str,"\033[;33m\33[1m%d\t\033[;31m\33[1m%s\t\033[;35m\33[1m%s\t\033[;34m\33[1m%s\033[0m",id,name,"在线","好友");
                    Send_pack(send_fd,VIEW_FRIEND_LIST_APPLY,str);
                }
                else 
                {
                    sprintf(str,"\033[;33m\33[1m%d\t\033[;31m\33[1m%s\t\033[;35m\33[1m%s\t\033[;34m\33[1m%s\033[0m",id,name,"离线","好友");
                    Send_pack(send_fd,VIEW_FRIEND_LIST_APPLY,str);
                }
                
            }
            else if(atoi(row[2])==2)
            {
                printf("row[2]:%d\n",atoi(row[2]));
                if(status==1)
                {
                    sprintf(str,"\033[;33m\33[1m%d\t\033[;31m\33[1m%s\t\033[;35m\33[1m%s\t\033[;34m\33[1m%s\033[0m",id,name,"在线","黑名单");
                    Send_pack(send_fd,VIEW_FRIEND_LIST_APPLY,str);
                }
                else
                {
                    sprintf(str,"\033[;33m\33[1m%d\t\033[;31m\33[1m%s\t\033[;35m\33[1m%s\t\033[;34m\33[1m%s\033[0m",id,name,"离线","黑名单");
                    Send_pack(send_fd,VIEW_FRIEND_LIST_APPLY,str);
                }
            }
        }
        Send_pack(fd,VIEW_FRIEND_LIST_APPLY,"over");
        printf("[%d]查询好友成功\n",friend.send);
    }
        
    int Get_status(int id)
    {
        server_list_t pos;
            List_ForEach(list_ser,pos)
            {
                if(pos->data.id==id)
                {
                    return 1;
                    printf("000000000000000");
                    printf("这是在线\n");
                }
            }
            return 0;
    }
    char* Get_name(int id)
    {
        server_list_t pos;
            List_ForEach(list_ser,pos)
            {
                if(pos->data.id==id)
                {
                    return pos->data.name;
                    printf("000000000000000");
                    printf("这是在线\n");
                }
            }
            return NULL;
    }
    void Create_group(int fd,char* buf)
    {
    
        Group_t group;
        memcpy(&group,buf,sizeof(group));
        printf("server/ create group_name:%s\n",group.group_name);
        printf("server/ create group_id:%d\n",group.group_owner);
        printf("server/ create group_owner:%d\n",group.group_owner);
        printf("server/ create group_admin:%d\n",group.admin);
    
    //查看群号是否被注册过
        char str1[BUFSIZ];
        sprintf(str1,"select gid from groups where group_name='%s'",group.group_name);
        printf("str1:%s\n",str1);
        int ret=mysql_real_query(&mysql,str1,strlen(str1));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result;
        MYSQL_ROW row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
    
    
        int send_fd=Get_connfd(group.group_owner);
        printf("send_fd:%d\n",send_fd);
        if(row!=NULL)
        {
            char mes[256];
            sprintf(mes,"该群名[%s]的群号[%d]已被注册过,请重新创建群",group.group_name,group.group_owner);
            Send_pack(send_fd,CREAT_GROUP_APPLY,mes);
            return;
        }
    
    
        char str[BUFSIZ];
        sprintf(str,"insert into groups values(NULL,'%s')",group.group_name);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
            printf("注册群失败\n");
        }
    
        char buf_t[BUFSIZ];
        sprintf(buf_t,"select LAST_INSERT_ID()");
        printf("buf_t:%s\n",buf_t);
        ret=mysql_real_query(&mysql,buf_t,strlen(buf_t));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result1;  
        MYSQL_ROW  row1;
        result1=mysql_store_result(&mysql);
        row1=mysql_fetch_row(result1);
        int id=atoi(row1[0]);
        printf("group_id:%d",id);
    
    
        char str2[256];
        sprintf(str2,"群名[%s]----群号[%d]创建成功",group.group_name,id);
        printf("str2:%s\n",str2);
        Send_pack(send_fd,CREAT_GROUP_APPLY,str2);
    
    
        memset(str,0,sizeof(str));
        //群号  群成员 群地位 请求
        sprintf(str,"insert into group_member values('%d','%d','%d','%d')",id,group.group_owner,OWNER,1);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        printf("[%d]注册群成功\n",group.group_owner);
    
       
    }
    void Add_group(int fd,char* buf)
    {
        Relation_t relation;
        memcpy(&relation,buf,sizeof(relation));
    
        
        char str[BUFSIZ];
        int send_fd=Get_connfd(relation.send);
    
        //查询是否申请过
        char str1[BUFSIZ];
        sprintf(str1,"select request from group_member where gid=%d and mid=%d",relation.recv,relation.send);
        printf("str1:%s\n",str1);
        int ret=mysql_real_query(&mysql,str1,strlen(str1));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result;
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row)
        {
            //已经是成员
           if(atoi(row[0])==1)
           {
               char mes[256];
               sprintf(mes,"您已经是群[%d]成员,请勿重复添加",relation.recv);
               Send_pack(send_fd,GROUP_APPLY,mes);
           }
           //重复添加
           else if(atoi(row[0])==2)
           {
                char mes[256];
               sprintf(mes,"您的加群[%d]正在审核,请勿重复添加",relation.recv);
               Send_pack(send_fd,GROUP_APPLY,mes);
           }
           return ;
        }
    
    
    
        //查询是否有该群
        memset(str,0,sizeof(str));
        sprintf(str,"select group_name from groups where gid=%d",relation.recv);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result1;
        MYSQL_ROW  row1;
        result1=mysql_store_result(&mysql);
        row1=mysql_fetch_row(result1);
        if(row1==NULL)
        {
            char mes[256];
            sprintf(mes,"此群[%d]不存在",relation.recv);
            Send_pack(send_fd,GROUP_APPLY,mes);
            return;
        }
    
        //群存在
        //先插入数据到 group_member
        //待审核 request 2
        //群号 群成员 请求
        memset(str,0,sizeof(str));
        sprintf(str,"insert into group_member(gid,mid,request) values('%d','%d','%d')",relation.recv,relation.send,2);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        printf("[%d]请求加入群[%d]\n",relation.send,relation.recv);
    
    
        //查询管理人员
    
        memset(str,0,sizeof(str));
        sprintf(str,"select mid from group_member where gid=%d and (status=1 or status=2)",relation.recv);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        
        MYSQL_RES *result2;
        MYSQL_ROW  row2;
        result2=mysql_store_result(&mysql);
        while((row2=mysql_fetch_row(result2)))
        {
            memset(str,0,sizeof(str));
            //请求为2  待审核
            sprintf(str,"insert into group_request values(%d,%d,%d)",relation.send,atoi(row2[0]),2);
            printf("str:%s\n",str);
            ret=mysql_real_query(&mysql,str,strlen(str));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            /*memset(str,0,sizeof(str));
            sprintf(str,"select status from account where id=%d",atoi(row2[0]));
            printf("str:%s\n",str);
            ret=mysql_real_query(&mysql,str,strlen(str));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            MYSQL_RES *result3;
            MYSQL_ROW  row3;
            result3=mysql_store_result(&mysql);
            row3=mysql_fetch_row(result3);*/
            int recv_fd=Get_connfd(atoi(row2[0]));
    
            if(recv_fd<0)
            {
                 printf("群[%d]管理不在线,请等待审核\n",relation.recv);
                char mes[256];
                sprintf(mes,"群[%d]管理不在线,请等待审核",relation.recv);
                Send_pack(send_fd,GROUP_APPLY,mes);
                return;
            }
    
             printf("[%d]向群管理[%d]发起了群申请\n",relation.send,atoi(row2[0]));
            //群管理处理
            char str2[256];
            sprintf(str2,"用户[%d]向你(群管理[%d])发送了群申请",relation.send,atoi(row2[0]));
            printf("str2:%s\n",str2);
            Send_connfd_pack(ADD_GROUP_APPLY,relation.send,atoi(row2[0]),str2);
    
    
    
            //如果在线为request为2已经发送
                char buf[BUFSIZ];
                sprintf(buf,"update group_member set request=1 where (gid=%d and mid=%d)",relation.recv,relation.send);
                printf("buf=%s\n",buf);
                int ret=mysql_real_query(&mysql,buf,strlen(buf));
                if(ret)
                {
                    Mysql_with_error(&mysql);
                }
    
            memset(buf,0,sizeof(buf));
                sprintf(buf,"update group_request set request=1 where (sid=%d and mid=%d)",relation.send,atoi(row2[0]));
                printf("buf=%s\n",buf);
                ret=mysql_real_query(&mysql,buf,strlen(buf));
                if(ret)
                {
                    Mysql_with_error(&mysql);
                }
        }
    }
       
    
        
        
        /*//查询管理人员
        //找到群主
        memset(str,0,sizeof(str));
        sprintf(str,"select mid from group_member where gid=%d and status=1",relation.recv);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        
        MYSQL_RES *result2;
        MYSQL_ROW  row2;
        result2=mysql_store_result(&mysql);
        row2=mysql_fetch_row(result2);
        
        Group_t group;
        group.group_owner=atoi(row2[0]);
    
        int owner_fd=Get_connfd(group.group_owner);
    
    
        //群管理
        memset(str,0,sizeof(str));
        sprintf(str,"select mid from group_member where gid=%d and status=2",relation.recv);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result3;
        MYSQL_ROW  row3;
        result3=mysql_store_result(&mysql);
        row3=mysql_fetch_row(result3);
        if(row3==NULL)
        {
            printf("群[%d]暂时没有管理员\n",relation.recv);
              printf("[%d]向群主[%d]发起了群申请\n",relation.send,group.group_owner);
    
    
            if(owner_fd<0)
            {
                //请求为2  待审核
                char str[BUFSIZ];
                sprintf(str,"insert into group_request values(%d,%d,%d)",relation.send,group.group_owner,2);
                printf("str:%s\n",str);
                ret=mysql_real_query(&mysql,str,strlen(str));
                if(ret)
                {
                    Mysql_with_error(&mysql);
                }
    
                printf("群[%d]主不在线,请等待审核\n",relation.recv);
                char mes[256];
                sprintf(mes,"群[%d]主不在线,请等待审核",relation.recv);
                Send_pack(send_fd,GROUP_APPLY,mes);
                return;
            }
    
    
            //群主处理
            char str2[256];
            sprintf(str2,"用户[%d]向你(群主[%d])发送了群申请",relation.send,group.group_owner);
            printf("str2:%s\n",str2);
            Send_connfd_pack(ADD_GROUP_APPLY,relation.send,group.group_owner,str2);
            return ;
        }
    
    
        //如果有管理员
        printf("row3:%d\n",atoi(row3[0]));
        group.admin=atoi(row3[0]);
    
    
        int admin_fd=Get_connfd(group.admin);
    
        if(owner_fd<0)
        {
            printf("群[%d]主不在线,请等待审核\n",relation.recv);
                char mes[256];
                sprintf(mes,"群[%d]主不在线,请等待审核",relation.recv);
                Send_pack(send_fd,GROUP_APPLY,mes);
                return;
        }
        else if(admin_fd<0)
        {
            
              printf("群[%d]管理不在线,请等待审核\n",relation.recv);
                char mes[256];
                sprintf(mes,"群[%d]管理不在线,请等待审核",relation.recv);
                Send_pack(send_fd,GROUP_APPLY,mes);
                return;
        }
        else if(owner_fd<0 && admin_fd<0)
        {
             printf("群[%d]管理不在线,请等待审核\n",relation.recv);
                char mes[256];
                sprintf(mes,"群[%d]管理不在线,请等待审核",relation.recv);
                Send_pack(send_fd,GROUP_APPLY,mes);
                return;
        }
          //群管理处理
            printf("[%d]向群管理[%d]发送了群申请\n",relation.send,group.admin);
            char str3[256];
            sprintf(str3,"用户[%d]向你(群管理[%d])发送了群申请",relation.send,group.admin);
            printf("str3:%s\n",str3);
            Send_connfd_pack(ADD_GROUP_APPLY,relation.send,group.admin,str3);
    */
    void Add_group_accept(int fd,char* buf)
    {
        Relation_t relation;
        memcpy(&relation,buf,sizeof(relation));
        printf("server/ group accpet send:%d\n",relation.send);//管理员
        printf("server/ group accpet recv:%d\n",relation.recv);//申请者
        printf("server/ group accpet message:%s\n",relation.message);
    
        char str1[BUFSIZ];
        char str2[BUFSIZ];
        if(strcmp(relation.message,"y")==0)
        {
            //更改地位
            char buf[BUFSIZ];
            relation.relation=COMMON;
            sprintf(buf,"update group_member set status=%d where mid=%d ",relation.relation,relation.recv);
            printf("buf:%s\n",buf);
            int ret=mysql_real_query(&mysql,buf,strlen(buf));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            //更改请求
            memset(buf,0,sizeof(buf));
            sprintf(buf,"update group_member set request=%d where mid=%d ",1,relation.recv);
            printf("buf:%s\n",buf);
            ret=mysql_real_query(&mysql,buf,strlen(buf));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            printf("[%d]同意了[%d]的入群请求\n",relation.send,relation.recv);
    
            sprintf(str1,"[%d]通过了您的入群请求",relation.send);
            Send_pack_name(ADD_GROUP_ACCEPT_APPLY,relation.send,relation.recv,str1);//发给申请者
    
            sprintf(str2,"您已经同意了[%d]的入群请求",relation.recv);
            Send_pack_name(ADD_GROUP_ACCEPT_APPLY,relation.recv,relation.send,str2);//发给管理员
        }
        else
        {
            char buf[BUFSIZ];
            sprintf(buf,"delete from group_member where mid=%d",relation.recv);
            printf("buf:%s\n",buf);
            int ret=mysql_real_query(&mysql,buf,strlen(buf));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            printf("[%d]拒绝了[%d]的入群请求\n",relation.send,relation.recv);
    
            memset(str1,0,sizeof(str1));
            sprintf(str1,"[%d]拒绝了您的入群请求",relation.send);
            Send_pack_name(ADD_FRIEND_ACCEPT_APPLY,relation.send,relation.recv,str1);//发给申请者
    
        }
    }
    void Withdraw_group(int fd,char* buf)
    {
        Relation_t relation;
        memcpy(&relation,buf,sizeof(relation));
        
        //先查询是否是群成员
        char str1[BUFSIZ];
        sprintf(str1,"select request from group_member where (gid=%d and mid=%d)",relation.recv,relation.send);
        printf("str1:%s\n",str1);
        int ret=mysql_real_query(&mysql,str1,strlen(str1));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result;
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row==NULL)
        {
            char mes[256];
            sprintf(mes,"群[%d]不存在",relation.recv);
            Send_pack(fd,WITHDRAW_GROUP_APPLY,mes);
            return;
        }
    
    
        if(atoi(row[0])==2)
        {
            char mes[256];
            sprintf(mes,"你不在该群[%d]中,无法退出(没有被审核)",relation.recv);
            Send_pack(fd,WITHDRAW_GROUP_APPLY,mes);
            return;
        }
        
            //查询群主
            Group_t group;
            //memset(str,0,sizeof(str));
            char str[BUFSIZ];
            sprintf(str,"select mid from group_member where (gid=%d and status=1)",relation.recv);
            printf("str:%s\n",str);
            ret=mysql_real_query(&mysql,str,strlen(str));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            MYSQL_RES *result1;
            MYSQL_ROW  row1;
            result1=mysql_store_result(&mysql);
            row1=mysql_fetch_row(result1);
            group.group_owner=atoi(row1[0]);
    
            int send_fd=Get_connfd(group.group_owner);
    
             //获得申请退群者的端口号
            int fd_t=Get_connfd(relation.send);
    
            if(send_fd<0)
            {
                char mes[256];
                sprintf(mes,"[%d]不在线,请稍后再试",group.group_owner);
                Send_pack(fd_t,WITHDRAW_GROUP_APPLY,mes);
                return;
            }
    
            char mes[256];
            printf("[%d]退出了群聊[%d]\n",relation.send,relation.recv);
            sprintf(mes,"[%d]退出了你的群聊[%d]",relation.send,relation.recv);
            Send_pack(send_fd,WITHDRAW_GROUP_APPLY,mes);
    
    
    
            memset(str,0,sizeof(str));
            sprintf(str,"delete from group_member where (mid=%d and gid=%d)",relation.send,relation.recv);
            printf("str:%s\n",str);
            ret=mysql_real_query(&mysql,str,strlen(str));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
    
           
            memset(mes,0,sizeof(mes));
            sprintf(mes,"您已经退出了群聊[%d]\n",relation.recv);
            printf("mes:%s\n",mes);
            Send_pack(fd_t,WITHDRAW_GROUP_APPLY,mes);
        
            //如果群主解散
            if(relation.send==group.group_owner)
            {
                char str1[BUFSIZ];
                sprintf(str1,"delete from groups where gid=%d",relation.recv);
                printf("str1:%s\n",str1);
                ret=mysql_real_query(&mysql,str1,strlen(str1));
                if(ret)
                {
                    Mysql_with_error(&mysql);
                }
                
                memset(str1,0,sizeof(str1));
                sprintf(str1,"delete from group_member where gid=%d",relation.recv);
                printf("str1:%s\n",str1);
                ret=mysql_real_query(&mysql,str1,strlen(str1));
                if(ret)
                {
                    Mysql_with_error(&mysql);
                }
                
    
                char str2[256];
                sprintf(str2,"群[%d]已经解散",relation.recv);
                Send_pack(send_fd,DEL_GROUP_APPLY,str2);
                return ;
            }
    
    }
    void View_group_member(int fd,char* buf)
    {
         Relation_t relation;
        memcpy(&relation,buf,sizeof(relation));
    
        char str[BUFSIZ];
        sprintf(str,"select *from group_member where (mid=%d and gid=%d and request=1)",relation.send,relation.recv);
        printf("str:%s\n",str);
        int ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
            printf("[%d]查询群信息失败\n",relation.send);
        }
        MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        printf("111111111111\n");
        int send_fd=Get_connfd(relation.send);
        if(row==NULL)
        {
             printf("你[%d]还没有加入此群或者此群不存在\n",relation.send);
            char mes[256];
            sprintf(mes,"你还没有加入此群聊或此群不存在");
            Send_pack(send_fd,VIEW_GROUP_MEMBER_APPLY,mes);
             Send_pack(fd,VIEW_GROUP_MEMBER_APPLY,"over");
            return ;
        }
    
        //查找成员
        memset(str,0,sizeof(str));
        sprintf(str,"select mid from group_member where (gid=%d and request=1)",relation.recv);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result1;  
        MYSQL_ROW  row1;
        result1=mysql_store_result(&mysql);
       
        while((row1=mysql_fetch_row(result1)))
        {
    
            char buf[BUFSIZ];
     
            memset(buf,0,sizeof(buf));
            sprintf(buf,"select username,status from account where id=%d",atoi(row1[0]));
            printf("buf:%s\n",buf);
            ret=mysql_real_query(&mysql,buf,strlen(buf));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            MYSQL_RES *result2;  
            MYSQL_ROW  row2;
            result2=mysql_store_result(&mysql);
            row2=mysql_fetch_row(result2);
    
            char mes[256];
            memset(&mes,0,sizeof(mes));
            //账号 名字 状态
            if(atoi(row2[1])==1)
                sprintf(mes,"\033[;33m\33[1m%d\t\033[;31m\33[1m%s\t\033[;35m\33[1m%s\033[0m",atoi(row1[0]),row2[0],"在线");
            else if(atoi(row2[1])==0)
                sprintf(mes,"\033[;33m\33[1m%d\t\033[;31m\33[1m%s\t\033[;35m\33[1m%s\033[0m",atoi(row1[0]),row2[0],"离线");
            Send_pack(send_fd,VIEW_GROUP_MEMBER_APPLY,mes);
             //Send_pack(fd,VIEW_GROUP_MEMBER_APPLY,"over");
        }
    
        Send_pack(fd,VIEW_GROUP_MEMBER_APPLY,"over");
    }
    /*
    
    char member[MAX_CHAR][MAX_CHAR];
    
        int i=0;
        int j=0;
    while((row1=mysql_fetch_row(result1)))
        {
            strcpy(member[i],row1[0]);
            i++;
        }
    for(j=0;j<i;j++)
        {
            char buf[BUFSIZ];
            memset(buf,0,sizeof(buf));
            sprintf(buf,"select username,status from account where id=%d",atoi(member[j]));
            printf("buf:%s\n",buf);
            ret=mysql_real_query(&mysql,buf,strlen(buf));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            MYSQL_RES *result2;  
            MYSQL_ROW  row2;
            result2=mysql_store_result(&mysql);
            row2=mysql_fetch_row(result2);
    
            char mes[256];
            memset(&mes,0,sizeof(mes));
            //账号 名字 状态
            if(atoi(row2[1])==1)
                sprintf(mes,"\033[;33m\33[1m%d\t\033[;31m\33[1m%s\t\033[;35m\33[1m%s\033[0m",atoi(member[j]),row2[0],"在线");
            else if(atoi(row2[1])==0)
                sprintf(mes,"\033[;33m\33[1m%d\t\033[;31m\33[1m%s\t\033[;35m\33[1m%s\033[0m",atoi(member[j]),row2[0],"离线");
            Send_pack(send_fd,VIEW_GROUP_MEMBER_APPLY,mes);
        }*/
    void View_add_group(int fd,char* buf)
    {
        Relation_t relation;
        memcpy(&relation,buf,sizeof(relation));
    
        char str[BUFSIZ];
        memset(str,0,sizeof(str));
        sprintf(str,"select gid,mid,status from group_member where (mid=%d and request=1)",relation.send);
        printf("str:%s\n",str);
        int ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
            printf("[%d]查询群信息失败\n",relation.send);
        }
        MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        printf("111111111111\n");
        int send_fd=Get_connfd(relation.send);
        //if((row=mysql_fetch_row(result))==NULL)
        if(row==NULL)
        {
            printf("2222222222\n");
             printf("你[%d]还没有加入任何群\n",relation.send);
            char mes[256];
             memset(&mes,0,sizeof(mes));
            sprintf(mes,"你还没有加入任何群聊");
            Send_pack(send_fd,VIEW_ADD_GROUP_APPLY,mes);
             Send_pack(fd,VIEW_ADD_GROUP_APPLY,"over");
            return ;
        }
        printf("44444444\n");
        
    
    
        memset(str,0,sizeof(str));
        sprintf(str,"select gid,mid,status from group_member where (mid=%d and request=1)",relation.send);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
            printf("[%d]查询群信息失败\n",relation.send);
        }
        MYSQL_RES *result2;  
        MYSQL_ROW  row2;
        result2=mysql_store_result(&mysql);
        while((row2=mysql_fetch_row(result2)))
        {    
            printf("3333333333333\n");
            char str[BUFSIZ];
            memset(str,0,sizeof(str));
            sprintf(str,"select group_name from groups where gid=%d",atoi(row2[0]));
            printf("str:%s\n",str);
            ret=mysql_real_query(&mysql,str,strlen(str));
            if(ret)
            {
                Mysql_with_error(&mysql);
                printf("[%d]查询群信息失败\n",relation.send);
            }
            MYSQL_RES *result1;  
            MYSQL_ROW  row1;
            result1=mysql_store_result(&mysql);
            row1=mysql_fetch_row(result1);
            
    
            char mes[256];
            memset(&mes,0,sizeof(mes));
            //群号 群名  地位
            if(atoi(row2[2])==1)
            {
                sprintf(mes,"\033[;33m\33[1m%d\t\033[;31m\33[1m%s\t\033[;36m\33[1m%s\033[0m",atoi(row2[0]),row1[0],"群主");
                Send_pack(fd,VIEW_ADD_GROUP_APPLY,mes);
            }
            else if(atoi(row2[2])==2)
            {     
                sprintf(mes,"\033[;33m\33[1m%d\t\033[;31m\33[1m%s\t\033[;36m\33[1m%s\033[0m",atoi(row2[0]),row1[0],"群管理");
                Send_pack(fd,VIEW_ADD_GROUP_APPLY,mes);
            }
            else if(atoi(row2[2])==3)
            {
                 sprintf(mes,"\033[;33m\33[1m%d\t\033[;31m\33[1m%s\t\033[;36m\33[1m%s\033[0m",atoi(row2[0]),row1[0],"群成员");
                Send_pack(fd,VIEW_ADD_GROUP_APPLY,mes);
            }
            
        }
        //while((row=mysql_fetch_row(result)));
        
        Send_pack(fd,VIEW_ADD_GROUP_APPLY,"over");
    
        printf("666666666666\n");
        printf("[%d]查询群信息成功\n",relation.send);
    
    }
    
    void Group_chat(int fd,char* buf)
    {
        Chat_message mes;
        memcpy(&mes,buf,sizeof(mes));
        printf("mes.send= %d\n",mes.sender);
        printf("mes.recv= %d\n",mes.recver);
        printf("mes.message= %s\n",mes.message);
    
    
        //先判断有没有这个群
        char str3[BUFSIZ];
        memset(str3,0,sizeof(str3));
        sprintf(str3,"select group_name from groups where gid=%d",mes.recver);
        printf("str3:%s\n",str3);
        int ret=mysql_real_query(&mysql,str3,strlen(str3));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result4;  
        MYSQL_ROW  row4;
        result4=mysql_store_result(&mysql);
        row4=mysql_fetch_row(result4);
        if(row4==NULL)
        {
            char mes1[256];
            memset(&mes1,0,sizeof(mes1));
            sprintf(mes1,"[%d]群聊不存在",mes.recver);
            Send_pack(fd,GROUP_CHAT_APPLY,mes1);
            return ;
        }
    
        //找出发送者姓名
        memset(str3,0,sizeof(str3));
        sprintf(str3,"select username from account where id=%d",mes.sender);
        printf("str3:%s\n",str3);
        ret=mysql_real_query(&mysql,str3,strlen(str3));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result3;  
        MYSQL_ROW  row3;
        result3=mysql_store_result(&mysql);
        row3=mysql_fetch_row(result3);
    
        char name[MAX];
        strcpy(name,row3[0]);
    
    //是否是群成员
    //1为已加群
        char str[BUFSIZ];
        memset(str,0,sizeof(str));
        sprintf(str,"select mid from group_member where (gid=%d and request=1)",mes.recver);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row==NULL)
        {
            char mes1[256];
            memset(&mes1,0,sizeof(mes1));
            sprintf(mes1,"你还不是该群[%d]成员",mes.recver);
            Send_pack(fd,GROUP_CHAT_APPLY,mes1);
            return ;
        }
    
    
        memset(str,0,sizeof(str));
        sprintf(str,"select mid from group_member where (gid=%d and mid!=%d)",mes.recver,mes.sender);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result2;  
        MYSQL_ROW  row2;
        result2=mysql_store_result(&mysql);
        while((row2=mysql_fetch_row(result2)))
        {
            //先插入mysql
            char str1[BUFSIZ];
            //0未发送
            //发送者  接受者  信息  状态 群号
            sprintf(str1,"insert into group_message values('%d','%d','%s','%d','%d')",mes.sender,atoi(row2[0]),mes.message,0,mes.recver);
    
            printf("str1:%s\n",str1);
            ret=mysql_real_query(&mysql,str1,strlen(str1));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
    
            printf("[%d]对[%d]群聊成员[%d]的聊天记录以及写入mysql\n",mes.sender,mes.recver,atoi(row2[0]));
    
            /*char str2[BUFSIZ];
            sprintf(str2,"select status from account where id=%d",atoi(row[0]));
            ret=mysql_real_query(&mysql,str2,strlen(str2));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
            MYSQL_RES *result1;  
            MYSQL_ROW  row1;
            result1=mysql_store_result(&mysql);
            row1=mysql_fetch_row(result1);*/
    
            int send_fd=Get_connfd(atoi(row2[0]));
            //不在线
            /*if(atoi(row1[0])==0)
            {
                continue;
            }*/
            if(send_fd<0)
            {
                continue;
            }
            //在线
            char mes1[256];
            memset(&mes1,0,sizeof(mes1));
            //发送者账号 名字 信息
            sprintf(mes1,"[%d]\t%s\t%s",mes.sender,name,mes.message);
            Send_pack(send_fd,GROUP_CHAT_APPLY,mes1);
            
    
       
       
            char str3[BUFSIZ];
            //已发改为1
            sprintf(str3,"update group_message set status=1 where (send_name=%d and recv_name=%d and message=%s and gid=%d)",mes.sender,atoi(row2[0]),mes.message,mes.recver);
            ret=mysql_real_query(&mysql,str3,strlen(str3));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
       
            printf("[%d]正在群[%d]聊天\n",mes.sender,mes.recver);
        }
    
    }
    void View_group_record(int fd,char* buf)
    {
        Chat_message mes;
        memcpy(&mes,buf,sizeof(mes));
    
        char str[BUFSIZ];
        sprintf(str,"select request from group_member where (gid=%d and mid=%d)",mes.recver,mes.sender);
        printf("str:%s\n",str);
        int ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row==NULL)
        {
            Send_pack(fd,VIEW_GROUP_RECORD_APPLY,"你还不是群成员,请先添加群");
            printf("[%d]查询群聊天记录失败\n",mes.sender);
    
             Send_pack(fd,VIEW_GROUP_RECORD_APPLY,"over");
            return ;
        }
    
        if(atoi(row[0])==2)
        {
            Send_pack(fd,VIEW_GROUP_RECORD_APPLY,"你还不是群成员,请等待管理审核");
            printf("[%d]查询群聊天记录失败\n",mes.sender);
    
             Send_pack(fd,VIEW_GROUP_RECORD_APPLY,"over");
            return ;
        }
    
        //获得群成员的id
        memset(str,0,sizeof(str));
        sprintf(str,"select mid from group_member where (gid=%d and mid!=%d)",mes.recver,mes.sender);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result1;  
        MYSQL_ROW  row1;
        result1=mysql_store_result(&mysql);
        row1=mysql_fetch_row(result1);
    
        char str1[BUFSIZ];
        memset(str1,0,sizeof(str1));
        sprintf(str1,"select send_name,message from group_message where (recv_name=%d and gid=%d) || (send_name=%d and recv_name=%d)",mes.sender,mes.recver,mes.sender,atoi(row1[0]));
        printf("str1:%s\n",str1);
        ret=mysql_real_query(&mysql,str1,strlen(str1));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result2;
        MYSQL_ROW  row2;
        result2=mysql_store_result(&mysql);
        
        int send_fd=Get_connfd(mes.sender);
        printf(">>>>>>\n");
        //循环读取每一行数据
        while((row2=mysql_fetch_row(result2)))
        {
            char str1[256];
            memset(str1,0,sizeof(str1));
            printf("1111111\n");
            sprintf(str1,"[%d]在群[%d]:%s",atoi(row2[0]),mes.recver,row2[1]);
            Send_pack(fd,VIEW_GROUP_RECORD_APPLY,str1);
        }
    
        Send_pack(fd,VIEW_GROUP_RECORD_APPLY,"over");
        printf("[%d]查询了群[%d]的聊天记录\n",mes.sender,mes.recver);
    }
    
    void Set_group_admin(int fd,char* buf)
    {
        Group_leader leader;
        memcpy(&leader,buf,sizeof(leader));
        printf("server set flag:%d\n",leader.flag);
        printf("server set sender:%d\n",leader.sender);
        printf("server set recver:%d\n",leader.recver);
        printf("server set admin:%d\n",leader.admin);
        printf("server set message:%s\n",leader.message);
    
        //查询操作者的地位
        char str[BUFSIZ];
        sprintf(str,"select status from group_member where (mid=%d and gid=%d)",leader.sender,leader.recver);
        printf("str:%s\n",str);
        int ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        int send_fd=Get_connfd(leader.sender);
    
        MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row==NULL)
        {
            printf("没有群[%d],操作无效\n",leader.recver);
            char mes[256];
            sprintf(mes,"没有该群[%d],无法操作",leader.recver);
            Send_pack(send_fd,SET_GROUP_ADMIN_APPLY,mes);
            return ;
        }
        if(atoi(row[0])!=1)
        {
            printf("[%d]不是群主,操作无效\n",leader.sender);
            char mes[256];
            memset(&mes,0,sizeof(mes));
            sprintf(mes,"不是该群[%d]的群主,无法操作",leader.recver);
            Send_pack(send_fd,SET_GROUP_ADMIN_APPLY,mes);
            return ;
        }
    
    
        //再查询成员是否存在
        memset(str,0,sizeof(str));
        sprintf(str,"select status from group_member where (mid=%d and gid=%d)",leader.admin,leader.recver);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result1;  
        MYSQL_ROW  row1;
        result1=mysql_store_result(&mysql);
        row1=mysql_fetch_row(result1);
        if(row1==NULL)
        {
    
            printf("[%d]不是群成员,操作无效\n",leader.admin);
            char mes[256];
            sprintf(mes,"[%d]不是该群[%d]成员,无法操作",leader.admin,leader.recver);
            Send_pack(send_fd,SET_GROUP_ADMIN_APPLY,mes);
            return ;
        }
        if(atoi(row1[0])==2)
        {
            printf("[%d]已经是群管理\n",leader.admin);
            char mes[256];
            sprintf(mes,"[%d]已经是该群[%d]管理",leader.admin,leader.recver);
            Send_pack(send_fd,SET_GROUP_ADMIN_APPLY,mes);
            return ;
        }
    
    
    
    
        char buff[BUFSIZ]; 
        sprintf(buff,"update group_member set status=2 where (gid=%d and mid=%d)",leader.recver,leader.admin);
        printf("buff:%s\n",buff);
        ret=mysql_real_query(&mysql,buff,strlen(buff));
        if(ret)
        {
            Mysql_with_error(&mysql);
            printf("[%d]设置管理员[%d]失败\n",leader.sender,leader.admin);
        }
        printf("[%d]设置管理员[%d]成功\n",leader.sender,leader.admin);
    
        
        char mes[256];
        sprintf(mes,"您已经成功设置[%d]为管理员",leader.admin);
        Send_pack(send_fd,SET_GROUP_ADMIN_APPLY,mes);
    
    
        int recv_fd=Get_connfd(leader.admin);
    
        if(recv_fd<0)
        {
            char mes[256];
            sprintf(mes,"[%d]不在线",leader.admin);
            Send_pack(send_fd,SET_GROUP_ADMIN_APPLY,mes);
            return;
        }
        memset(&mes,0,sizeof(mes));
        sprintf(mes,"您已经成为该群[%d]的管理员",leader.recver);
        Send_pack(recv_fd,SET_GROUP_ADMIN_APPLY,mes);
    }
    void Kick(int fd,char* buf)
    {
        Group_leader leader;
        memcpy(&leader,buf,sizeof(leader));
        printf("server kick flag:%d\n",leader.flag);
        printf("server kick sender:%d\n",leader.sender);
        printf("server kick recver:%d\n",leader.recver);
        printf("server kick admin:%d\n",leader.admin);
        printf("server kick message:%s\n",leader.message);
    
    
        //群是否存在
        char str[BUFSIZ];
        sprintf(str,"select status from group_member where (mid=%d and gid=%d)",leader.sender,leader.recver);
        printf("str:%s\n",str);
        int ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        int send_fd=Get_connfd(leader.sender);
        MYSQL_RES *result1;  
        MYSQL_ROW  row1;
        result1=mysql_store_result(&mysql);
        row1=mysql_fetch_row(result1);
        if(row1==NULL)
        {
            printf("没有群[%d],操作无效\n",leader.recver);
            char mes[256];
            sprintf(mes,"没有该群[%d],无法操作",leader.recver);
            Send_pack(send_fd,KICK_APPLY,mes);
            return ;
        }
        if(atoi(row1[0])==3)
        {
            printf("[%d]不是群管理或群主,操作无效\n",leader.sender);
            char mes[256];
            sprintf(mes,"您不是该群[%d]群管理或群主,无法操作",leader.recver);
            Send_pack(send_fd,KICK_APPLY,mes);
            return ;
        }
        int send_status=atoi(row1[0]);
        //再查询成员是否存在
        memset(str,0,sizeof(str));
        sprintf(str,"select status from group_member where (mid=%d and gid=%d)",leader.admin,leader.recver);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(row==NULL)
        {
    
            printf("[%d]不是群成员,操作无效\n",leader.admin);
            char mes[256];
            sprintf(mes,"[%d]不是该群[%d]成员,无法操作",leader.admin,leader.recver);
            Send_pack(send_fd,KICK_APPLY,mes);
            return ;
        }
        int admin_status=atoi(row[0]);
        int recv_fd=Get_connfd(leader.admin);//获得被踢成员的端口号
        //管理员地位为1或2
        //如果踢出成员地位为3
        if(send_status<admin_status)
        {
            char buff[BUFSIZ];
            sprintf(buff,"delete from group_member where gid=%d and mid=%d",leader.recver,leader.admin);
            printf("buff:%s\n",buff);
            ret=mysql_real_query(&mysql,buff,strlen(buff));
            if(ret)
            {
                Mysql_with_error(&mysql);
                printf("[%d]踢出[%d]失败\n",leader.sender,leader.admin);
            }
            printf("[%d]踢出[%d]成功\n",leader.sender,leader.admin);
            char mes[256];
            sprintf(mes,"您踢出群成员[%d]成功",leader.admin);
            Send_pack(send_fd,KICK_APPLY,mes);
    
    
            if(recv_fd<0)
            {
                char mes[256];
                sprintf(mes,"[%d]不在线",leader.admin);
                Send_pack(send_fd,KICK_APPLY,mes);
                return ;
            }
    
            memset(&mes,0,sizeof(mes));
            sprintf(mes,"您已经被管理员[%d]踢出群[%d]",leader.sender,leader.recver);
            Send_pack(recv_fd,KICK_APPLY,mes);
            return ;
        }
        else 
        {
            printf("操作者[%d]的群[%d]权限不够\n",leader.sender,leader.recver);
            char mes[256];
            sprintf(mes,"您在该群[%d]的权限不够",leader.recver);
            Send_pack(send_fd,KICK_APPLY,mes);
            return ;
        }
    
    
        /*//先查询他是不是管理员
       memset(str,0,sizeof(str));
        sprintf(str,"select mid from group_member where gid=%d and (status=1 ||status=2)",leader.recver);
        printf("str:%s\n",str);
        ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
        MYSQL_RES *result;  
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        if(leader.sender==atoi(row[0]))
        {
            printf("[%d]不是群管理或群主,操作无效\n",leader.sender);
            char mes[256];
            sprintf(mes,"您不是该群[%d]群管理或群主,无法操作",leader.recver);
            Send_pack(send_fd,KICK_APPLY,mes);
        }*/
    
    }
    int Check_relationship2(int fd,int send,int recv)
    {
        char str[BUFSIZ];
        sprintf(str,"select status from friend where (uid=%d and fid=%d and request=2) or (uid=%d and fid=%d and request=2)",send,recv,recv,send);
        printf("str:%s\n",str);
        int ret=mysql_real_query(&mysql,str,strlen(str));
        if(ret)
        {
            Mysql_with_error(&mysql);
        }
    
        MYSQL_RES *result; 
        MYSQL_ROW  row;
        result=mysql_store_result(&mysql);
        row=mysql_fetch_row(result);
        printf("here\n");
        if(row==NULL)
        {
            /*printf("why>\n");
            char mes[256];
            sprintf(mes,"[%d]还不是您的好友",recv);
            Send_pack(fd,RECV_FILE,mes);*/
            //Send_pack(fd,PRIVATE_CHAT_APPLY,"0");
            return -1;
        }
        if(atoi(row[0])==2)
        {
            char mes[256];
            sprintf(mes,"[%d]已经被屏蔽",recv);
            Send_pack(fd,RECV_FILE,mes);
            return 0;
        }
        return 1;
    }
    
    void Upload(int fd,char* buf)
    {
        file_t file;
        memcpy(&file,buf,sizeof(file));
        printf("file server flag:%d\n",file.flag);
        printf("file server send:%d\n",file.sender);
        printf("file server recv:%d\n",file.recver);
        printf("file server name:%s\n",file.file_name);
        //printf("file server message:%s\n",file.message);
        printf("file server file_size:%d\n",file.file_size);
    
    
    
        char buff[1024];
        memset(buff,0,sizeof(buff));
        char file_name[100];
        memset(file_name,0,sizeof(file_name));
      
    
        strcpy(file_name,file.file_name);
        memset(buff,0,sizeof(buff));
    
    
    
        //FILE * fp=fopen(file_name,"w+");
        //fclose(fp);
        int fp = open(file_name,O_CREAT |O_TRUNC ,0666);
        if(fp < 0)
        {
            perror("open fail");
        }
        close(fp);
    
        fp = open(file_name,O_APPEND | O_WRONLY);
        if(fp < 0)
            perror("open fail");
        memset(buff,0,sizeof(buff));
    
        int len=0;
        int write_len;
        int i=0;
        //接收文件
         while((len=recv(fd,buff,sizeof(buff),0))>0)
        {
            
            i++;
            printf("server recv len:%d\n",len);
    
            if(strcmp(buff,"end") == 0)
                break;
            if(len<0)
            {
                printf("recv file fail\n");
                return ;
            }
    
            
            write_len=write(fp,buff,len);
       
            memset(buff,0,sizeof(buff));
        }
        close(fp);
        printf("接受文件成功!\n");
    
    
    
        //int fd=Get_connfd(file.sender);
    
       int flag=Check_relationship2(fd,file.sender,file.recver);
    
        if(flag>0)
        {
            char str[BUFSIZ];
            memset(str,0,sizeof(str));
            //用户  朋友  文件名  请求为0 未发送
            sprintf(str,"insert into file (uid,fid,filename,request)values('%d','%d','%s','%d')",file.sender,file.recver,file.file_name,0);
            printf("str:%s\n",str);
            int ret=mysql_real_query(&mysql,str,strlen(str));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
    
    
            int recv_fd=Get_connfd(file.recver);
            if(recv_fd<0)
            {
                char mes[256];
                memset(&mes,0,sizeof(mes));
                sprintf(mes,"[%d]不在线",file.recver);
                Send_pack(fd,RECV_APPLY,mes);
    
                //free(buf);
                return ;
            }
    
    
            char mes[256];
            memset(&mes,0,sizeof(mes));
            sprintf(mes,"[%d]向你发送了一个文件:%s到了服务器,请去下载",file.sender,file.file_name);
            Send_pack(recv_fd,RECV_APPLY,mes);
    
    
            char str1[BUFSIZ];
            memset(str1,0,sizeof(str1));
            //用户  朋友  文件名  请求为1 已发送
            sprintf(str1,"update file set request=1 where (uid=%d and fid=%d)",file.sender,file.recver);
            printf("str1:%s\n",str1);
            ret=mysql_real_query(&mysql,str1,strlen(str1));
            if(ret)
            {
                Mysql_with_error(&mysql);
            }
        }
        else if(flag==0)
        {
            printf("[%d]和[%d]处于屏蔽状态\n",file.sender,file.recver);
            char mes1[256];
            memset(&mes1,0,sizeof(mes1));
            sprintf(mes1,"你与[%d]处于屏蔽状态,无法发送文件",file.recver);
            Send_pack(fd,RECV_APPLY,mes1);
            free(buf);
            return ;
        }
        else if(flag<0)
        {
            printf("why>\n");
            char mes[256];
            sprintf(mes,"[%d]还不是您的好友",file.recver);
            Send_pack(fd,RECV_APPLY,mes);
            return ;
        }
    }
    
    /*void* Send_file(void *arg)
    {
        arg=(char*)arg;
        file_t file;
        memcpy(&file,arg,sizeof(file));
        printf("flag= %d\n",file.flag);
    
        printf("server file_flag=%d\n",file.flag);
        printf("server file_name=%s\n",file.file_name);
        printf("server file_recver=%d\n",file.recver);
        printf("server file_sender=%d\n",file.sender);
        printf("server file_size=%d\n",file.file_size);*/
        //printf("server file_pos=%lld\n",file.pos);
    
    
        // //得到好友套接
      //  int recv_fd=Get_connfd(file.recver);
    
    //    printf("sercver file mes=%s\n",file.data);
        
        
       /* if(strcmp(file.data,"over")==0)
        {
            return NULL;
        }*/
        
    
        //向好友转发
      //  send(recv_fd,arg,1024,0);
      //  free(arg);
      //  return NULL;
       /* PACK request;
        memcpy(&request,buf,sizeof(request));
    
    
    
    	char filename[50];
    	memset(filename, 0, sizeof(filename));
    
    	printf("收到文件名:%s\n",request.data);
        strcpy(filename,request.data);
    	usleep(100000);*/
    
      
    
    
        /*char data[10];
        memset(data,0,sizeof(data));
        sprintf(data,"start");
        //发送下就绪信息
        if(Send_file_pack(fd,0,sizeof(data),data)<0)
        {
            my_err("write error",__LINE__);
        }*/
    	 
    //}
    
    void Download(int fd,char* buf)
    {
        file_t file;
        memcpy(&file,buf,sizeof(file));
        printf("server recv file name=%s",file.file_name);
    
    
        file_t file_t;
        file_t.flag=RECV_FILE;
        strcpy(file_t.file_name,file.file_name);
    
        char buff[BUFMAX];
        memcpy(buff,&file_t,sizeof(file_t));
    
        send(fd,buff,sizeof(buff),0);
    
    
        char buffer[1024];
        memset(buffer,0,sizeof(buffer));
    
        int fp=open(file_t.file_name,O_RDONLY);
        printf("file name=%s\n",file_t.file_name);
    
        if(fp<0)
        {
            printf("open fail\n");
            char mes[256];
            sprintf(mes,"文件%s不存在",file_t.file_name);
            Send_pack(fd,RECV_APPLY,mes);
            return ;
        }
    
        else 
        {
            int i = 0;
            memset(buffer,0,sizeof(buffer));
            int len= 0;
            
            while((len=read(fp,buffer,sizeof(buffer)))>0)
            {
                i++;
                
                printf("len= %d\n",len);
    
                if(send(fd,buffer,len,0) < 0)
                {
                    printf("Send file fail\n");
                    break;
                }
                
                memset(buffer,0,sizeof(buffer));
    
            }
            
            close(fp);
            memset(buffer,0,sizeof(buffer));
    
            sleep(1);
            strcpy(buffer,"end");
            send(fd,buffer,strlen(buffer),0);
            
            printf("发送成功\n");
            remove(file.file_name);
    
            char mes[256];
            memset(mes,0,sizeof(mes));
            sprintf(mes,"账户 :%d 接收文件%s成功",fd,file.file_name);
            Send_pack(fd,RECV_APPLY,mes);
        }
    
    }
    
    void Connect_mysql()
    {
        mysql_init(&mysql);
        //初始化数据库
        mysql_library_init(0,NULL,NULL);
        if(!mysql_real_connect(&mysql,"47.94.14.45","Linux_7136","18861757136","chat_room_7136",0,NULL,0))
        {
            sys_err("connect error!",__LINE__);
        }
        if(mysql_set_character_set(&mysql,"utf8"))
        {
            sys_err("set error!",__LINE__);
        }
        printf("连接MYSQL数据库成功!\n");
    }
    
    void Close_mysql(MYSQL mysql)
    {
        mysql_close(&mysql);
        //mysql_free_result(result);
        mysql_library_end();
        printf("MYSQL数据库关闭!\n");
    }
    
    void my_err(const char* err_string,int line)
    {
        fprintf(stderr,"line:%d",line);
        perror(err_string);
        exit(1);
    }
    void Clear_buf()
    {
        char ch;
        while(getchar()!='\n')
    		continue;
        /*while((ch=getchar())!='\n' && ch!=EOF)
                continue;*/
    }
    void display(char* str)
    {
        int i;
        system("clear");
        for(i=0;i<50;i++)
            putchar('-');
        putchar('\n');
        printf("       %s\n",str);
        for(i=0;i<50;i++)
            putchar('-');
        putchar('\n');
        return;
    }
    char getch()
    {
    	char ch;
    
        system("stty -echo");//不回显
        system("stty -icanon");//设置一次性读完操作,如使用getchar()读操作,不需要按回车
        ch = getchar();
        system("stty icanon");//取消上面的设置
        system("stty echo");//回显
    
        return ch;
    }
    char* Get_string(char* buf,int len)
    {
        char* str;
        int i=0;
        str=fgets(buf,len,stdin);
    	if(str!=NULL)
    	{
    		while(str[i]!='\0' && str[i]!='\n')
    			i++;
    		if(str[i]=='\n')
    			str[i]='\0';
    		else
    			while(getchar()!='\n')
    				continue;
    	}
    	return str;
    }
    void Mysql_with_error(MYSQL* mysql)
    {
        fprintf(stderr,"%s\n",mysql_error(mysql));
        mysql_close(mysql);
        return ;
    }
    
    void Send_pack(int fd,int flag,char* buf)
    {
        char str[BUFSIZ];
        message mes;
    
        mes.flag=flag;
        strcpy(mes.message,buf);
        printf("server send message:%s\n",mes.message);
        memcpy(str,&mes,sizeof(mes));
        
        printf("server send message:%s\n",mes.message);
        printf("server send flag:%d\n",mes.flag);
        if(send(fd,str,sizeof(str),0)<0)
        {
            my_err("send error!",__LINE__);
            close(fd);
        }
    }
    
    展开全文
  • linux.h" #include #include #include #include "wrang.h" #include "List.h" #include "pthreadpool.h" //#define SERV_ADDRESS "47.94.14.45" //#define SERV_ADDRESS "127.0.0.1" #define SERV_ADDRESS "192.168....

    封装过的出错函数可以去服务端代码里找

    以下是代码实现

    client.h

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <dirent.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    //#include "fcntl-linux.h"
    #include <limits.h>
    #include <termio.h>
    #include <sys/sendfile.h>
    #include "wrang.h"
    #include "List.h"
    #include "pthreadpool.h"
    
    
    
    //#define SERV_ADDRESS "47.94.14.45"
    //#define SERV_ADDRESS "127.0.0.1"
    #define SERV_ADDRESS "192.168.30.185"
    //#define SERV_ADDRESS "192.168.1.184"
    #define SERV_PORT 8013
    
    #define MAX 50
    #define MAX_CHAR 300
    #define SAVE 10
    #define BUF 2048
    
    
    #define REGISTER 1
    #define LOGIN 2
    #define MODIFY 3
    
    #define ADD_FRIEND 4
    #define DEL_FRIEND 5
    //#define QUERY_FRIEND 6
    #define PRIVATE_CHAT 7
    #define VIEW_FRIEND_LIST 8
    //#define SHOW_FRIEND_STATUS 9
    #define VIEW_CHAT_HISTORY 10
    #define SHIELD 11
    #define UNSHIELD 12
    #define SHOW_FRIEND 13
    //#define GET_FRIEND_STATUS 14
    
    #define CREAT_GROUP 15
    #define ADD_GROUP 16
    #define DEL_GROUP 17
    #define WITHDRAW_GROUP 18
    #define KICK 19
    #define SET_GROUP_ADMIN 20
    #define VIEW_ADD_GROUP 21
    #define VIEW_GROUP_MEMBER 22 
    #define VIEW_GROUP_RECORD 23
    #define SEND_FILE 24
    #define GROUP_CHAT 25
    
    #define ADD_FRIEND_APPLY 26
    #define DEL_FRIEND_APPLY 27
    #define PRIVATE_CHAT_APPLY 28
    #define SHIELD_APPLY 29
    #define UNSHIELD_APPLY 30
    #define VIEW_FRIEND_LIST_APPLY 31
    //#define VIEW_FRIEND_STATUS_APPLY 32
    
    #define CREAT_GROUP_APPLY 33
    #define ADD_GROUP_APPLY 34
    #define DEL_GROUP_APPLY 35
    #define WITHDRAW_GROUP_APPLY 36
    #define SET_GROUP_ADMIN_APPLY 37
    #define KICK_APPLY 38
    #define VIEW_ADD_GROUP_APPLY 39
    #define VIEW_GROUP_MEMBER_APPLY 40
    #define MESSAGE_RECORD 41
    
    #define REGISTER_APPLY 42
    #define LOGIN_APPLY 43
    #define PRINT_APPLY 44
    #define ADD_FRIEND_ACCEPT 45
    #define VIEW_CHAT_HISTORY_APPLY 46
    #define ADD_FRIEND_ACCEPT_APPLY 47
    #define GROUP_APPLY 48
    #define ADD_GROUP_ACCEPT 49
    #define ADD_GROUP_ACCEPT_APPLY 50
    #define VIEW_GROUP_RECORD_APPLY 51
    #define GROUP_CHAT_APPLY 52
    #define RECV_FILE 53
    //#define REGISTER_ERROR_APPLY 54
    #define EXIT 54
    //#define EXIT_APPLY 55
    #define RECV_APPLY 55
    #define UPLOAD 56
    #define DOWNLOAD 57
    
    
    #define DOWNLINE 0
    #define ONLINE 1
    #define UNBLACK 1
    #define BLACK 0
    
    #define OWNER 1
    #define ADMIN 2
    #define COMMON 3
    
    pthread_mutex_t mutex_gmb;
    pthread_cond_t cond_gmb;
    
    pthread_mutex_t mutex_msg;
    pthread_cond_t cond_msg;
    
    pthread_mutex_t mutex_login;
    pthread_cond_t cond_login;
    
    pthread_mutex_t mutex_show;
    pthread_cond_t cond_show;
    
    pthread_mutex_t mutex_add_grp;
    pthread_cond_t cond_add_grp;
    
    pthread_mutex_t mutex_gchat;
    pthread_cond_t cond_gchat;
    
    pthread_mutex_t mutex_gcord;
    pthread_cond_t cond_gcord;
    
    int cfd;
    
    int flag_login=0;
    
    typedef struct message
    {
        int flag;
        int id;
        char messsge[256];
    }message;
    
    
    typedef struct apply_messgae
    {
        int flag;
        int sender;
        int recver;
        int send_fd;
        int recv_fd;
        char message[256];
    }apply_messgae;
    
    
    
    typedef struct chat_message
    {
        int flag;
        int sender;
        int recver;
        char message[256];
        //char time[30];
    }Chat_message;
    
    
    typedef struct box
    {
        int flag;
        int sender;
        int recver;
        int send_fd;
        int recv_fd;
        char message[256];
        //struct box* next;
    }box_t;
    
    typedef struct box_node
    {
        box_t data;
        struct box_node *next;
        struct box_node *prev;
    }box_node_t,*box_list_t;
    box_list_t head;
    box_list_t fhead;
    
    
    
    typedef struct relation_info
    {
        int flag;
        int sender;
        int recver;
        int relation;
        char message[256];
    }Relation_t;
    
    typedef struct friend_info
    {
        int flag;
        int send;
        int recv;
        int status;
        int relation;
        char name[MAX];
    
        char message[256];
    }Friend_t;
    
    
    typedef struct group_info
    {
        int flag;
        int group_owner;
      
        int admin;
        char group_name[MAX];
    }Group_t;
    
    
    typedef struct group_leader
    {
        int flag;
        int sender;
        int recver;
        int admin;
        char message[256];
    }Group_leader;
    
    
    
    
    typedef struct file
    {
        int flag;
        int sender;
        int recver;
        int file_size;
        char file_name[100];
        char data[800];
    }file_t;
    int len;
    
    
    
    typedef struct account
    {
        int flag;
        int id;
        char name[MAX];
        char password[MAX];
        struct sockaddr_in useraddr;
      
        int online;      //1:开;0:关
        int connfd;      //链接套接字
    }Account_t;
    
    int username;
    int nums=0;
    void Login_menu();
    void Menu();
    void Friend_menu();
    void Group_menu();
    
    
    void Register();
    void Register_apply(char* buf);
    //void Register_error_apply(char* buf);
    
    void Login();
    void Login_apply(char* buf);
    
    void Exit();
    void Exit_apply(char* buf);
    
    void Add_friend();
    void Add_friend_apply(char* buf);
    void Friend_box();
    void Add_friend_accept_appy(char* buf);
    
    void Del_friend();
    void Del_friend_apply(char* buf);
    
    void Shield_friend();
    void Shield_friend_apply(char* buf);
    
    void Unshield_friend();
    void Unshield_friend_apply(char* buf);
    
    void View_friend();
    void View_friend_list_apply(char* buf);
    
    void Private_chat();
    void Private_chat_apply(char* buf);
    
    void View_chat_history();
    void View_chat_history_apply(char*  buf);
    
    
    void Create_group();
    void Create_group_apply(char* buf);
    
    void Add_group();
    void Add_group_apply(char* buf);
    
    void Group_box();
    void Group_apply(char* buf);
    void Add_group_accept_apply(char* buf);
    
    void Withdraw_group();
    void Withdraw_group_apply(char* buf);
    void Del_group_apply(char* buf);
    
    void View_add_group();
    void View_add_group_apply(char* buf);
    
    
    void View_group_member();
    void View_group_member_apply(char* buf);
    
    
    void Group_chat();
    void Group_chat_apply(char* buf);
    
    void View_group_record();
    void View_group_record_apply(char* buf);
    
    void Set_group_admin();
    void Set_group_admin_apply(char* buf);
    
    void Kick();
    void Kick_apply(char* buf);
    
    
    void File_menu();
    
    //void Upload();
    void Send_file();
    //void* Send_file(void *arg);
    
    void Download();
    //void* Recv_file(void *arg);
    void Recv_file(char* buf);
    void Recv_apply(char* buf);
    
    
    void Send_message(int flag,char* buf);
    
    
    
    
    void display(char* str);
    void my_err(const char* err_string,int line);
    char* Get_string(char* buf,int len);
    //char getch();
    int getch();
    void Clear_buffer();
    int Get_choice(char *choice_t);
    
    void Init_socket();
    void *Recv_pack(void* arg);
    void Turn_worker_thread();
    

    client.c

    #include "client.h"
    #define SIZE 100
    #define MAXLEN  80 //一行显示的最多字符数
    #define BUFFSIZE 32
    #define BUFMAX 1024
    
    int g_leave_len=MAXLEN; //一行剩余长度,用于输出对齐
    int g_maxlen;      //存放某目录下最长文件名的长度
    
    
    void Print_menu();
    
    int Check_data(char *num);//检查输入是否为数字
    int Get_choice_int(char* str);
    char *Time();
    void Print_apply(char* buf);
    int GetPassword(char *password);
    int get_choice_int(int min, int max);
    
    void Client_list();
    void Display(char* pathname);
    void Display_single(char* name);
    
    
    void clear_stdin();
    char* get_str(char* str,size_t len);
    
    
    
    
    
    
    int main()
    {
        Init_socket();
        
    
        List_Init(head,box_node_t);
        List_Init(fhead,box_node_t);
        pthread_mutex_init(&mutex_login,NULL);
        pthread_cond_init(&cond_login,NULL);
    
        pthread_mutex_init(&mutex_add_grp,NULL);
        pthread_cond_init(&cond_add_grp,NULL);
    
        pthread_mutex_init(&mutex_gchat,NULL);
        pthread_cond_init(&cond_gchat,NULL);
    
        pthread_mutex_init(&mutex_show,NULL);
        pthread_cond_init(&cond_show,NULL);
    
        pthread_mutex_init(&mutex_msg,NULL);
        pthread_cond_init(&cond_msg,NULL);
    
        pthread_mutex_init(&mutex_gcord,NULL);
        pthread_cond_init(&cond_gcord,NULL);
    
        pthread_mutex_init(&mutex_gmb,NULL);
        pthread_cond_init(&cond_gmb,NULL);
    
    
        Login_menu();
        //printf("开始收包\n");
        Turn_worker_thread();
        //Menu();
    
        close(cfd);
    }
    void Init_socket()
    {
        
        
        printf("客户端启动\n");
        struct sockaddr_in serv_addr;
    
    
        cfd=Socket(AF_INET,SOCK_STREAM,0);
    
        bzero(&serv_addr,sizeof(serv_addr));
        serv_addr.sin_family=AF_INET;
        serv_addr.sin_port=htons(SERV_PORT);
        inet_pton(AF_INET,SERV_ADDRESS,&serv_addr.sin_addr.s_addr);
        //serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
        Connect(cfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
    
        Turn_worker_thread();
    
        printf("客户端启动成功!\n");
    
    }
    
    //密码回显
    //返回值不包括'\0'
    int GetPassword(char *password)
    {
    	char ch;
    	int i=0;
        do
        {
            ch = getch();
            if(ch != '\n' && ch != '\r' && ch!=127)
            {
                password[i]=ch;
                printf("*");
                i++;
            }
            else if(((ch!='\n')|(ch!='\r'))&&(ch==127))
            {
                if(i>0)
                {
                    i--;
                    printf("\b \b");
                }
            }
        }while(ch!='\n'&&ch!='\r');
        password[i]='\0';
    	return i;
    }
    void Register()
    {
        Account_t register_t;
        
        char buf[BUFMAX];
        memset(buf,0,sizeof(buf));
        printf("用户名:");
        printf("[此用户名为您暂时的名字,并不是登录账号]\n");
        scanf("%s",register_t.name);
        //fgets(register_t.username,sizeof(register_t.username),stdin);
        printf("密码:");
        scanf("%s",register_t.password);
        //fgets(register_t.password,sizeof(register_t.password),stdin);
        register_t.flag=REGISTER;
    
        memcpy(buf,&register_t,sizeof(Account_t));
    
        printf("client flag:%d\n",register_t.flag);
        printf("client message:%s\n",register_t.password);
        printf("client send:%s\n",register_t.name);
        if(send(cfd,buf,sizeof(buf),0)<0)
        {
            my_err("send error!",__LINE__);
        }
    }
    void Register_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
    
        printf("--------%s\n",mes.messsge);
        int id=mes.id;
        printf("----等会输入账号时请输入系统给您的账号\n");
        printf("您的账号是:%d\n",mes.id);
        printf(">...\n");
        printf("正在返回登录界面\n");
        usleep(1000);
        Login_menu();
        //sleep(1);
        //getchar();
    }
    /*void Register_error_apply(char* buf)
    {
        message mes;
        printf("-----%s\n",mes.messsge);
    }*/
    int Check_data(char *num)
    {
        int i;
        for(i=0;num[i];i++) 
        {
            if(num[i]>'9' || num[i]<'0')//只要有非数字,就返回错误
            {
                printf("您的输入不为数字\n");
                return 0;
            }
        }
    
        if(i>100)//长度超过100位,返回错误
        {
            printf("超出数字长度\n");
            return 0;
        }
        return 1;
    }
    int Get_choice_int(char* str)
    {
        while (1)
        {
            scanf("%s",str);
            if (Check_data(str)==0)
            {
                //printf("wraning------[[[不要输入之前注册的用户名]]]\n");
                printf("输入错误,请重新输入整数\n");
            }
            else
            {
                printf("输入正确\n");
                break;
            }
        }
        int choice;
        choice=atoi(str);
        return choice;
    }
    void Login()
    {
        char buf[BUFMAX];
        Account_t account;
        account.flag=LOGIN;
        //printf("wraning------[[[不要输入之前注册的用户名]]]\n");
        printf("请输入账号:\n");
        //scanf("%d",&account.id);
        char str[SIZE];
        while (1)
        {
            scanf("%s",str);
            if (Check_data(str)==0)
            {
                printf("wraning------[[[不要输入之前注册的用户名]]]\n");
                printf("输入错误,请重新输入\n");
            }
            else
            {
                printf("账号输入正确\n");
                break;
            }
        }
    
        //printf("%d\n", atoi(str));
        account.id=atoi(str);
    
        printf("请输入密码:\n");
        scanf("%s",account.password);
        
        username=account.id;
        memcpy(buf,&account,sizeof(account));
        if(send(cfd,buf,sizeof(buf),0)<0)
        {
            my_err("send error!",__LINE__);
        }
    
        pthread_mutex_lock(&mutex_login);
        pthread_cond_wait(&cond_login,&mutex_login);
        if(flag_login==1)
            Menu();
        flag_login=0;
        pthread_mutex_unlock(&mutex_login);
    }
    void Login_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
        pthread_mutex_lock(&mutex_login);
        if(strcmp(mes.messsge,"y")==0)
        {
            printf("登录成功\n");
            flag_login=1;
        }
        else if(strcmp(mes.messsge,"a")==0)
            printf("账号已登录\n");
        else if(strcmp(mes.messsge,"n")==0)
            printf("密码错误或账户不存在\n");
        /*else if 
        {
            printf("---%s\n",mes.message);
        }*/
        
        
        pthread_cond_signal(&cond_login);
        pthread_mutex_unlock(&mutex_login);
    }
    void Login_menu()
    {
    
        int choice=-1;
       
        //int choice=-1;
        while(choice)
        {
            usleep(10000);
            //system("clear");
            printf("\t\t\033[44;34m\033[44;37m**************************\033[0m\n");
            printf("\t\t\033[1;34m*        1.注册          \033[1;34m*\033[0m \n");
            printf("\t\t\033[1;34m*        2.登录          \033[1;34m*\033[0m \n");
            printf("\t\t\033[1;34m*        0.退出          \033[1;34m*\033[0m \n");
            printf("\t\t\033[44;34m\033[44;37m**************************\033[0m\n");
            printf("\t\tchoice:");
            char choice_t[SIZE];
            choice=Get_choice_int(choice_t);
            //choice=Get_choice_int();
            //scanf("%d",&choice);
            //while(getchar()!='\n');
            //choice=Get_choice(choice_t);    
            switch(choice)
            {
                case 1:
                    puts("注册");
                    Register();
                    break;
                case 2:
                    puts("登录");
                    Login();
                    break;
                /*case 3:
                    puts("找回密码");
                    Modify_password();
                    break;*/
                default:
                    break;
            }
        }
    }
    void Exit()
    {
        message mes;
        mes.flag=EXIT;
        mes.id=username;
        char mess[256];
        sprintf(mess,"用户[%d]退出登录\n",username);
        strcpy(mes.messsge,mess);
    
        char buf[BUFMAX];
        memcpy(buf,&mes,sizeof(mes));
        if(send(cfd,buf,sizeof(buf),0)<0)
        {
            my_err("send error",__LINE__);
        }
       // Login_menu();
    }
    /*void Exit_apply(char* buf)
    {   
        pthread_mutex_lock(&mutex);
        message mes;
        printf("---%s\n",mes.messsge);
        pthread_cond_wait(&cond,&mutex);
        pthread_mutex_unlock(&mutex);
    
    }*/
    void *Recv_pack(void *arg)
    {
        pthread_t apply_id;
        char buf[BUFMAX];    
        while(1)
        {
            int n=recv(cfd,buf,sizeof(buf),0);
            if(n<0)
            {
                my_err("recv error",__LINE__);
            }
            //printf("client recv:%s\n",buf);
            //pthread_mutex_lock(&mutex);
            else if(n==0)
            {
                printf("\n服务端已经停止了工作,请退出客户端\n");
                exit(0);
            }
            int flag;
            memcpy(&flag,buf,sizeof(int));
            //printf("client recv flag:%d\n",flag);
            switch (flag)
            {
                /*case EXIT_APPLY:
                    pthread_mutex_lock(&mutex);
                    Exit_apply(buf);
                    pthread_cond_signal(&cond);
                    pthread_mutex_unlock(&mutex);
                    break;*/
                case PRINT_APPLY:
                    Print_apply(buf);
                    break;
                case REGISTER_APPLY:
                    Register_apply(buf);
                    break;
                /*case REGISTER_ERROR_APPLY:
                    Register_error_apply(buf);
                    break;*/
                case LOGIN_APPLY:
                    Login_apply(buf);
                    break;
                case ADD_FRIEND_APPLY:
                    Add_friend_apply(buf);
                    break;
                case ADD_FRIEND_ACCEPT_APPLY:
                    Add_friend_accept_appy(buf);
                case DEL_FRIEND_APPLY:
                    Del_friend_apply(buf);
                    break;
                //一起实现
                //case SHOW_FRIEND_STATUS_APPLY:
                case VIEW_FRIEND_LIST_APPLY:
                    View_friend_list_apply(buf);
                    break;
                case SHIELD_APPLY:
                    Shield_friend_apply(buf);
                    break;
                case UNSHIELD_APPLY:
                    Unshield_friend_apply(buf);
                    break;
                case PRIVATE_CHAT_APPLY:
                    Private_chat_apply(buf);
                    break;
                case VIEW_CHAT_HISTORY_APPLY:
                    View_chat_history_apply(buf);
                    break;
                case CREAT_GROUP_APPLY:
                    Create_group_apply(buf);
                    break;
                case ADD_GROUP_APPLY:
                    Add_group_apply(buf);
                    break;
                case GROUP_APPLY:
                    Group_apply(buf);
                    break;
                case ADD_GROUP_ACCEPT_APPLY:
                    Add_group_accept_apply(buf);
                    break;
                //一起实现
                case DEL_GROUP_APPLY:
                    Del_group_apply(buf);
                    break;
                case WITHDRAW_GROUP_APPLY:
                    Withdraw_group_apply(buf);
                    break;
                case VIEW_GROUP_MEMBER_APPLY:
                    View_group_member_apply(buf);
                    break;
                case VIEW_ADD_GROUP_APPLY:
                    View_add_group_apply(buf);
                    break;
                case GROUP_CHAT_APPLY:
                    Group_chat_apply(buf);
                    break;
                case VIEW_GROUP_RECORD_APPLY:
                    View_group_record_apply(buf);
                    break;
                case SET_GROUP_ADMIN_APPLY:
                    Set_group_admin_apply(buf);
                    break;
                case KICK_APPLY:
                    Kick_apply(buf);
                    break;
                    //
                //case SEND_FILE:
                  //  {
                        //printf(">>>>>>\n");
                    //    Recv_file(buf);
                        //printf("??????\n");
                      //  break;
                    //}
                case RECV_FILE:
                    Recv_file(buf);
                    break;
                case RECV_APPLY:
                    Recv_apply(buf);
                    break;
            }
            //pthread_mutex_unlock(&mutex);
        }
        memset(buf,0,sizeof(buf));
    }
    void Turn_worker_thread()
    {
        pthread_t pid_recv;
        pthread_create(&pid_recv,NULL,Recv_pack,NULL);
    }
    void Friend_box()
    {
        //printf("111");
        Relation_t relation;
        //box_list_t pos=head;
        box_list_t pos;
        List_ForEach(head,pos)
        {
            if(pos->data.recver==username)
            {
                printf("uid\tsender\trecver\tmessage\n");
                printf("%d\t%d\t%d\t%s\n",username,pos->data.sender,pos->data.recver,pos->data.message);
            //pos=pos->next;
                break;
            }
        }
        List_ForEach(head,pos)
        {
            if(pos->data.recver==username)
            {
                List_DelNode(pos);
                char ch;
                printf("请输入同意还是不同意:\n");
                printf("同意[y or Y]不同意[n]");
            scanf("%c",&ch);
            if(ch=='Y' || ch=='y')
            {
                    char str[BUFMAX];
                    memset(str,0,sizeof(str));
                    
                    relation.flag=ADD_FRIEND_ACCEPT;
                    strcpy(relation.message,"y");
                    relation.sender=pos->data.recver;//被申请者
                    relation.recver=pos->data.sender;//申请者
                    //mes.send_fd=box_tt.send_fd;//申请者客户端端口号
                    //mes.recv_fd=box_tt.recv_fd;//被申请者客户端端口号
                    memcpy(str,&relation,sizeof(relation));
                    if(send(cfd,str,sizeof(str),0)<0)
                    {
                        my_err("send error",__LINE__);
                    }
                    printf("同意好友申请发送成功\n");
            }
            else
            {
                char str[BUFMAX];
                memset(str,0,sizeof(str));
                    
                relation.flag=ADD_FRIEND_ACCEPT;
                strcpy(relation.message,"n");
                relation.sender=pos->data.recver;//被申请者
                relation.recver=pos->data.sender;//申请者
                //mes.send_fd=box_tt.send_fd;//申请者客户端端口号
                //mes.recv_fd=box_tt.recv_fd;//被申请者客户端端口号
                memcpy(str,&relation,sizeof(relation));
                if(send(cfd,str,sizeof(str),0)<0)
                {
                    my_err("send error",__LINE__);
                }
                printf("拒绝好友申请发送成功\n");
            }
            }
        }
        /*
        system("clear");
        box_list_t pos;
        while(pos!=NULL)
        {
            printf("好友消息盒子信息\n");
            printf("uid\tsend_fd\trecv_fd\t消息\n");
            printf("%d\t%d\t%d\t%s\t",username,pos->data.send_fd,pos->data.recv_fd,pos->data.message);
            pos=pos->next;
        }
        apply_messgae mes;
        char str[BUFMAX];
        memset(&mes,0,sizeof(mes));
        mes.flag=ADD_FRIEND_ACCPET;
        //strcpy(mes.message,"y");
        mes.sender=username;//被申请者
        mes.recver=pos->data.sender;//申请者
        mes.send_fd=pos->data.send_fd;//申请者客户端端口号
        mes.recv_fd=pos->data.recv_fd;//被申请者客户端端口号
        memcpy(str,&mes,sizeof(mes));
        printf("cfd:%d\n",cfd);
        int id;
        List_ForEach(head,pos)
        {
            apply_messgae mes;
            memcpy(&mes,buf,sizeof(mes));
            printf("[%d]申请向您添加为好友\n",mes.recver);
            char ch;
            scanf("%c",&ch);
            getchar();
            if(ch=='Y' || ch=='y')
            {
                //strcpy(mes.message,"y");
                if(send(,str,sizeof(str),0)<0)
                {
                    my_err("send error",__LINE__);
                }
                printf("同意好友申请发送成功\n");
            }
            else
            {
                char str1[BUFMAX];
                //memset(&mes,0,sizeof(mes));
                mes.flag=ADD_FRIEND_ACCPET;
                strcpy(mes.message,"n");
                mes.sender=username;//被申请者
                mes.recver=pos->data.sender;//申请者
                memcpy(str1,&mes,sizeof(mes));
                if(send(cfd,str1,sizeof(str1),0)<0)
                {
                    my_err("send error",__LINE__);
                }
                printf("拒绝好友申请发送成功\n");
            }
         
        }   
    */
        
    }
    
    void Print_apply(char* buf)
    {
        
        message mes;
        memcpy(&mes,buf,sizeof(mes));
        //pthread_mutex_lock(&mutex);
       
        printf("%s\n",mes.messsge);
        //pthread_cond_wait(&cond,&mutex);
        //pthread_mutex_unlock(&mutex);    
    }
    void Add_friend_accept_appy(char* buf)
    {
        apply_messgae mes;
        memcpy(&mes,buf,sizeof(mes));
        printf("%s\n",mes.message);
    }
    void Add_friend_apply(char* buf)
    {
        //apply_messgae mes;
        box_t box;
        memcpy(&box,buf,sizeof(box));
        
    
        
        box_list_t new;
        new=(box_list_t)malloc(sizeof(box_node_t));
        printf("你有请求消息来了,在消息盒子\n");
       
    
        new->data.flag=box.flag;
        new->data.sender=box.sender;//申请者
        new->data.recver=box.recver;//被申请者
        new->data.send_fd=box.send_fd;//申请者客户端端口号
        new->data.recv_fd=box.recv_fd;//被申请者客户端端口号
        strcpy(new->data.message,box.message);
        List_AddTail(head,new);
    
       // printf("client message:%s\n",new->data.message);
    
        //printf("server send message:%s\n",box.message);
        //printf("server send flag:%d\n",box.flag);
        //printf("server/ friend send id:%d\n",box.sender);
        //printf("server/ friend recv id:%d\n",box.recver);
        //朋友客户端号
        //printf("server/ friend recv_fd:%d\n",new->data.recv_fd);
        //printf("server/ friend send_fd:%d\n",new->data.send_fd);
        
    
    
        usleep(100);
    
        /*if(mes.sender==username)
        {
            printf("不能向自己发送好友申请\n");
            return;
        }*/
     
    }
    void Add_friend()
    {
        int id;
        puts("请输入想要添加好友的账号[id]:\n");
        scanf("%d",&id);
        if(id==username)
        {
            printf("请不要添加自己为好友\n");
            return ;
        }
        
        char buf[BUFMAX];
        sprintf(buf,"%d",id);
        printf("buf:%s\n",buf);
    
        char str[BUFMAX];
        memset(str,0,sizeof(str));
        Relation_t relation;
        relation.flag=ADD_FRIEND;
        relation.sender=username;//发送者
        relation.recver=id;//被申请者
        strcpy(relation.message,"");
        memcpy(str,&relation,sizeof(relation));
    
        //printf("client flag:%d\n",relation.flag);
        //printf("client message:%s\n",relation.message);
        //printf("client send:%d\n",relation.sender);
        //printf("client recv:%d\n",relation.recver);
    
        if(send(cfd,str,sizeof(str),0)<0)
        {
            my_err("send error!",__LINE__);
        }
    }
    
    
    void Del_friend()
    {
        
        int id;
        puts("请输入要删除的好友账号:");
        scanf("%d",&id);
    
        char buf[BUFMAX];
        sprintf(buf,"%d",id);
        printf("buf:%s\n",buf);
    
        char str[BUFMAX];
        memset(str,0,sizeof(str));
        Relation_t relation;
        relation.flag=DEL_FRIEND;
        relation.sender=username;//发送者
        relation.recver=id;//被申请者
        strcpy(relation.message,"");
        memcpy(str,&relation,sizeof(relation));
    
        //printf("client flag:%d\n",relation.flag);
       // printf("client message:%s\n",relation.message);
       // printf("client send:%d\n",relation.sender);
       // printf("client recv:%d\n",relation.recver);
    
        if(send(cfd,str,sizeof(str),0)<0)
        {
            my_err("send error!",__LINE__);
        }
    
        return;
    }
    void Del_friend_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
    
        printf("%s\n",mes.messsge);
    
    }
    void Shield_friend()
    {
        int id;
        printf("请输入你要屏蔽的好友账号:\n");
        scanf("%d",&id);
        char buf[BUFMAX];
        sprintf(buf,"%d",id);
        //printf("buf:%s\n",buf);
    
        char str[BUFMAX];
        memset(str,0,sizeof(str));
        Relation_t relation;
        relation.flag=SHIELD;
        relation.sender=username;//发送者
        relation.recver=id;//被申请者
        strcpy(relation.message,"");
        memcpy(str,&relation,sizeof(relation));
    
        if(send(cfd,str,sizeof(str),0)<0)
        {
            my_err("send error",__LINE__);
        }
    
        /*printf("client flag:%d\n",relation.flag);
        printf("client message:%s\n",relation.message);
        printf("client send:%d\n",relation.sender);
        printf("client recv:%d\n",relation.recver);*/
    
    
    }
    void Shield_friend_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
    
        printf("%s\n",mes.messsge);
    }
    void Unshield_friend()
    {
        
        int id;
        printf("请输入你要解除屏蔽的好友账号:\n");
        scanf("%d",&id);
        char buf[BUFMAX];
        sprintf(buf,"%d",id);
        //printf("buf:%s\n",buf);
    
        char str[BUFMAX];
        memset(str,0,sizeof(str));
        Relation_t relation;
        relation.flag=UNSHIELD;
        relation.sender=username;//发送者
        relation.recver=id;//被申请者
        strcpy(relation.message,"");
        memcpy(str,&relation,sizeof(relation));
    
        if(send(cfd,str,sizeof(str),0)<0)
        {
            my_err("send error",__LINE__);
        }
    
       /* printf("client flag:%d\n",relation.flag);
        printf("client message:%s\n",relation.message);
        printf("client send:%d\n",relation.sender);
        printf("client recv:%d\n",relation.recver); */
    }
    void Unshield_friend_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
    
        printf("%s\n",mes.messsge);
    }
    
    //一起实现
    //void Show_friend_status();
    void View_friend_list()
    {
        
        pthread_mutex_lock(&mutex_show);
        printf("-----------------------\n");
        printf("账号\t姓名\t状态\t关系\n");
        
    
        char str[BUFMAX];
        memset(str,0,sizeof(str));
        Friend_t friend;
        friend.flag=VIEW_FRIEND_LIST;
        friend.send=username;//发送者
        friend.recv=username;//接收者
        strcpy(friend.message,"");
        memcpy(str,&friend,sizeof(friend));
    
        if(send(cfd,str,sizeof(str),0)<0)
        {
            my_err("send error",__LINE__);
        }
        printf("-----------------------------\n");
        //printf("client flag:%d\n",friend.flag);
        //printf("client message:%s\n",friend.message);
        //printf("client send:%d\n",friend.send);
        //printf("client recv:%d\n",friend.recv); 
        pthread_cond_wait(&cond_show,&mutex_show);
         printf("=========================\n");
        pthread_mutex_unlock(&mutex_show);    
    }
    void View_friend_list_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
        //printf("%s\n",mes.messsge);
        if(strcmp(mes.messsge,"over"))
        {
            printf("%s\n",mes.messsge);
        }
        else
        {
            pthread_mutex_lock(&mutex_show);
            pthread_cond_signal(&cond_show);
            pthread_mutex_unlock(&mutex_show);
        }
       //getch();
       //Friend_menu();
       //usleep(1000);
        return;
    }
    
    
    void Private_chat()
    {
        int id;
        printf("请输入要私聊的好友账号:\n");
        scanf("%d",&id);
        //Chat_message mes;
        //memset(&mes, 0, sizeof(message));
        //char time[100];
        //char str[BUFMAX];
    
        /*char time[30];
    
        memset(time,0,sizeof(time));
        strcpy(time,Time());*/
        system("clear");
    
        printf("-----正在与 %d 聊天-----\n",id);
        printf("   --- quit 退出 ---\n");
       // getchar();
        //printf("=============================\n");
        //printf("time:%s",time);
        //scanf("%s",buf);
        //fgets(buf,sizeof(buf),stdin);
        while(1)
        {
    
            char str[BUFMAX];
           
            Chat_message mes;
            mes.flag=PRIVATE_CHAT;
            mes.sender=username;
            mes.recver=id;
            //strcpy(mes.time,time);
            //printf("client send:%s\n",time);
            char buf[256];
            memset(buf,0,sizeof(buf));
             fgets(buf,sizeof(buf),stdin);
            if(strcmp(buf,"quit\n")==0)
                break;
    
            strcpy(mes.message,buf);
    
            //保存光标位置
             //printf("\033[s");
            //fflush(stdout);
          
    
            //printf("\33[u");
            //fflush(stdout);
            /*printf("\33[s");
            fflush(stdout);
    
            //清除从光标到行尾的内容
            printf("\33[K\n\33[K\n\33[K\n");
            fflush(stdout);
            //恢复光标位置
            printf("\33[u");
            fflush(stdout);*/
    
            memcpy(str,&mes,sizeof(mes));
            if(send(cfd,str,sizeof(str),0)<0)
            {
                my_err("send error!",__LINE__);
            }
            //memset(buf,0,sizeof(buf));
            //memset(str,0,sizeof(str));
            //memset(&mes, 0, sizeof(message));
    
    
            //fgets(buf,sizeof(buf),stdin);
            //scanf("%s",buf);
        }
       /* printf("按任意键返回\n");
        getchar();*/
        return ;
    }
    char *Time()
    {
        /*time_t time_t;
        char timep[100];
        int len;
        //时间
        time(&time_t);
        strcpy(timep,ctime(&time_t));
        len=strlen(timep);
        timep[len-5]='\0'; */
    
        char* str;
        time_t  time_t;
        time(&time_t);
    
        str=ctime(&time_t);
        str[strlen(str-1)]='\0';
        return str;
    }
    void Private_chat_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
    
            //printf("                       %s",mes.time);
           printf("账号\t姓名\t消息\n");
    
            printf("%s\n",mes.messsge); 
    }
    
    
    void View_chat_history()
    {
        pthread_mutex_lock(&mutex_msg);
        int id;
        //system("clear");
        printf("请输入要查询聊天的好友账号:");
        scanf("%d",&id);
        
        char buf[BUFMAX];
        Chat_message mes;
        mes.flag=VIEW_CHAT_HISTORY;
        strcpy(mes.message,"");
        mes.sender=username;
        mes.recver=id;
        memcpy(buf,&mes,sizeof(mes));
    
        printf("\n");
        printf("--------------------聊天记录-------------------------\n");
    
        if(send(cfd,buf,sizeof(buf),0)<0)
        {
            my_err("send error!",__LINE__);
        }
    
    
        pthread_cond_wait(&cond_msg,&mutex_msg);
        pthread_mutex_unlock(&mutex_msg);
    }
    void View_chat_history_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
        
        if(strcmp(mes.messsge,"over"))
        {
            printf("%s\n",mes.messsge);
        } 
        else
        {
            pthread_mutex_lock(&mutex_msg);
            pthread_cond_signal(&cond_msg);
            pthread_mutex_unlock(&mutex_msg);       
        }
       // getch();
        return;
    
    }
    
    void Create_group()
    {
        char buf[BUFMAX];
        Group_t group; 
     
    
        printf("请输入群名:");
        scanf("%s",group.group_name);
        printf("此群名只是当前群的称谓,创建者id为该群唯一标识\n");
        group.group_owner=username;
        group.flag=CREAT_GROUP;
        memcpy(buf,&group,sizeof(group));
        if(send(cfd,buf,sizeof(buf),0)<0)
        {
            my_err("send error",__LINE__);
        }    
    }
    void Create_group_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
    
        printf("%s\n",mes.messsge);
    
    }
    void Add_group()
    {
       int id;
       printf("请输入要加入的群号:\n");
       scanf("%d",&id);
    
        char buf[BUFMAX];
        Relation_t relation;
        relation.flag=ADD_GROUP;
        relation.sender=username;
        relation.recver=id;
        strcpy(relation.message,"");
        memcpy(buf,&relation,sizeof(relation));
        if(send(cfd,buf,sizeof(buf),0)<0)
        {
            my_err("send error",__LINE__);
        }    
    }
    void Add_group_apply(char* buf)
    {
        box_t box;
        memcpy(&box,buf,sizeof(box));
        
    
        
        box_list_t new;
        new=(box_list_t)malloc(sizeof(box_node_t));
        printf("你有群请求消息来了,在消息盒子\n");
       
    
        new->data.flag=box.flag;
        new->data.sender=box.sender;//申请者
        new->data.recver=box.recver;//管理员
        new->data.send_fd=box.send_fd;//申请者客户端端口号
        new->data.recv_fd=box.recv_fd;//管理员客户端端口号
        strcpy(new->data.message,box.message);
        List_AddTail(fhead,new);
    
       /* printf("client message:%s\n",new->data.message);
    
        printf("server send message:%s\n",box.message);
        printf("server send flag:%d\n",box.flag);
        printf("server/ group apply send id:%d\n",box.sender);
        printf("server/ group apply recv id:%d\n",box.recver);
        //管理员客户端号
        printf("server/ group recv_fd:%d\n",new->data.recv_fd);
        printf("server/ group send_fd:%d\n",new->data.send_fd);*/
        
    
    
        usleep(100);
    }
    void Group_box()
    {
        //printf("111");
        Relation_t relation;
    
        box_list_t pos;
        List_ForEach(fhead,pos)
        {
            if(pos->data.recver==username)
            {
                printf("uid\tsender\trecver\tmessage\n");
                printf("%d\t%d\t%d\t%s\n",username,pos->data.sender,pos->data.recver,pos->data.message);
            //pos=pos->next;
                break;
            }
        }
        List_ForEach(fhead,pos)
        {
            if(pos->data.recver==username)
            {
                List_DelNode(pos);
                char ch;
                printf("请输入同意还是不同意:\n");
                 printf("同意[y or Y]不同意[n]");
                scanf("%c",&ch);
                if(ch=='Y' || ch=='y')
                {
                        char str[BUFMAX];
                        memset(str,0,sizeof(str));
                        
                        relation.flag=ADD_GROUP_ACCEPT;
                        strcpy(relation.message,"y");
                        relation.sender=pos->data.recver;//管理员
                        relation.recver=pos->data.sender;//申请者
                        //mes.send_fd=box_tt.send_fd;//申请者客户端端口号
                        //mes.recv_fd=box_tt.recv_fd;//被申请者客户端端口号
                        memcpy(str,&relation,sizeof(relation));
                        if(send(cfd,str,sizeof(str),0)<0)
                        {
                            my_err("send error",__LINE__);
                        }
                        printf("同意群申请发送成功\n");
                }
                else
                {
                    char str[BUFMAX];
                    memset(str,0,sizeof(str));
                        
                    relation.flag=ADD_GROUP_ACCEPT;
                    strcpy(relation.message,"n");
                    relation.sender=pos->data.recver;//被申请者
                    relation.recver=pos->data.sender;//申请者
                    //mes.send_fd=box_tt.send_fd;//申请者客户端端口号
                    //mes.recv_fd=box_tt.recv_fd;//被申请者客户端端口号
                    memcpy(str,&relation,sizeof(relation));
                    if(send(cfd,str,sizeof(str),0)<0)
                    {
                        my_err("send error",__LINE__);
                    }
                    printf("拒绝群申请发送成功\n");
                }
            }
        }
    }
    void Add_group_accept_apply(char* buf)
    {
        apply_messgae mes;
        memcpy(&mes,buf,sizeof(mes));
        printf("%s\n",mes.message);
    }
    void Group_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
    
        printf("%s\n",mes.messsge);
    }
    
    //一起实现
    //void Del_group();
    void Withdraw_group()
    {
        int id;
        printf("请输入你要退出的群号:");
        scanf("%d",&id);
    
        char buf[BUFMAX];
        Relation_t relation;
        relation.flag=WITHDRAW_GROUP;
        relation.sender=username;
        relation.recver=id;
        strcpy(relation.message,"");
        memcpy(buf,&relation,sizeof(relation));
        if(send(cfd,buf,sizeof(buf),0)<0)
        {
            my_err("send error",__LINE__);
        }    
        
        
    
    }
    void Withdraw_group_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
    
        printf("%s\n",mes.messsge);
    }
    void Del_group_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
    
        printf("%s\n",mes.messsge);
    }
    
    void View_group_member()
    {
        pthread_mutex_lock(&mutex_gmb);
        int id;
        printf("请输入你要查询的群号:");
        scanf("%d",&id);
        
        char buf[BUFMAX];
        Relation_t relation;
        relation.flag=VIEW_GROUP_MEMBER;
        relation.sender=username;
        relation.recver=id;
        strcpy(relation.message,"");
        memcpy(buf,&relation,sizeof(relation));
    
        printf("----------------------------\n");
        printf("账号\t姓名\t状态\n");
        if(send(cfd,buf,sizeof(buf),0)<0)
        {
            my_err("send error",__LINE__);
        }    
    
        printf("-----------------------------\n");
        pthread_cond_wait(&cond_gmb,&mutex_gmb);
        printf("=========================\n");
        pthread_mutex_unlock(&mutex_gmb);
     
    }
    void View_group_member_apply(char* buf)
    {
        
        message mes;
        memcpy(&mes,buf,sizeof(mes));
        if(strcmp(mes.messsge,"over"))
        {
            printf("%s\n",mes.messsge);
        }
        else
        {
            pthread_mutex_lock(&mutex_gmb);
            pthread_cond_signal(&cond_gmb);
            pthread_mutex_unlock(&mutex_gmb);
        }
        //getch();
        return;
    }
    void View_add_group()
    {
        pthread_mutex_lock(&mutex_add_grp);
    
        char str[BUFMAX];
        memset(str,0,sizeof(str));
        Relation_t relation;
        relation.flag=VIEW_ADD_GROUP;
        relation.sender=username;//发送者
        relation.recver=username;//群号
        strcpy(relation.message,"");
        memcpy(str,&relation,sizeof(relation));
    
        printf("----------------------------\n");
        printf("群号\t群名\t地位\n");
        if(send(cfd,str,sizeof(str),0)<0)
        {
            my_err("send error",__LINE__);
        }
        printf("-----------------------------\n");
         //阻塞等待
        pthread_cond_wait(&cond_add_grp,&mutex_add_grp);
        printf("=============================\n");
        pthread_mutex_unlock(&mutex_add_grp);
     
    }
    void View_add_group_apply(char* buf)
    {
        
        message mes;
        memcpy(&mes,buf,sizeof(mes));
    
        if(strcmp(mes.messsge,"over"))
        {
            printf("%s\n",mes.messsge);
        }
        else
        {
            //唤醒阻塞状态的好友列表
            pthread_mutex_lock(&mutex_add_grp);
            pthread_cond_signal(&cond_add_grp);
            pthread_mutex_unlock(&mutex_add_grp);
        }
       // getch();
    	return;
    
    }
    
    
    void Group_chat()
    {
        int id;
        printf("请输入要发送聊天的群账号:\n");
        scanf("%d",&id);
        while(getchar()!='\n');
        //Chat_message mes;
        //memset(&mes, 0, sizeof(message));
      
     
        //char buf[256];
        //char time[100];
        //char str[BUFMAX];
    
        /*char time[30];
    
        memset(time,0,sizeof(time));
        strcpy(time,Time());*/
        system("clear");
    
        printf("-----正在与 %d 群里聊天-----\n",id);
        printf("   --- quit 退出 ---\n");
    
        printf("=============================\n");
        //printf("time:%s",time);
        //fgets(buf,sizeof(buf),stdin);
        //scanf("%s",buf);
        while(1)
        {
    
            char str[BUFMAX];
           
            Chat_message mes;
            mes.flag=GROUP_CHAT;
            mes.sender=username;
            mes.recver=id;
            //strcpy(mes.time,time);
            //printf("client send:%s\n",time);
    
            char buf[256];
            memset(buf,0,sizeof(buf));
             fgets(buf,sizeof(buf),stdin);
            if(strcmp(buf,"quit\n")==0)
                break;
    
            strcpy(mes.message,buf);
            memcpy(str,&mes,sizeof(mes));
            if(send(cfd,str,sizeof(str),0)<0)
            {
                my_err("send error!",__LINE__);
            }
            //memset(buf,0,sizeof(buf));
            //memset(str,0,sizeof(str));
            //memset(&mes, 0, sizeof(message));
            //scanf("%s",buf);
    
            //fgets(buf,sizeof(buf),stdin);
    
        }
    
    }
    void Group_chat_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
        /*if(strcmp(mes.message,"d")==0)
            printf("[%d]不在线 \n",mes.recver);*/
        //else
        //{
            //printf("                       %s",mes.time);
        
      
                printf("账号\t名字\t信息\n");
                printf("%s\n",mes.messsge);
       
    }
    void View_group_record()
    {
        pthread_mutex_lock(&mutex_gcord);
        printf("--------------------聊天记录-------------------------\n");
    
        int id;
        //system("clear");
        printf("请输入要查询聊天的群账号:");
        scanf("%d",&id);
        
        char buf[BUFMAX];
        Chat_message mes;
        mes.flag=VIEW_GROUP_RECORD;
        strcpy(mes.message,"");
        mes.sender=username;
        mes.recver=id;
        memcpy(buf,&mes,sizeof(mes));
        if(send(cfd,buf,sizeof(buf),0)<0)
        {
            my_err("send error!",__LINE__);
        }
        
    
        pthread_cond_wait(&cond_gcord,&mutex_gcord);
         printf("=========================\n");
        pthread_mutex_unlock(&mutex_gcord);  
    }
    void View_group_record_apply(char* buf)
    {
      
        message mes;
        memcpy(&mes,buf,sizeof(mes));
        if(strcmp(mes.messsge,"over"))
        {
             printf("%s\n",mes.messsge);
        }
        else
        {
            pthread_mutex_lock(&mutex_gcord);
            pthread_cond_signal(&cond_gcord);
            pthread_mutex_unlock(&mutex_gcord);     
               
        }
        //  getch();
        return;
    }
    
    void Set_group_admin()
    {
        char buf[BUFMAX];
        Group_leader leader;
        leader.flag=SET_GROUP_ADMIN;
        leader.sender=username;
        printf("请输入你设置的群号:");
        scanf("%d",&leader.recver);
        printf("请输入你要设置管理员的账号:");
        scanf("%d",&leader.admin);
        strcpy(leader.message,"");
    
        memcpy(buf,&leader,sizeof(leader));
        if(send(cfd,buf,sizeof(buf),0)<0) 
        {
            my_err("send error",__LINE__);
        }
    }
    void Set_group_admin_apply(char *buf)
    {
        
        message mes;
        memcpy(&mes,buf,sizeof(mes));
        printf("%s\n",mes.messsge);
    }
    void Kick()
    {
        char buf[BUFMAX];
        Group_leader leader;
        leader.flag=KICK;
        leader.sender=username;
        printf("请输入你设置的群号:");
        scanf("%d",&leader.recver);
        printf("请输入你要删除成员的账号:");
        scanf("%d",&leader.admin);
        strcpy(leader.message,"");
    
        memcpy(buf,&leader,sizeof(leader));
        if(send(cfd,buf,sizeof(buf),0)<0) 
        {
            my_err("send error",__LINE__);
        }
        
    }
    void Kick_apply(char *buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
        printf("%s\n",mes.messsge);
    }
    void File_menu()
    {
        int choice=1;
        system("clear");
        
        while(choice)
        {
            usleep(1000);
            printf("\t\t\033[;33m\033[1m*********文件管理**********\033[0m\n");
            printf("\t\t\033[1;33m|\033[0m-1.查看本地客户端目录文件-\033[1;33m|\033[0m\n");
            printf("\t\t\033[1;33m|\033[0m----------2.上传----------\033[1;33m|\033[0m\n");
            printf("\t\t\033[1;33m|\033[0m----------3.下载----------\033[1;33m|\033[0m\n");
            printf("\t\t\033[1;33m|\033[0m----------0.退出----------\033[1;33m|\033[0m\n");
    
            printf("\t\tchoice:\n");
            //printf("请输入选择:");
            scanf("%d",&choice);
            while(getchar() != '\n');
            switch (choice)
            {
                case 1:
                    Client_list();
                    break;
                case 2:
                   //Upload();
                    Send_file();
                    break;
                case 3:
                    Download();
                    break;
                case 0:
                    break;
            }
        }
        return;
    }
    void Client_list()
    {
        printf("当前客户端目录列表:\n");
    	DIR *dir;
    	
    	struct dirent *dirent;
        char name[256];
        int i,j;
        int count=0;
    
    
        char filenames[256][PATH_MAX+1],temp[PATH_MAX+1];
        //获取该目录下文件总数和最长的文件名
        dir=opendir("."); //统计文件名数量
        if(dir==NULL)
            my_err("opendir",__LINE__);
        while((dirent=readdir(dir))!=NULL)
        {
            if(g_maxlen<strlen(dirent->d_name))
                    g_maxlen=strlen(dirent->d_name);
            count++;
        }
    
            if(count>256)
                my_err("too mant files under this dir",__LINE__);
            
            closedir(dir);
        
    
        int len=strlen(".");
            //获取该目录下所有的文件名
            dir=opendir(".");
            for(i=0;i<count;i++)
            {
                dirent=readdir(dir);
                if(dirent==NULL)
                    my_err("readdir",__LINE__);
    
                strncpy(filenames[i],"",len);
                filenames[i][len]='\0';
                strcat(filenames[i],dirent->d_name);
                filenames[i][len+strlen(dirent->d_name)]='\0';
            }
            closedir(dir);
    
            //使用冒泡法对文件名进行排序,排序后文件名按字母顺序存储于filenames
            for(i=0;i<count-1;i++)
            {
                for(j=0;j<count-1-i;j++)
                {
                    if(strcmp(filenames[j],filenames[j+1])>0)
                    {
                        strcpy(temp,filenames[j+1]);
                        temp[strlen(filenames[j+1])]='\0';
                        strcpy(filenames[j+1],filenames[j]);
                        filenames[j+1][strlen(filenames[j])]='\0';
                        strcpy(filenames[j],temp);
                        filenames[j][strlen(temp)]='\0';
                    }
                }
            }
        for(i=0;i<count;i++)
            Display(filenames[i]);
    
    	/*while((dirent=readdir(dir))!=NULL)
    	{
    		printf("%s ",dirent->d_name);
            printf("\n");
    
        }*/
    
          
    
    	printf("\n");
    
        printf("\033[;33m请按任意键继续\033[0m\n");
    	getch();
    	return;
    }
    void Display(char* pathname)
    {
        int i,j;
        struct stat buf;
        char name[256];
    
        //从路径中解析出文件名
        for(i=0,j=0;i<strlen(pathname);i++)
        {
            if(pathname[i]=='/')
            {
                j=0;
                continue;
            }
            name[j++]=pathname[i];
        }
        name[j]='\0';
        
    
        //如果本行不足以打印一个文件名则换行
        if(g_leave_len<g_maxlen)
        {
            printf("\n");
            g_leave_len=MAXLEN;
        }
    
        len=strlen(name);
        len=g_maxlen-len;
       
        printf("\033[;33m%s\033[0m",name);
    
        for(i=0;i<len;i++)
            printf(" ");
    
        printf(" ");
    
        //下面的2指示空两格
        g_leave_len-=(g_maxlen+2);//一行中剩下的字符数量
    
        //Display_single(name);
    }
    
    /*void Display_single(char* name)
    {
        int i,len;
         //如果本行不足以打印一个文件名则换行
        if(g_leave_len<g_maxlen)
        {
            printf("\n");
            g_leave_len=MAXLEN;
        }
    
        len=strlen(name);
        len=g_maxlen-len;
       
        printf("\033[;33m%s\033[0m",name);
    
        for(i=0;i<len;i++)
            printf(" ");
    
        printf(" ");
    
        //下面的2指示空两格
        g_leave_len-=(g_maxlen+2);//一行中剩下的字符数量
    }*/
    
    /*void Send_file()
    {
        int id;
        printf("请输入要发送文件的好友账号:\n");
        scanf("%d",&id);
    
      
    	printf("请输入文件名:\n");
    	char pathname[100];
    
    
    	//get_str(pathname,100);
        scanf("%s",pathname);
        
        int fd=open(pathname,O_RDONLY);
        if(fd<0)
        {
           printf("请输入正确的文件路径\n");
           return ;
        }
    
        file_t file;
        memset(&file,0,sizeof(file));
        file.recver=id;
        file.sender=username;
        file.flag=SEND_FILE;
        strcpy(file.file_name,pathname);
    
    
    
        struct stat stat;
    	int fs=fstat(fd,&stat);
    	long file_size=0;
    	file_size=stat.st_size;
       // file.file_size=file_size;
        printf("file.file_size=%d\n",file.file_size);
        
        printf("sizeof(file)=%ld\n",sizeof(file));
        printf("file_size=%ld\n",file_size);
        
        int filefd = open(pathname,O_RDONLY);
        assert(filefd>0);
        struct stat file_stat;
        //为了获取文件大小
        fstat(filefd,&file_stat);
    
        sendfile(connfd,filefd,NULL,file_stat.st_size);
        close(filefd);
     
        close(fd);    
    }*/
    void Send_file()
    {
        int id;
        printf("请输入要发送文件的好友账号:\n");
        scanf("%d",&id);
    
      
    	printf("请输入文件名:\n");
    	char pathname[100];
    
    
    	//get_str(pathname,100);
        scanf("%s",pathname);
        
        /*int fd=open(pathname,O_RDONLY);
        if(fd<0)
        {
           printf("请输入正确的文件路径\n");
           return ;
        }
    
    
        struct stat st;
        long int size=stat(pathname, &st);
        if(size < 0)
        {
            printf("file stat error\n");
            exit(1);
        }
        printf("file size:%ld\n",st.st_size);
    
        off_t pos=lseek(fd,0,SEEK_SET);
        if(pos < 0)
        {
            printf("get file_pos error\n");
            exit(1);
        }*/
    
        
        file_t file;
        file.flag=UPLOAD;
        strcpy(file.file_name,pathname);
        file.recver=id;
        file.sender=username;
    
        char buf[BUFMAX];
        memcpy(buf,&file,sizeof(file));
        send(cfd,buf,sizeof(buf),0);
        
    
        char buff[1024];
        memset(buff,0,sizeof(buff));
        // FILE *fp = fopen(file.file_name,"r");
        int fp=open(pathname,O_RDONLY);
        if(fp<0)
        {
            perror("open failed");
            return;
        }
        else 
        {
            int i = 0;
    
            memset(buff,0,sizeof(buff));
            int len=0;
            //while((len=fread(buff,sizeof(char),1024,fp))> 0)
            while((len=read(fp,buff,sizeof(buff)))>0)
            {
                                
                i++;
                                    
                //  printf("len= %d\n",len);
                if(send(cfd,buff,len,0)<=0)
                {
                    printf("Send file failed\n");
                    break;
                }
                memset(buff,0,sizeof(buff));
    
            }
            close(fp);
            memset(buff,0,sizeof(buff));
                                
            sleep(1);
            strcpy(buff,"end");
            send(cfd,buff,strlen(buff),0);
        }           
    
    
        /*long int ssize = 0;
        char buffer[BUFMAX];
        long int n=0;
        
        while(1)
        {
            bzero(buffer,1024);
            int rn = read(fd, buffer, 1024);
            int wn = write(cfd, buffer, 1024);
            if(n >= st.st_size)
            {
                printf("size:%ld\n", n);
                printf("size:%ld\n", st.st_size);
                break;
            }
            n += rn;
        }
        if(n==-1)
        {
            printf("send file error\n");
            exit(1);
        }*/
    
    }
    
    void Download()
    {
        file_t file;
    
        //char file_name[100];
        printf("请输入下载文件名:\n");
        scanf("%s",file.file_name);
    
        file.flag=DOWNLOAD;
        file.sender=username;
        file.recver=0;//服务器接收
    
        char buf[BUFMAX];
        memcpy(buf,&file,sizeof(file));
    
        send(cfd,buf,sizeof(buf),0);
    
    }
    
    void Recv_file(char* buf)
    {
    
        file_t file;
        memcpy(&file,buf,sizeof(file));
    
        char buff[1024];
        memset(buff,0,sizeof(buff));
        char file_name[100];
        memset(file_name,0,sizeof(file_name));
    
    
             
        strcpy(file_name,file.file_name);    
        printf("file name=%s\n",file_name);
        int fp = open(file_name,O_CREAT  | O_TRUNC ,0666);
        if(fp < 0)
        {
            perror("open file fail");
        }
        close(fp);
    
        fp = open(file_name,O_APPEND | O_WRONLY);
        if(fp<0)
            perror("open file fail");
    
        memset(buff,0,sizeof(buff));
        int len=0;
        int write_len;
        int i = 0;
        while( (len=recv(cfd,buff,sizeof(buff),0) ) > 0 )
        {
                            
                        
            if(strcmp(buff,"end") == 0)
                break;
                        
            if(len<0)
            {
                printf("Download file error\n");
                break;
            }
                        
            write_len=write(fp,buff,len);
            /*                
            if(write_len!= len)
            {
                printf("write failed\n");
                return 0;
            }*/
            memset(buff,0,sizeof(buff));
                        
        }
        close(fp);
       // arg=(char*)arg;
        /*int fd;
        file_t file;
        memcpy(&file,buf,sizeof(file));
        printf("file name:%s\n",file.file_name);
        //如果文件不存在创建文件
        if((fd=open(file.file_name,O_RDWR | O_CREAT | O_APPEND,0777))<0)
        {
            my_err("open file_name error",__LINE__);
        }
        
        
        int ret=write(fd,file.data,file.file_size);
        if(ret<0)
        {
            my_err("write file error",__LINE__);
        }*/
    
    
        /*
        printf("ret=%d\n",ret);
        printf("file_name=%s\n",file.file_name);
        printf("recver=%d\n",file.recver);
        printf("sender=%d\n",file.sender);
        printf("file_size=%d\n",file.file_size);
        */
    
    //    close(fd);
    }
    
    void Recv_apply(char* buf)
    {
        message mes;
        memcpy(&mes,buf,sizeof(mes));
        printf("%s\n",mes.messsge);
    
    }
    void Friend_menu()
    {
        int choice=1;
        system("clear");
        
        while(choice)
        {
            usleep(1000);
            printf("\t\t\033[;36m\033[1m*********朋友管理*********\033[0m\n");
            printf("\t\t\033[1;36m|\033[0m--------1.添加好友-------\033[1;36m|\033[0m\n");
            printf("\t\t\033[1;36m|\033[0m--------2.好友消息盒子-------\033[1;36m|\033[0m\n");
            printf("\t\t\033[1;36m|\033[0m--------3.删除好友-------\033[1;36m|\033[0m\n");
            printf("\t\t\033[1;36m|\033[0m--------4.私聊好友-------\033[1;36m|\033[0m\n");
            printf("\t\t\033[1;36m|\033[0m--------5.屏蔽好友-------\033[1;36m|\033[0m\n");
            printf("\t\t\033[1;36m|\033[0m------6.解除屏蔽好友-----\033[1;36m|\033[0m\n");
            printf("\t\t\033[1;36m|\033[0m------7.查看好友列表-----\033[1;36m|\033[0m\n");
            printf("\t\t\033[1;36m|\033[0m------8.查看聊天记录-----\033[1;36m|\033[0m\n");
            printf("\t\t\033[1;36m|\033[0m------0.退出-----\033[1;36m|\033[0m\n");
            printf("\t\tchoice:\n");
            //printf("请输入选择:");
            scanf("%d",&choice);
            while(getchar() != '\n');
            switch (choice)
            {
                case 1:
                    Add_friend();
                    break;
                case 2:
                    Friend_box();
                    break;
                case 3:
                    Del_friend();
                    break;
                case 4:
                    Private_chat();
                    break;
                case 5:
                    Shield_friend();
                    break;
                case 6:
                    Unshield_friend();
                    break;
                case 7:
                    View_friend_list();
                    break;
                case 8:
                    View_chat_history();
                    break;
                case 0:
                    break;
            }
        }
        return;
    }
    void Group_menu()
    {
        system("clear");
        int choice=1;
        while(choice)
        {
            usleep(1000);
            //printf("\t\t\033[;34m\033[1m*********群管理*********\033[0m\n");
            printf("\t\t\033[1;34m|\033[0m--------1.创建群-------\033[1;34m|\033[0m\n");
            printf("\t\t\033[1;34m|\033[0m--------2.添加群-------\033[1;34m|\033[0m\n");
            printf("\t\t\033[1;34m|\033[0m--------3.群消息盒子-------\033[1;34m|\033[0m\n");
            printf("\t\t\033[1;34m|\033[0m--------4.退群---------\033[1;34m|\033[0m\n");
            printf("\t\t\033[1;34m|\033[0m--------5.群聊---------\033[1;34m|\033[0m\n");
            printf("\t\t\033[1;34m|\033[0m--------6.已加群-------\033[1;34m|\033[0m\n");
            printf("\t\t\033[1;34m|\033[0m--------7.群成员-------\033[1;34m|\033[0m\n");
            printf("\t\t\033[1;34m|\033[0m-----8.查看聊天记录----\033[1;34m|\033[0m\n");
            //printf("\t\t\033[1;34m|\033[0m------群管理权限-----\033[1;34m|\033[0m\n");
            //printf("\t\t\033[1;34m|\033[0m-------------------\033[1;34m|\033[0m\n");
            //printf("\t\t\033[1;34m|\033[0m*群主--1,2,3/管理员--3权限*\033[1;34m|\033[0m\n");
            //printf("\t\t\033[1;34m|\033[0m-------------------\033[1;34m|\033[0m\n");
            printf("\t\t\033[1;34m|\033[0m------9.设置管理员------\033[1;34m|\033[0m\n");
            printf("\t\t\033[1;34m|\033[0m------10.踢人-----\033[1;34m|\033[0m\n");
            printf("\t\t\033[1;34m|\033[0m--------0.退出--------\033[1;34m|\033[0m\n");
            printf("\t\tchoice:\n");
            scanf("%d",&choice);
            while(getchar() != '\n');
            switch (choice)
            {
                case 1:
                    Create_group();
                    break;
                case 2:
                    Add_group();
                    break;
                case 3:
                    Group_box();
                    break;
                case 4:
                    Withdraw_group();
                    break;
                case 5:
                    Group_chat();
                    break;
                case 6:
                    View_add_group();
                    break;
                case 7:
                    View_group_member();
                    break;
                case 8:
                    View_group_record();
                    break;
                case 9:
                    Set_group_admin();
                    break;
                case 10:
                    Kick();
                    break;
                case 0:
                    break;
            }
        }
        return;
    }
    
    void Print_menu()
    {
        printf("\t\t\033[1;34m**************************\033[0m\n");
        printf("\t\t\033[1;34m|        1.好友管理      \033[1;34m|\033[0m \n");
        printf("\t\t\033[1;34m|        2.群管理        \033[1;34m|\033[0m \n");
        printf("\t\t\033[1;34m|        3.文件管理      \033[1;34m|\033[0m \n");
        printf("\t\t\033[1;34m|        0.退出          \033[1;34m|\033[0m \n");
        printf("\t\t\033[1;34m**************************\033[0m\n");
        printf("\t\tchoice:");
        printf("\n");
    }
    void Menu()
    {
        system("clear");
        int choice=1;
        //char choice_t[50];
    
        do
        {
           
            Print_menu();
            scanf("%d",&choice);
            //get_choice_int(0,3);
             //while(getchar()!='\n');
            //choice=Get_choice(choice_t);
           
            switch (choice)
            {
                case 1:
                    Friend_menu();
                    break;
                case 2:
                    Group_menu();
                    break;
                case 3:
                    File_menu();
                    break;
                case 0:
                    Exit();
                    //Login_menu();
                    break;
            }
        }while(choice!=0);
     
    }
    void my_err(const char* err_string,int line)
    {
        fprintf(stderr,"line:%d",line);
        perror(err_string);
        exit(1);
    }
    void Clear_buffer()
    {
        char ch;
        while(getchar()!='\n')
    		continue;
        /*while((ch=getchar())!='\n' && ch!=EOF)
                continue;*/
    }
    void display(char* str)
    {
        int i;
        system("clear");
        for(i=0;i<50;i++)
            putchar('-');
        putchar('\n');
        printf("       %s\n",str);
        for(i=0;i<50;i++)
            putchar('-');
        putchar('\n');
        return;
    }
    int get_choice_int(int min, int max)
    {
    	int input;
    	char ch;
    
    	while ( (scanf("%d", &input) != 1) || (input < min) || (input > max))
    	{
    		while ((ch =getchar()) != '\n')
                continue;
    		printf("请输入正确选项:\n");
    	}
    
        while ((ch =getchar()) != '\n')
                continue;
    
    	return input;
    }
    
    /*char getch()
    {
    	char ch;
    
        system("stty -echo");//不回显
        system("stty -icanon");//设置一次性读完操作,如使用getchar()读操作,不需要按回车
        ch = getchar();
        system("stty icanon");//取消上面的设置
        system("stty echo");//回显
    
        return ch;
    }*/
    // 修改终端的控制方式,1取消回显、确认 2获取数据 3还原
    int getch()
    {
        // 记录终端的配置信息
        struct termios old;
        // 获取终端的配置信息
        tcgetattr(STDIN_FILENO,&old);
        // 设置新的终端配置   
        struct termios new1 = old;
        // 取消确认、回显
        new1.c_lflag &= ~(ICANON|ECHO);
        // 设置终端配置信息
        tcsetattr(STDIN_FILENO,TCSANOW,&new1);
    
        // 在新模式下获取数据   
        int key_val = 0; 
        do{
        	key_val += getchar();
        }while(stdin->_IO_read_end - stdin->_IO_read_ptr);
    
        // 还原配置信息
        tcsetattr(STDIN_FILENO,TCSANOW,&old); 
        return key_val; 
    }
    
    char* Get_string(char* buf,int len)
    {
        char* str;
        int i=0;
        str=fgets(buf,len,stdin);
    	if(str!=NULL)
    	{
    		while(str[i]!='\0' && str[i]!='\n')
    			i++;
    		if(str[i]=='\n')
    			str[i]='\0';
    		else
    			while(getchar()!='\n')
    				continue;
    	}
    	return str;
    }
    char* get_str(char* str,size_t len)
    {
    	if(NULL == str)
    	{
    		puts("空指针异常\n");
    		return NULL;
    	}
    
    	char *in=fgets(str,len,stdin);
    	
    	size_t cnt = strlen(str);
    	if('\n' == str[cnt-1])
    	{
    		str[cnt-1] = '\0';
    	}
    	
    	clear_stdin();
    
    	return str;
    }
    void clear_stdin()
    {
    	stdin->_IO_read_ptr = stdin->_IO_read_end;//清理输入缓冲区
    }
    int Get_choice(char *choice_t)
    {
        int choice =0;
        for(int i=0;i<strlen(choice_t) ;i++)
            if(choice_t[i]<'0' || choice_t[i]>'9')
                return -1;
        for(int i=0;i<strlen(choice_t);i++)
        {
            int t=1;
            for(int j=1;j<strlen(choice_t)-i;j++)
            {
                t *=10;
            }
            choice += t*(int)(choice_t[i] - 48);
        }
        return choice;
    }
    
    展开全文
  • 明明聊天室是要在暑假两个星期内写完的,由于疫情没有回校学习,在家也是写一点放松一点,并且第一次写一个比较大的项目有点力不从心,总之有遗憾吧,在网络编程这块学习也是浅上折纸,在想整体架构上有明显不足,...

    明明聊天室是要在暑假两个星期内写完的,由于疫情没有回校学习,在家也是写一点放松一点,并且第一次写一个比较大的项目有点力不从心,总之有遗憾吧,在网络编程这块学习也是浅上折纸,在想整体架构上有明显不足,所以导致了第一版问题比较多,在垂头丧气了几天感觉自己目前能力解决不了的情况下选择了重写,过程比较痛苦,也焦虑了几夜,躺着也难受想放弃,不知道选这个有没有错,还是说自学并没有什么作用,菜是菜了点,好歹挺过来了。。。然后又是测试,学长帮我测了四次来慢慢解决一些逻辑漏洞,逐渐也熟悉了这部分的要求,再看看别人的实现和对网络编程的理解,有羡慕,也有难过,逃避宣泄着情绪,小城无路可逃。我先看到了这里,然后感受非常复杂。

    该程序仅在本机上测试通过,部署到公网上时出现的getch()回显问题以及登录不上一些问题(这个可以重启client端完成登录),应该是加锁和数据阻塞的原因,由于不想改了如果有大佬看到这篇博客希望能给一些建议和帮助

    我的ubuntu的版本

    Linux version 5.4.0-42-generic (buildd@lgw01-amd64-038) linux内核版本号
    gcc version 9.3.0 gcc编译器版本号
    Ubuntu 9.3.0-10ubuntu2 Ubuntu版本号
    
    1. 加好友和加群
      一般客户端发送一个请求消息给服务器后,服务器再发给客户端一个添加消息,客户端用盒子链表来存,再输入同意与否,处理一条删除一条,最后发送回执给服务器,服务器判断是否同意再发回客户端显示消息
    2. 离线私聊和群聊
      私聊要判断有没有屏蔽,是否是好友,在不在线,不在线采用离线status位存发送与否先存mysql库里面,等对面上线了由服务器发送消息,群聊多加了是否是存在群和是否是群成员判断,以及查找发送给其他群成员的mysql查找
    3. 文件传输
      由于实现的框架局限,这部分之前版本有些内存泄漏和栈溢出的问题,之后查到了sendfile和splice的Linux零拷贝方法,但是在参考后还是选择了上传服务器和客户端再下载的实现,注意传输的数据要完全最后要加一个消息通知服务器传输完成
    4. 如果不太明白一些具体逻辑的实现可以私聊我,后面看时间会不会写一个解释博客,估计是不会了

    以下是代码实现

    server.c
    #include "chat.h"
    #define EPOLLEVENT 1024
    #define BUFMAX 1024
    #define BUF 2048
    
    
    char *Server_time();
    int	Set_no_block(int sfd);
    
    int sys_log;
    MYSQL mysql;
    
    /*
    void Add_node(int fd,int id,char* name);
    void Send_register_pack(int fd,int flag,char* buf,int id);
    int Get_status(int id);
    char* Get_name(int id);*/
    int main()
    {
    
       
    
    
        /*if((sys_log=open("sys_log",O_WRONLY | O_CREAT | O_APPEND,S_IRUSR|S_IWUSR))<0)
        {
            sys_err("open error",__LINE__);
            return 0;
        }
        dup2(sys_log,1);*/
    
        
        signal(SIGINT,Signal_close);
    
        //pthread_mutex_init(&mutex,NULL);
        //pthread_cond_init(&cond,NULL);
    
        Connect_mysql();
        /*printf("线程池启动\n");
        pool_init(MAX_THREAD_NUM);
        printf("线程池启动成功!\n");
        sleep(2);*/
        pool_init(50);
        //sleep(2);
        //Read_from_mysql();
        Init_socket();
    
    
        //threadpool_destroy();
    
    }
    void Signal_close(int i)
    {
        close(sys_log);
        Close_mysql(mysql);
        printf("服务器关闭\n");
        exit(1);
    }
    
    
    char *Server_time()
    {
    	time_t ctime;//服务器时间
    	struct tm *server_time;
    	time(&ctime);
    	server_time=localtime(&ctime);
    	return asctime(server_time);
    }
    
    int	Set_no_block(int sfd)
    {
    	/* 内层调用fcntl()的F_GETFL获取flag,
    	 * 外层fcntl()将获取到的flag设置为O_NONBLOCK非阻塞*/
    	if( fcntl(sfd, F_SETFL, fcntl(sfd, F_GETFL, 0) ) == -1)
    	{	
            return -1;
        }
    	return 0;
    }
    
    void Init_socket(int argc,char *argv[])
    {
        struct stat stat_buf;
    	const char* file_name=argv[1];   
        int file_fd=open(file_name,O_RDONLY);
    	fstat(file_fd,&stat_buf);
    	close(file_fd); 
    
        List_Init(list_ser,server_user_node_t);
        printf("服务端启动\n");
        struct sockaddr_in serv_addr;
        struct sockaddr_in cli_addr;
    
        socklen_t cli_addr_len;
    
        lfd=Socket(AF_INET,SOCK_STREAM,0);
    
    
        Set_no_block(lfd);
        //端口复用
        int opt=1;
        setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt));
    
        bzero(&serv_addr,sizeof(serv_addr));
    
        serv_addr.sin_family=AF_INET;
        serv_addr.sin_port=htons(SERV_PORT);
        serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    
        Bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
        Listen(lfd,128);
    
        printf("服务器启动成功!\n");
    
        epfd=epoll_create(EPOLLEVENT);
        struct epoll_event tep,ep[EPOLLEVENT];
        tep.events=EPOLLIN;
        tep.data.fd=lfd;
        epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&tep);
    
        int i;
        int ret;
        pthread_t pid;
        char buf[BUFMAX];
        //memset(buf,0,sizeof(buf));
        while(1)
        {
            ret=epoll_wait(epfd,ep,EPOLLEVENT,-1);
            for(i=0;i<ret;i++)
            {
    
                //printf("the event is %x\n",ep[i].events);
                int fd=ep[i].data.fd;
    
                if (!(ep[i].events & EPOLLIN))      //如果不是"读"事件, 继续循环
                    continue;
    
                if(ep[i].data.fd==lfd)
                {
                    cli_addr_len=sizeof(cli_addr);
                    cfd=Accept(lfd,(struct sockaddr*)&cli_addr,&cli_addr_len);
                    printf("连接到新的客户端ip:%s\n端口号:%d\n",inet_ntoa(cli_addr.sin_addr),cli_addr.sin_port);
                    
                    /*设置非阻塞io*/
    				if(Set_no_block(cfd) != 0 )
    				{
    					printf("SET_no_black\n");
    					printf("%s",Server_time());
    					close(cfd);
    					continue;
    				}
                    
                    tep.events=EPOLLIN;
                    tep.data.fd=cfd;
                    if(epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&tep)<0)
                    {
                        printf("EPOLL_CTL add client error\n");
                        printf("%s",Server_time());
    					
                        close(cfd);
    					continue;
                    }
    
                }
                /*else if(ep[i].events & EPOLLOUT) 
                {
                    printf("start to sendfile !\n");
                    printf("处理写事件\n");
                    int write;
                    write=send(fd,buf,strlen(buf),0);
                    if(write == -1)
                    {
                        my_err("write event error",__LINE__);
                        close(fd);
                    }
                    else
                    {
                        printf("发送消息成功\n");
                    }
                    memset(buf,0,BUFMAX);
                }*/
                /*else if(ep[i].events & EPOLLOUT)
                {
    
    				printf("start to sendfile !\n");
    				int send_ret=0;
                    int left=stat_buf.st_size;
    				file_fd=open(file_name,O_RDONLY);
    
    				while(left>0)
                    {
    					send_ret=sendfile(cfd,file_fd,NULL,BUF);
    					if(send_ret<0 && errno==EAGAIN)
                        {
    						continue;
    					}
                        else if(send_ret==0)
                        {
    						break;
    					}
                        else
                        {
    						left-=send_ret;
    					}
    				}
    
    				printf("sendfile over !\n");
    				close(file_fd);
    
    				tep.data.fd=cfd;
    				epoll_ctl(epfd,EPOLL_CTL_DEL,cfd,&tep);
    
    				close(cfd);
                }*/