实验室培训项目之即时通讯软件

  这次的即时通信软件包括服务器端和客户端,服务器端在红帽的基础上用gcc写成,客户端利用C#完成,由于oracle数据库的配置问题,有部分功能还未能实现,现在实现的功能就只是聊天, 聊天记录, 文件传输, 文件记录, 会议室, 会议室记录,界面和qq类似,易于操作。

  服务器端的架构是以多进程epoll为基础,建立共享的内存,通过在共享内存中实现hash来提高消息的转发效率,服务器的设计目标为可承受上万的用户连接,但由于条件有限,没办法在这个方面进行测试,套接字属于不同进程epoll间的用户,通过域套接字实现消息的进程间转发,这在一定程度上降低了系统的效率。有兴趣的同志可以联系。。邮箱290590436@qq.com。。。现在附上服务器主函数的代码。。。

  这个代码一共用了一个来月,期间学到了很多东西,虽然现在并未完全完成,但也算是阶段性的成功了,所以虽然我也是个新手,但我还是将代码共享出来。。对做IM软件有兴趣的同志可以联系我获得全部代码和主要思想,当然也欢迎大牛们对我的代码进行指导,风格这个就不用说了。。由于是边学边写的,这个项目风格确实欠佳,光main函数就上千行,但是对于epoll的多进程使用我还是有一定的心得体会,epoll对于大并发的程序确实是一个神器。。现在附上main。c代码。。。请大家多指教

 

#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/un.h>
#include "share_table.h"
#include "log.h"

#define MAXLINE 1024
#define OPEN_MAX 100
#define LISTENQ 20
#define SERV_PORT 5555
#define INFTIM 1000
#define HEADLENGTH 64
#define PATH "/home/wenhao/"

typedef struct task_t
{
    int fd;
    char head[HEADLENGTH+1];
    char buffer[MAXLINE+1];
    int n;
}task_t;

void init_semaphore_struct(struct sembuf* sem,int semnum,int semop,int semflag)
{
    sem->sem_num=semnum;
    sem->sem_op=semop;
    sem->sem_flg=semflag;
}

int del_semaphore(int semid)
{
#if 1
    return semctl(semid,0,IPC_RMID);
#endif
}

int setnonblocking(int sock)
{
    int opts;
    opts = fcntl(sock, F_GETFL);   //操作文件描述符的一些参数,F_GETFL表示获取文件描述词状态旗标
    if(opts<0)
    {
        perror("fcntl(sock,GETFL)");
        return 10;
    }
    opts = opts|O_NONBLOCK;         //设置为非阻塞模式
    if(fcntl(sock,F_SETFL,opts)<0)
    {
        perror("fcntl(sock,SETFL,opts)");
        return 11;
    }
}

int CreateWorker(int nWorker)
{
    if (0 < nWorker)
    {
        int bIsChild=0;
        pid_t nPid;

        while (!bIsChild)
        {
            if (0 < nWorker)
            {
                nPid = fork();
                if (nPid > 0)
                {
                    bIsChild = 0;
                    --nWorker;
                }
                else if (0 == nPid)
                {
                    bIsChild = 1;
                    printf("create worker %d success!\n", getpid());
                }
                else
                {
                    printf("fork error: %s\n", strerror(errno));
                    return -1;
                }
            }
            else
            {
                int nStatus;
                if (-1 == wait(&nStatus))
                {
                    ++nWorker;
                }
            }
        }
    }
    return 0;
}
    
int main(int argc, char* argv[])
{
    //*********************************************************初始化共享存储结构
    int sem_id,semop_ret,status;
    struct sembuf semwait,semsignal;
    if((sem_id=semget(IPC_PRIVATE,1,PERMS))==-1)
    {
        fprintf(stderr,"[%d]: access semophore error\n\a",getpid(),strerror(errno));
        exit(1);
    }
    init_semaphore_struct(&semwait,0,-1,0);
    init_semaphore_struct(&semsignal,0,1,0);
    
    if(semop(sem_id,&semsignal,1)==-1)
    {
        fprintf(stderr,"[%d] increment semaphore error\n\a",getpid(),strerror(errno));
        if(del_semaphore(sem_id)==-1)
        {
            fprintf(stderr,"[%d] destroy semaphore error\n\a",getpid(),strerror(errno));    
        }
        exit(1);
    }
    int shmid_online_table, shmid_hash_table, shmid_empty_list;
    struct online_member *ponline;
    struct online_member buf_online;

    if((shmid_online_table = shmget(IPC_PRIVATE, MAX_ONLINE_NUMBER*sizeof(struct online_member), 0666 | IPC_CREAT)) == -1)
    {
        fprintf(stderr, "1 shmget error: %s\n", strerror(errno));
        del_semaphore(sem_id);
        exit(1);
    }

        if((shmid_hash_table = shmget(IPC_PRIVATE, BIG_PRIME*sizeof(struct hash_table), 0666 | IPC_CREAT)) == -1)
        {
                fprintf(stderr, "2 shmget error: %s\n", strerror(errno));
                shmctl(shmid_online_table, IPC_RMID, 0);
                del_semaphore(sem_id);
                exit(1);
        }

        if((shmid_empty_list = shmget(IPC_PRIVATE, (MAX_ONLINE_NUMBER+2)*sizeof(struct empty_list), 0666 | IPC_CREAT)) == -1)
        {
                   fprintf(stderr, "3 shmget error: %s\n", strerror(errno));
                   shmctl(shmid_online_table, IPC_RMID, 0);
                shmctl(shmid_hash_table, IPC_RMID, 0);
                del_semaphore(sem_id);
                   exit(1);
        }

    init_share_table(shmid_hash_table, shmid_empty_list, shmid_online_table);
    //*********************************************************初始化共享存储结构


    int i, maxi, listenfd, connfd, sockfd, epfd, nfds, msg_length, j;
    ssize_t n;
    char line[MAXLINE], head[HEADLENGTH+1];
    socklen_t clilen = sizeof(struct sockaddr);

    task_t *ptask, task, *ptask_transfer;
    
    //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件
    struct sockaddr_in clientaddr;
    struct sockaddr_in serveraddr;
    listenfd = socket(AF_INET, SOCK_STREAM, 0);    
    bzero(&clientaddr, sizeof(clientaddr));
    bzero(&serveraddr, sizeof(serveraddr));
   // memset(&serveraddr,0x00,sizeof(serveraddr));

    serveraddr.sin_family = AF_INET;
    /*char *local_addr="192.168.101.22";
    inet_aton(local_addr,&(serveraddr.sin_addr));*/

    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port=htons(SERV_PORT);
    bind(listenfd,(struct sockaddr *)&serveraddr, sizeof(serveraddr));    
    
    CreateWorker(3);
    
    struct epoll_event ev,events[20];
    
    //生成用于处理accept的epoll专用的文件描述符
    epfd = epoll_create(256);                  //参数为描述符的最大范围 在此创建套接字池!!!!!!!
                                               //生成一个epoll专用的文件描述符

    
    //把socket设置为非阻塞方式
    //setnonblocking(listenfd);

    //设置与要处理的事件相关的文件描述符
    ev.data.fd=listenfd;
    
    //设置要处理的事件类型
    ev.events=EPOLLIN|EPOLLET;
    //ev.events=EPOLLIN;

    //注册epoll事件
    epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);    //在此处注册ev 针对Listenfd
                                                //你也可以在申请其他端口的listenfd,并注册ev
                                                //fd:关联的文件描述符
                                                
    //************************************初始化unix domain socket
    int unixd_sockfd = 0;
    struct sockaddr_un unixd_addr;
    char path[30];
    char path_transfer[30];
    sprintf(path, "%s%d", PATH, getpid());
    printf("this pid is %d\n", getpid());
    //unlink(PATH);    
    unixd_addr.sun_family = AF_UNIX;
    //unixd_addr_transfer.sun_family = AF_UNIX;
    strcpy(unixd_addr.sun_path, path);
    unlink(path);
    unsigned int unixd_len = strlen(unixd_addr.sun_path) + sizeof(unixd_addr.sun_family);
    unixd_sockfd = socket(AF_UNIX,SOCK_DGRAM,0);
    if(bind(unixd_sockfd,(struct sockaddr *)&unixd_addr,unixd_len) < 0)
    {
        perror("bind error");
        close(unixd_sockfd);
        exit(-1);
    }
    printf("Bind is ok\n");
    bzero(path,30);
    //************************************初始化unix domain socket
    ev.data.fd = unixd_sockfd;
    
    //设置要处理的事件类型
    ev.events = EPOLLIN | EPOLLET;
    //ev.events=EPOLLIN;

    //注册epoll事件
    epoll_ctl(epfd, EPOLL_CTL_ADD, unixd_sockfd, &ev);        

    listen(listenfd, LISTENQ);
    maxi = 0;
    int count;
    for (count = 0; ; count++) {        
        //等待epoll事件的发生
        nfds=epoll_wait(epfd,events,20,500);
        //if(nfds > 0)
            //printf("nfds: %d\n", nfds);
        //处理所发生的所有事件
        for(i=0;i<nfds;++i)
        {
            if(events[i].data.fd==listenfd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。
            {
                if((connfd = accept(listenfd,(struct sockaddr *)&clientaddr, &clilen)) < 0)
                {
                    fprintf(stderr, "accept error : %s\n", strerror(errno));
                }
                printf("connfd: %d\n", connfd);
                if(connfd < 0){
                    perror("connfd<0");
                    return 30;
                }
                ev.data.fd = connfd;
                
                //setnonblocking(connfd);

                char *str = inet_ntoa(clientaddr.sin_addr);
                printf("IP  %s has come,the sockfd is %d, this pid is %d:   \n", str, connfd, getpid());
                printf("the i =  %d ,the count = %d\n",i, count);
                //设置用于读操作的文件描述符
                
                //设置用于注测的读操作事件
                ev.events = EPOLLIN | EPOLLET;
                //ev.events=EPOLLIN;

                //注册ev
                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
            }
            else if(events[i].data.fd == unixd_sockfd && (events[i].events & EPOLLIN))
            {
                printf("the unixdomain socket %d have data to receive, the pid:  %d\n", events[i].data.fd, getpid());
                bzero(head, HEADLENGTH);
                if ((n = recvfrom(unixd_sockfd, head, HEADLENGTH, 0, (struct sockaddr*)&unixd_addr, &unixd_len)) < 0)
                {
                        if (errno == ECONNRESET)
                        {         //连接出错,一般在客户端强制退出时出现
                            fprintf(stderr, "recv error : %s", strerror(errno));
                            close(unixd_sockfd);
                            events[i].data.fd = -1;
                        }
                        else
                            printf("读取数据时出错\n");
                }
                else if(n == 0)
                {
                    printf("there's nothing");
                    close(unixd_sockfd);
                    events[i].data.fd = -1;
                }
                line[n] = '\0';
                strncpy(buf_online.username, &head[22], 20);
                semop_ret=semop(sem_id, &semwait, 1);
                //
                if( search_online_member(&buf_online, shmid_hash_table, shmid_empty_list, shmid_online_table) == 1)
                {
                    semop(sem_id, &semsignal, 1);
                    printf("search success: %s , %d\n", buf_online.username, buf_online.fd);
                    
                    ptask_transfer = NULL;
                    ptask_transfer = (task_t*)malloc(sizeof(task_t));
                    
                    if (ptask_transfer == NULL)
                    {
                        fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                        while(ptask_transfer == NULL)
                        {
                            ptask_transfer = (task_t*)malloc(sizeof(task_t));
                        }
                    }                    
                    bzero(ptask_transfer->buffer, MAXLINE);
                    /*strncpy(ptask_transfer->head, head, 2);//********用户上线指令
                    strncpy(&ptask_transfer->head[2], &head[2], 20);
                    strncpy(&ptask_transfer->head[22], buf_online.username, 20);
                    memcpy(&ptask_transfer->head[42], &head[42], 4);*/
                    memcpy(&msg_length, &head[42], 4);
                    memcpy(ptask_transfer->head, head, 64);
                    ptask_transfer->fd = buf_online.fd;
                    if ( msg_length != 0)
                    {
                        recvfrom(unixd_sockfd, ptask_transfer->buffer, msg_length, 0, (struct sockaddr*)&unixd_addr, &unixd_len);
                        printf("recv data: %s, length : %d\n", ptask_transfer->buffer, msg_length);
                    }                    
                    ev.data.ptr = ptask_transfer;
                    ev.events = EPOLLOUT | EPOLLET;
                    epoll_ctl(epfd, EPOLL_CTL_MOD, buf_online.fd, &ev);    
                    printf("epoll add finished\n");
                }
            }
            else if(events[i].events & EPOLLIN)//如果是已经连接的用户,并且收到数据,那么进行读入。
            {
                
                //printf("the sockfd: %d have data to receive\n", events[i].data.fd);
                bzero(head, HEADLENGTH);
                if ( (sockfd = events[i].data.fd) < 0)
                    continue;
                if ( (n = recv(sockfd, head, HEADLENGTH, 0)) < 0) {
                    if (errno == ECONNRESET) {         //连接出错,一般在客户端强制退出时出现
                        close(sockfd);
                        //**********************从共享存储中删除
                        
                        events[i].data.fd = -1;
                    }
                    else
                        printf("读取数据时出错\n");
                }
                else if (n == 0) {
                    close(sockfd);
                    events[i].data.fd = -1;
                }
                if(n < HEADLENGTH)
                    RecvData(sockfd, &head[n], HEADLENGTH - n);
                
                head[n] = '\0';
        //printf("n is %d\n", n);
                //printf("\t the date is :%s ,size is :%d, str len is :%d\n", head, n, strlen(head));
                
                if(strncmp(head, "LG", 2) == 0)
                {
                    //sleep(1);
                    //printf("351:  go into the if: head:  %c%c\n", head[0], head[1]);
                    //*********************插入共享存储区
                    strncpy(buf_online.username, &head[2], 20);
                    strncpy(buf_online.grade, "ISRC2012", 10);
                    buf_online.fd = sockfd;
                    buf_online.pid = getpid();
                    buf_online.next = -1;
                    printf("358 buf_online.username:  %s\n", buf_online.username);
                    semop_ret=semop(sem_id, &semwait, 1);
                    //
                    if(is_online_member(&buf_online, shmid_hash_table, shmid_empty_list, shmid_online_table) == 1)
                    {
                        printf("361 into the is online\n");
                        delete_online_member(&buf_online, shmid_hash_table, shmid_empty_list, shmid_online_table);
                        //***********************************************************************************
                        
                        
                        //挤掉冲突用户的后续操作
                    }
                    //printf("367  :  before insert!!!\n");
                    insert_online_member(&buf_online, shmid_hash_table, shmid_empty_list, shmid_online_table);
                    semop(sem_id, &semsignal, 1);
                    //*********************插入共享存储区
                    printf("new client has come. username:   %s,grade:    %s,pid: %d\n", buf_online.username, buf_online.grade, buf_online.pid);
                    //设置用于写操作的文件描述符
                    ptask = NULL;

                    ptask = (task_t*)malloc(sizeof(task_t));//安全分配内存
                    
                    if (ptask == NULL)
                    {
                        fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                        while(ptask == NULL)
                        {
                            ptask = (task_t*)malloc(sizeof(task_t));
                        }
                    }
                    
                    bzero(ptask, sizeof(task_t));
                    
                    print_online_table(shmid_online_table, shmid_hash_table);
                    //*************************生成消息头和消息
                    msg_length = sprint_online_table(ptask->buffer, shmid_online_table, shmid_hash_table);
                    //printf("msg_length = %d\n", msg_length);
                    strncpy(ptask->head, "LG", 2);
                    strncpy(&ptask->head[2], "server", 20);
                    strncpy(&ptask->head[22], buf_online.username, 20);
                    //printf("348   buf_online  :%s\n", buf_online.username);
                    memcpy(&ptask->head[42], &msg_length, 4);
                    //printf("381 head[42]: %s, msglen is:  %d\n", &ptask->head[42], msg_length);
                    //*************************生成消息头和消息
                    //printf("head: %s\n", ptask->head);
                    //printf("malloc :   %d\n", ptask);
                    ptask->fd = sockfd;
                    //strcpy(ptask->head, head);
                    //设置用于注测的写操作事件
                    ev.data.ptr = ptask;
                    ev.events = EPOLLOUT|EPOLLET;
                    //修改sockfd上要处理的事件为EPOLLOUT
                    epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
                    //write_chatlog_s(ptask->head, ptask->bu);
                    bzero(head, 64);
                    //********************************群发上线提醒
                    semop_ret=semop(sem_id, &semwait, 1);
                    //semop(sem_id, &semsignal, 1);
                    for (j = 0; j < msg_length; j += 20)
                    {
                        int msg_len = 0;
                        strncpy(buf_online.username, &ptask->buffer[j], 20);
                        if(strncmp(buf_online.username, &ptask->head[22], 20) == 0)
                            continue;
                        search_online_member(&buf_online, shmid_hash_table, shmid_empty_list, shmid_online_table);
                        printf("search success: %s\n", buf_online.username);
                        
                        if(buf_online.pid == getpid())
                        {
                            ptask_transfer = NULL;
                            ptask_transfer = (task_t*)malloc(sizeof(task_t));
                            
                            if (ptask_transfer == NULL)
                            {
                                fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                                while(ptask_transfer == NULL)
                                {
                                    ptask_transfer = (task_t*)malloc(sizeof(task_t));
                                }
                            }
                            
                            bzero(ptask_transfer, sizeof(task_t));
                            
                            strncpy(ptask_transfer->head, "CA", 2);//********用户上线指令
                            strncpy(&ptask_transfer->head[2], &ptask->head[22], 20);
                            strncpy(&ptask_transfer->head[22], buf_online.username, 20);
                            memcpy(&ptask_transfer->head[42], &ptask->head[42], 4);
                            ptask_transfer->fd = buf_online.fd;
                            //printf("412 new events!!!");
                            
                            ev.data.ptr = ptask_transfer;
                            ev.events = EPOLLOUT | EPOLLET;
                            epoll_ctl(epfd, EPOLL_CTL_MOD, buf_online.fd, &ev);
                        }
                        else
                        {
                            sprintf(path, "%s%d", PATH, buf_online.pid);
                            printf("436  transfer pid: %d, this pid %d, path:   %s\n", buf_online.pid, getpid(), path);
                            //int unixd_len = strlen(unixd_addr.sun_path)+sizeof(unixd_addr.sun_family);
                            int unixd_sockfd_transfer = 0;
                            struct sockaddr_un  unixd_addr_transfer;
                            bzero(&unixd_addr_transfer, sizeof(unixd_addr_transfer));
                            strcpy(unixd_addr_transfer.sun_path, path);
                            unixd_addr_transfer.sun_family = AF_UNIX;
                            unixd_sockfd_transfer = socket(AF_UNIX,SOCK_DGRAM,0);
                            if(unixd_sockfd_transfer < 0)
                            {
                                perror("socket error");
                                exit(-1);
                            }
                            int unixd_len_transfer = strlen(unixd_addr_transfer.sun_path)+sizeof(unixd_addr_transfer.sun_family);
                            strncpy(head, "CA", 2);
                            strncpy(&head[2], &ptask->head[22], 20);
                            strncpy(&head[22], buf_online.username, 20);
                            memcpy(&head[42], &msg_len, 4);
                            
                            sendto(unixd_sockfd_transfer, head, HEADLENGTH, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);
                            bzero(head, HEADLENGTH);
                        }
                        //printf("ready to transfer!!   %j\n", j);
                    }
                    semop(sem_id, &semsignal, 1);
                    //printf("broadcast over!!!\n");
                    //*******************群发上线提醒
                }
                else if(strncmp(head, "LO", 2) == 0)//正常断开连接的操作
                {
                    strncpy(buf_online.username, &head[2], 20);
                    strncpy(buf_online.grade, "ISRC2012", 10);
                    buf_online.fd = sockfd;
                    buf_online.pid = getpid();
                    buf_online.next = -1;
                    semop_ret=semop(sem_id, &semwait, 1);
                    //
                    delete_online_member(&buf_online, shmid_hash_table, shmid_empty_list, shmid_online_table);
                    semop(sem_id, &semsignal, 1);
                    print_online_table(shmid_online_table, shmid_hash_table);

                    ptask = NULL;
                    ptask = (task_t*)malloc(sizeof(task_t));//安全分配内存
                    if (ptask == NULL)
                    {
                        fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                        while(ptask == NULL)
                        {
                            ptask = (task_t*)malloc(sizeof(task_t));
                        }
                    }                    
                    bzero(ptask, sizeof(task_t));
                    
                    msg_length = sprint_online_table(ptask->buffer, shmid_online_table, shmid_hash_table);
                    
                    strncpy(ptask->head, "LG", 2);
                    strncpy(&ptask->head[2], "server", 20);
                    strncpy(&ptask->head[22], buf_online.username, 20);
                    //printf("348   buf_online  :%s\n", buf_online.username);
                    memcpy(&ptask->head[42], &msg_length, 4);
                    
                    close(sockfd);
                    events[i].data.fd = -1;
                    //*****************群发下线提醒
                    semop_ret=semop(sem_id, &semwait, 1);
                    //
                    for (j = 0; j < msg_length; j += 20)
                    {
                        int msg_len = 0;
                        strncpy(buf_online.username, &ptask->buffer[j], 20);
                        if(strncmp(buf_online.username, &ptask->head[22], 20) == 0)
                            continue;
                        search_online_member(&buf_online, shmid_hash_table, shmid_empty_list, shmid_online_table);
                        printf("search success: %s\n", buf_online.username);
                        
                        if(buf_online.pid == getpid())
                        {
                            ptask_transfer = NULL;
                            ptask_transfer = (task_t*)malloc(sizeof(task_t));
                            if (ptask_transfer == NULL)
                            {
                                fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                                while(ptask_transfer == NULL)
                                {
                                    ptask_transfer = (task_t*)malloc(sizeof(task_t));
                                }
                            }
                            bzero(ptask_transfer, sizeof(task_t));
                            
                            strncpy(ptask_transfer->head, "CD", 2);//********用户上线指令
                            strncpy(&ptask_transfer->head[2], &ptask->head[22], 20);
                            strncpy(&ptask_transfer->head[22], buf_online.username, 20);
                            memcpy(&ptask_transfer->head[42], &msg_len, 4);
                            ptask_transfer->fd = buf_online.fd;
                            //printf("412 new events!!!");
                            
                            ev.data.ptr = ptask_transfer;
                            ev.events = EPOLLOUT | EPOLLET;
                            epoll_ctl(epfd, EPOLL_CTL_MOD, buf_online.fd, &ev);
                        }
                        else
                        {
                            sprintf(path, "%s%d", PATH, buf_online.pid);
                            //printf("436  transfer pid: %d, this pid %d, path:   %s\n", buf_online.pid, getpid(), path);
                            //int unixd_len = strlen(unixd_addr.sun_path)+sizeof(unixd_addr.sun_family);
                            int unixd_sockfd_transfer = 0;
                            struct sockaddr_un  unixd_addr_transfer;
                            bzero(&unixd_addr_transfer, sizeof(unixd_addr_transfer));
                            strcpy(unixd_addr_transfer.sun_path, path);
                            unixd_addr_transfer.sun_family = AF_UNIX;
                            unixd_sockfd_transfer = socket(AF_UNIX,SOCK_DGRAM,0);
                            if(unixd_sockfd_transfer < 0)
                            {
                                perror("socket error");
                                exit(-1);
                            }
                            int unixd_len_transfer = strlen(unixd_addr_transfer.sun_path)+sizeof(unixd_addr_transfer.sun_family);
                            strncpy(head, "CD", 2);
                            strncpy(&head[2], &ptask->head[22], 20);
                            strncpy(&head[22], buf_online.username, 20);
                            memcpy(&head[42], &ptask->head[42], 4);
                            
                            sendto(unixd_sockfd_transfer, head, HEADLENGTH, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);
                            //free(ptask);//11-10 修改。。。。
                            bzero(head, HEADLENGTH);
                        }
                        //printf("ready to transfer!!   %j\n", j);
                    }
                    semop(sem_id, &semsignal, 1);
                    //printf("broadcast over!!!\n");                    
                    //*****************群发下线提醒
                    //
                    if(ptask != NULL)
                        free(ptask);
                    ptask = NULL;
                    msg_length = 0;
                }
                else if(strncmp(head, "IM", 2) == 0)
                {
                    strncpy(buf_online.username, &head[22], 20);
                    memcpy(&msg_length, &head[42], 4);
                    /*ptask = (task_t*)malloc(sizeof(task_t));
                    memcpy(ptask->head, head, 64);
                    recv(sockfd, ptask->buffer, msg_length, 0);*/
                    semop_ret=semop(sem_id, &semwait, 1);
                    if(search_online_member(&buf_online, shmid_hash_table, shmid_empty_list, shmid_online_table) == -1)
                    {
                        printf("can't find the user\n");
                        char norecvbuf[MAXLINE];
                        recv(sockfd, norecvbuf, msg_length, 0);
                        semop(sem_id, &semsignal, 1);
                        //离线日志的操作***************************
                        
                        continue;
                    }
                    semop(sem_id, &semsignal, 1);
                    
                    ev.data.fd =sockfd;
                //设置用于注测的读操作事件
                    ev.events = EPOLLIN | EPOLLET;
                    epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
                    
                    if(buf_online.pid == getpid())
                    {
                        ptask = NULL;
                        
                        ptask = (task_t*)malloc(sizeof(task_t));//安全分配内存
                        
                        if (ptask == NULL)
                        {
                            fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                            while(ptask == NULL)
                            {
                                ptask = (task_t*)malloc(sizeof(task_t));
                            }
                        }
                        bzero(ptask, sizeof(task_t));
                        
                        memcpy(ptask->head, head, 64);
                        if(msg_length != 0)
                        {
                            recv(sockfd, ptask->buffer, msg_length, 0);
                        }
                        //printf("563 the im data is %s\n", ptask->buffer);
                        
                        write_chatlog_s(head, ptask->buffer);//写发送者聊天日志
                        
                        ptask->fd = buf_online.fd;
                        ev.data.ptr = ptask;
                        ev.events = EPOLLOUT|EPOLLET;    
                        epoll_ctl(epfd, EPOLL_CTL_MOD, ptask->fd, &ev);
                    }
                    else
                    {
                        char im_buf[MAXLINE+1];
                        recv(sockfd, im_buf, msg_length, 0);
                        
                        sprintf(path, "%s%d", PATH, buf_online.pid);
                        //printf("436  transfer pid: %d, this pid %d, path:   %s\n", buf_online.pid, getpid(), path);
                            //int unixd_len = strlen(unixd_addr.sun_path)+sizeof(unixd_addr.sun_family);
                        int unixd_sockfd_transfer = 0;
                        struct sockaddr_un  unixd_addr_transfer;
                        bzero(&unixd_addr_transfer,sizeof(unixd_addr_transfer));
                        strcpy(unixd_addr_transfer.sun_path, path);
                        unixd_addr_transfer.sun_family = AF_UNIX;
                        unixd_sockfd_transfer = socket(AF_UNIX,SOCK_DGRAM,0);
                        if(unixd_sockfd_transfer < 0)
                        {
                            perror("socket error");
                            exit(-1);
                        }
                        int unixd_len_transfer = strlen(unixd_addr_transfer.sun_path)+sizeof(unixd_addr_transfer.sun_family);    
                        sendto(unixd_sockfd_transfer, head, HEADLENGTH, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);
                        sendto(unixd_sockfd_transfer, im_buf, msg_length, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);
                        //***********************在相应进程的域套接字接收在进行转发************
                    }
                    bzero(head, 64);
                }
                else if(strncmp(head, "HM", 2) == 0)
                {
                    int num;
                    memcpy(&num, &head[42], 4);
                    
                    ptask = NULL;
                    ptask = (task_t*)malloc(sizeof(task_t));//安全分配内存
                    
                    if (ptask == NULL)
                    {
                        fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                        while(ptask == NULL)
                        {
                            ptask = (task_t*)malloc(sizeof(task_t));
                        }
                    }
                    bzero(ptask, sizeof(task_t));
                    
                    int len;
                    len = read_chatlog(head, ptask->buffer, num);
                    if(len == -1)
                    {
                        //free(ptask);
                        len = 0;
                        strncpy(ptask->head, head, 2);
                        strncpy(&ptask->head[2], &head[22], 20);
                        strncpy(&ptask->head[22], &head[2], 20);
                        memcpy(&ptask->head[42], &len, 4);
                        memcpy(&ptask->head[46], &head[46], 18);
                        bzero(head, 64);
                        ptask->fd = sockfd;
                        ev.data.ptr = ptask;
                        ev.events = EPOLLOUT | EPOLLET;
                        //修改sockfd上要处理的事件为EPOLLOUT
                        epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);                        
                        continue;
                    }
                    strncpy(ptask->head, head, 2);
                    strncpy(&ptask->head[2], &head[22], 20);
                    strncpy(&ptask->head[22], &head[2], 20);
                    memcpy(&ptask->head[42], &len, 4);
                    memcpy(&ptask->head[46], &head[46], 18);
                    printf("hm the number: %d, the len:  %d\n", num, len);
                    ptask->fd = sockfd;
                    ev.data.ptr = ptask;
                    ev.events = EPOLLOUT | EPOLLET;
                    //修改sockfd上要处理的事件为EPOLLOUT
                    epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
                }
                else if(strncmp(head, "FS", 2) == 0)
                {
                    //********将最初收到的文件信息存入临时文件
                    char file_name[30];
                    bzero(file_name, 30);
                    recv(sockfd, &file_name[14], 16, 0);
                    strncpy(file_name, &head[50], 14);
                    char sender[20];
                    strncpy(sender, &head[2], 20);
                    char file_path[100];
                    sprintf(file_path, "./log/file/%s/%s.tmp", sender, file_name);
                    int fd = open(file_path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
                    char file_info[40];
                    bzero(file_info, 40);
                    int len;
                    memcpy(&len, &head[42], 4);
                    recv(sockfd, file_info, len, 0);
                    if(fd == -1)
                    {
                        fprintf(stderr, "open tmp error: %s\n", strerror(errno));
                        continue;
                    }
                    write(fd, head, 50);
                    write(fd, file_name, 30);
                    write(fd, file_info, len);
                    close(fd);
                    //*******写日志记录
                    char log_path[100];
                    sprintf(log_path, "./log/file/%s/filelog", sender);
                    int log_fd = open(log_path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
                    write(fd, head, 50);
                    write(fd, file_name, 30);
                    write(fd, file_info, len);                    
                    close(log_fd);
                    ev.data.fd =sockfd;
                    //设置用于注测的读操作事件
                    ev.events = EPOLLIN | EPOLLET;
                    epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
                    bzero(head, HEADLENGTH);
                    
                }
                else if(strncmp(head, "FM", 2) == 0)
                {
                    char file_name[30];
                    bzero(file_name, 30);
                    recv(sockfd, &file_name[14], 16, 0);
                    strncpy(file_name, &head[50], 14);
                    char sender[20];
                    strncpy(sender, &head[2], 20);
                    char file_path[100];
                    sprintf(file_path, "./log/file/%s/%s", sender, file_name);
                    int len, rest;
                    memcpy(&len, &head[42], 4);
                    memcpy(&rest, &head[46], 4);
                    int fd = open(file_path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR );
                    if(fd == -1)
                    {
                        fprintf(stderr, "open tmp error: %s\n", strerror(errno));
                        continue;
                    }
                    char fmbuf[MAXLINE];
                    bzero(fmbuf, MAXLINE);
                    //int file_len = recv(sockfd, fmbuf, len, 0);
                    RecvData(sockfd, fmbuf, len);
                    WriteData(fd, fmbuf, len);
                    //printf("file_len: %d\n", file_len);
                    close(fd);
                    if(rest == 0)
                    {

                        //转发文件的到来的提醒,删除临时文件
                        //char receiver[20];
                        bzero(buf_online.username, 20);
                        strncpy(buf_online.username, &head[22], 20);
                        semop_ret=semop(sem_id, &semwait, 1);
                        if(search_online_member(&buf_online, shmid_hash_table, shmid_empty_list, shmid_online_table) == -1)
                        {
                            printf("can't find the user\n");
                            semop(sem_id, &semsignal, 1);
                            //**********************离线操作
                        }
                        semop(sem_id, &semsignal, 1);
                        
                        char tmp_path[100];
                        bzero(tmp_path, 100);
                            
                        sprintf(tmp_path, "./log/file/%s/%s.tmp", sender, file_name);
                        int tmp_fd = open(tmp_path, O_RDWR);
                            
                        char buf[104];//tmp中文件信息的长度
                        bzero(buf, 104);
                            
                        int tmp_len = 0;
                        while(1)
                        {
                            tmp_len += read(tmp_fd, &buf[tmp_len], 104-tmp_len);
                            if(tmp_len < 0 | tmp_len == 104)
                            {
                                break;
                            }
                        }
                        if(tmp_len < 0)
                        {
                            fprintf(stderr, "open tmp error: %s\n", strerror(errno));
                            continue;
                        }    

                        /*printf("768 buffer %s\n", buf);
                        int j;
                        for(j = 0; j < tmp_len; j++)
                            printf(" %c", buf[j]);*/
                        
                        if(buf_online.pid == getpid())
                        {
                            ptask = NULL;
                            ptask = (task_t*)malloc(sizeof(task_t));
                            
                            if (ptask == NULL)
                            {
                                fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                                while(ptask == NULL)
                                {
                                    ptask = (task_t*)malloc(sizeof(task_t));
                                }
                            }
                            bzero(ptask, sizeof(task_t));

                            memcpy(ptask->head, buf, 64);
                            memcpy(ptask->buffer, &buf[64], 40);
                            tmp_len -= 64;
                            memcpy(&ptask->head[42], &tmp_len, 4);
                            
                            ptask->fd = buf_online.fd;
                            ev.data.ptr = ptask;
                            ev.events = EPOLLOUT | EPOLLET;
                            epoll_ctl(epfd, EPOLL_CTL_MOD, ptask->fd, &ev);
                            
                        }
                        else
                        {
                            char tmp_head[HEADLENGTH];
                            memcpy(&tmp_head, buf, 64);
                            tmp_len -= 64;
                            memcpy(&tmp_head, &tmp_len, 4);
                            
                            sprintf(path, "%s%d", PATH, buf_online.pid);
                            int unixd_sockfd_transfer = 0;
                            struct sockaddr_un  unixd_addr_transfer;
                            bzero(&unixd_addr_transfer,sizeof(unixd_addr_transfer));
                            strcpy(unixd_addr_transfer.sun_path, path);
                            unixd_addr_transfer.sun_family = AF_UNIX;
                            unixd_sockfd_transfer = socket(AF_UNIX,SOCK_DGRAM,0);
                            if(unixd_sockfd_transfer < 0)
                            {
                                perror("socket error");
                                exit(-1);
                            }
                            int unixd_len_transfer = strlen(unixd_addr_transfer.sun_path)+sizeof(unixd_addr_transfer.sun_family);    
                            sendto(unixd_sockfd_transfer, tmp_head, HEADLENGTH, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);
                            sendto(unixd_sockfd_transfer, &buf[64], tmp_len, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);                             
                        }    
                        close(tmp_fd);    
                        //*************************写接收者的日志
                        char receiver_file_path[100], receiver_log_path[100];
                        bzero(receiver_file_path, 100);
                        bzero(receiver_log_path, 100);
                        char receiver[20];
                        bzero(receiver, 20);
                        strncpy(receiver, &head[22], 20);
                        sprintf(receiver_file_path, "./log/file/%s/%s", receiver, file_name);
                        sprintf(receiver_log_path, "./log/file/%s/filelog", receiver);
                        if(link(file_path, receiver_file_path) == -1)
                        {
                            fprintf(stderr, "link error!!\n", strerror(errno));
                        }
                        int log_fd = open(receiver_log_path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
                        if(log_fd == -1)
                        {
                            fprintf(stderr, "link error!!\n", strerror(errno));
                        }
                        else
                        {
                            int write_len = write(log_fd, buf, 104);
                            if (write_len < 104)
                            {
                                WriteData(log_fd, &buf[write_len], 104-write_len);
                            }
                            close(log_fd);
                            //write(file_name, );
                        }
                        
                        char cmd[140];
                        bzero(cmd, 140);
                        sprintf(cmd, "rm ./log/file/%s/\"%s.tmp\"", sender, file_name);
                        //printf("cmd: %s\n", cmd);
                        system(cmd);
                        bzero(&buf_online, sizeof(buf_online));
                    
                    }
                    ev.data.fd =sockfd;
                //设置用于注测的读操作事件
                    ev.events = EPOLLIN | EPOLLET;
                    epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
                    bzero(head, HEADLENGTH);
                    
                }
                else if(strncmp(head, "FD", 2) == 0)
                {
                    char file_name[30];
                    bzero(file_name, 30);
                    
                    recv(sockfd, &file_name[14], 16, 0);
                    
                    memcpy(file_name, &head[50], 14);
                    char receiver[20];
                    bzero(receiver, 20);
                    strncpy(receiver, &head[22], 20);
                    int pos, len;
                    memcpy(&pos, &head[46], 4);
                    
                    char file_path[100];
                    bzero(file_path, 100);
                    sprintf(file_path, "./log/file/%s/%s", receiver, file_name);
                    
                    int fd = open(file_path, O_RDONLY);
                    if(fd == -1)
                    {
                        fprintf(stderr, "read file: %s error:  %s\n", file_path, strerror(errno));
                        bzero(head, 64);
                        continue;
                    }
                    else
                    {
                        ptask = NULL;
                        ptask = (task_t*)malloc(sizeof(task_t));
                        if (ptask == NULL)
                        {
                            fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                            while(ptask == NULL)
                            {
                                ptask = (task_t*)malloc(sizeof(task_t));
                            }
                        }
                        
                        bzero(ptask, sizeof(task_t));
                        
                        if(lseek(fd, pos, SEEK_SET) == -1)
                        {
                            fprintf(stderr,"lseek error: %s\n", strerror(errno));
                        }
                        printf("pos:  %d\n", pos);
                        memcpy(ptask->buffer, &file_name[14], 16);
                        len = read(fd, &ptask->buffer[16], 1008);//为了扩展文件名,,,此处每次最多读1010字节
                        pos += len;
                        len += 16;
                        memcpy(&head[46], &pos, 4);
                        memcpy(&head[42], &len, 4);
                        memcpy(ptask->head, head, 64);
                        ptask->fd = sockfd;
                        
                        ev.data.ptr = ptask;
                        //设置用于注测的读操作事件
                        ev.events = EPOLLOUT | EPOLLET;
                        epoll_ctl(epfd, EPOLL_CTL_MOD, ptask->fd, &ev);
                        
                    }
                    close(fd);
                    bzero(head, 64);
                }
                else if(strncmp(head, "HF", 2) == 0)
                {
                    char log_path[100], sender[20];
                    bzero(log_path, 100);
                    bzero(sender, 20);
                    memcpy(sender, &head[2], 20);
                    sprintf(log_path, "./log/file/%s/filelog", sender);
                    /*
                    int file_log = open(log_path, O_RDONLY);
                    if(file_log < 0)
                    {
                        fprintf(stderr, "open file log error: %s\n", strerror(errno));
                        continue;
                    }*/
                    ptask = NULL;
                    ptask = (task_t*)malloc(sizeof(task_t));//安全分配内存
                    
                    if (ptask == NULL)
                    {
                        fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                        while(ptask == NULL)
                        {
                            ptask = (task_t*)malloc(sizeof(task_t));
                        }
                    }
                    bzero(ptask, sizeof(task_t));
                    memcpy(ptask->head, head, 64);
                    memcpy(ptask->buffer, log_path, 100);
                    
                    ptask->fd = sockfd;
                    ev.data.ptr = ptask;
                    ev.events = EPOLLOUT | EPOLLET;
                    //修改sockfd上要处理的事件为EPOLLOUT
                    epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
                }
                else if(strncmp(head, "MC", 2) == 0)
                {
                    char meeting_name[40];
                    bzero(meeting_name, 40);
                    RecvData(sockfd, meeting_name, 40);
                    int mfd = open("./log/meeting/meeting", O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
                    if(mfd < 0)
                    {
                        fprintf(stderr, "open meeting error: %s\n", strerror(errno));
                        continue;
                    }
                    WriteData(mfd, meeting_name, 40);
                    char meeting_member[120], meeting_log[120];
                    bzero(meeting_member, 120);
                    bzero(meeting_log, 120);
                    sprintf(meeting_log, "./log/meeting/meeting_log_%s", meeting_name);
                    sprintf(meeting_member, "./log/meeting/meeting_member_%s", meeting_name);
                    int lfd = open(meeting_log, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
                    int mbfd = open(meeting_member, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
                    if(lfd < 0 || mbfd < 0)
                    {
                        fprintf(stderr, "open log error: %s\n", strerror(errno));
                        close(mfd);
                        continue;
                    }
                    WriteData(mbfd, &head[2], 20);//*******************************************是否写进日志
                    close(mfd);
                    close(lfd);
                    close(mbfd);
                    
                    ev.data.fd =sockfd;
                //设置用于注测的读操作事件
                    ev.events = EPOLLIN | EPOLLET;
                    epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
                }
                else if(strncmp(head, "MI", 2) == 0 || strncmp(head, "MR", 2) == 0)
                {
                    char meeting_name[40];
                    bzero(meeting_name, 40);
                    
                    RecvData(sockfd, meeting_name, 40);
                    
                    bzero(&buf_online, sizeof(buf_online));
                    //int len = 40;
                    strncpy(buf_online.username, &head[22], 20);
                    memcpy(&msg_length, &head[42], 4);
                    char data[MAXLINE-40];
                    if(msg_length - 40 > 0)
                    {    
                        bzero(data, MAXLINE-40);
                        RecvData(sockfd, data, msg_length - 40);
                    }
                    /*ptask = (task_t*)malloc(sizeof(task_t));
                    memcpy(ptask->head, head, 64);
                    recv(sockfd, ptask->buffer, msg_length, 0);*/
                    semop_ret=semop(sem_id, &semwait, 1);
                    if(search_online_member(&buf_online, shmid_hash_table, shmid_empty_list, shmid_online_table) == -1)
                    {
                        printf("can't find the user\n");
                        //char norecvbuf[MAXLINE];
                        //recv(sockfd, norecvbuf, msg_length, 0);
                        semop(sem_id, &semsignal, 1);                        
                        continue;
                    }
                    semop(sem_id, &semsignal, 1);
                    
                    ev.data.fd =sockfd;
                //设置用于注测的读操作事件
                    ev.events = EPOLLIN | EPOLLET;
                    epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
                    
                    if(buf_online.pid == getpid())
                    {
                        ptask = NULL;
                        
                        ptask = (task_t*)malloc(sizeof(task_t));//安全分配内存
                        
                        if (ptask == NULL)
                        {
                            fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                            while(ptask == NULL)
                            {
                                ptask = (task_t*)malloc(sizeof(task_t));
                            }
                        }
                        bzero(ptask, sizeof(task_t));
                        
                        memcpy(ptask->head, head, 64);
                        memcpy(ptask->buffer, meeting_name, 40);
                        if(msg_length > 40)
                            memcpy(&ptask->buffer[40], data, msg_length - 40);
                        /*if(msg_length != 0)
                        {
                            recv(sockfd, ptask->buffer, msg_length, 0);
                        }*/
                        //printf("563 the im data is %s\n", ptask->buffer);
                        
                        //write_chatlog_s(head, ptask->buffer);//写发送者聊天日志
                        
                        ptask->fd = buf_online.fd;
                        ev.data.ptr = ptask;
                        ev.events = EPOLLOUT|EPOLLET;    
                        epoll_ctl(epfd, EPOLL_CTL_MOD, ptask->fd, &ev);
                    }
                    else
                    {
                        //char im_buf[MAXLINE+1];
                        //recv(sockfd, im_buf, msg_length, 0);
                        
                        sprintf(path, "%s%d", PATH, buf_online.pid);
                        //printf("436  transfer pid: %d, this pid %d, path:   %s\n", buf_online.pid, getpid(), path);
                            //int unixd_len = strlen(unixd_addr.sun_path)+sizeof(unixd_addr.sun_family);
                        int unixd_sockfd_transfer = 0;
                        struct sockaddr_un  unixd_addr_transfer;
                        bzero(&unixd_addr_transfer,sizeof(unixd_addr_transfer));
                        strcpy(unixd_addr_transfer.sun_path, path);
                        unixd_addr_transfer.sun_family = AF_UNIX;
                        unixd_sockfd_transfer = socket(AF_UNIX,SOCK_DGRAM,0);
                        if(unixd_sockfd_transfer < 0)
                        {
                            perror("socket error");
                            exit(-1);
                        }
                        int unixd_len_transfer = strlen(unixd_addr_transfer.sun_path)+sizeof(unixd_addr_transfer.sun_family);    
                        sendto(unixd_sockfd_transfer, head, HEADLENGTH, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);
                        sendto(unixd_sockfd_transfer, meeting_name, 40, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);
                        if(msg_length > 40)
                            sendto(unixd_sockfd_transfer, data, msg_length - 40, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);
                        //***********************在相应进程的域套接字接收在进行转发************
                    }
                    bzero(head, 64);                    
                }
                else if(strncmp(head, "MJ", 2) == 0 || strncmp(head, "MA", 2) == 0)//MJ 需要些日志
                {
                    char meeting_name[40];
                    bzero(meeting_name, 40);
                    RecvData(sockfd, meeting_name, 40);
                    
                    bzero(&buf_online, sizeof(buf_online));
                    //int len = 40;
                    strncpy(buf_online.username, &head[22], 20);
                    memcpy(&msg_length, &head[42], 4);

                    semop_ret=semop(sem_id, &semwait, 1);
                    if(search_online_member(&buf_online, shmid_hash_table, shmid_empty_list, shmid_online_table) == -1)
                    {
                        printf("can't find the user\n");
                        //char norecvbuf[MAXLINE];
                        //recv(sockfd, norecvbuf, msg_length, 0);
                        semop(sem_id, &semsignal, 1);                        
                        continue;
                    }
                    semop(sem_id, &semsignal, 1);
                    
                    if (strncmp(head, "MJ", 2) == 0)
                    {
                        char logpath[120];
                        bzero(logpath, 120);
                        sprintf(logpath, "./log/meeting/meeting_member_%s", meeting_name);
                        int logfd = open(logpath, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
                        if (logfd < 0)
                        {
                            fprintf(stderr, "open log error: %s!!\n", strerror(errno));
                        }
                        else
                        {
                            WriteData(logfd, &head[2], 20);
                            close(logfd);
                        }
                    }
                    
                    ev.data.fd =sockfd;
                //设置用于注测的读操作事件
                    ev.events = EPOLLIN | EPOLLET;
                    epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
                    
                    if(buf_online.pid == getpid())
                    {
                        ptask = NULL;
                        
                        ptask = (task_t*)malloc(sizeof(task_t));//安全分配内存
                        
                        if (ptask == NULL)
                        {
                            fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                            while(ptask == NULL)
                            {
                                ptask = (task_t*)malloc(sizeof(task_t));
                            }
                        }
                        bzero(ptask, sizeof(task_t));
                        
                        memcpy(ptask->head, head, 64);
                        memcpy(ptask->buffer, meeting_name, 40);
                        /*if(msg_length > 40)
                            memcpy(&ptask->buffer[40], data, msg_length - 40);*/
                        /*if(msg_length != 0)
                        {
                            recv(sockfd, ptask->buffer, msg_length, 0);
                        }*/
                        //printf("563 the im data is %s\n", ptask->buffer);
                        
                        //write_chatlog_s(head, ptask->buffer);//写发送者聊天日志
                        
                        ptask->fd = buf_online.fd;
                        ev.data.ptr = ptask;
                        ev.events = EPOLLOUT|EPOLLET;    
                        epoll_ctl(epfd, EPOLL_CTL_MOD, ptask->fd, &ev);
                    }
                    else
                    {
                        //char im_buf[MAXLINE+1];
                        //recv(sockfd, im_buf, msg_length, 0);
                        
                        sprintf(path, "%s%d", PATH, buf_online.pid);
                        //printf("436  transfer pid: %d, this pid %d, path:   %s\n", buf_online.pid, getpid(), path);
                            //int unixd_len = strlen(unixd_addr.sun_path)+sizeof(unixd_addr.sun_family);
                        int unixd_sockfd_transfer = 0;
                        struct sockaddr_un  unixd_addr_transfer;
                        bzero(&unixd_addr_transfer,sizeof(unixd_addr_transfer));
                        strcpy(unixd_addr_transfer.sun_path, path);
                        unixd_addr_transfer.sun_family = AF_UNIX;
                        unixd_sockfd_transfer = socket(AF_UNIX,SOCK_DGRAM,0);
                        if(unixd_sockfd_transfer < 0)
                        {
                            perror("socket error");
                            exit(-1);
                        }
                        int unixd_len_transfer = strlen(unixd_addr_transfer.sun_path)+sizeof(unixd_addr_transfer.sun_family);    
                        sendto(unixd_sockfd_transfer, head, HEADLENGTH, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);
                        sendto(unixd_sockfd_transfer, meeting_name, 40, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);
                        /*if(msg_length > 40)
                            sendto(unixd_sockfd_transfer, data, msg_length - 40, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);*/
                        //***********************在相应进程的域套接字接收在进行转发************
                    }
                    bzero(head, 64);                    
                }
                else if(strncmp(head, "MM", 2) == 0)//写日志
                {
                    printf("receive MM head : %s\n", head);
                    char meeting_name[40];
                    bzero(meeting_name, 40);
                    
                    int len, pos, ll;
                    memcpy(&len, &head[42], 4);
                    memcpy(&pos, &head[46], 4);
                    printf("pos: %d, len: %d\n", pos, len);
                    char *members = (char *)malloc(pos*sizeof(char));
                    char *message = (char *)malloc(len*sizeof(char));
                    ll = len + 40;
                    memcpy(&head[42], &ll, 4);
                    
                    while(members == NULL)
                    {
                        fprintf(stderr, "malloc error: %s!!\n", strerror(errno));
                        members = (char *)malloc(pos*sizeof(char));
                    }
                    
                    while(message == NULL)
                    {
                        fprintf(stderr, "malloc error: %s!!\n", strerror(errno));
                        message = (char *)malloc(len*sizeof(char));
                    }
                    
                    bzero(members, pos);
                    bzero(message, len);
                    RecvData(sockfd, meeting_name, 40);
                    RecvData(sockfd, members, pos);
                    RecvData(sockfd, message, len);
                    printf("members: %s\n", members);
                    printf("message: %s\n", message);
                    int i;
                    for(i = 0; i < pos; i+= 20)
                    {
                        bzero(&buf_online, sizeof(buf_online));
                        memcpy(buf_online.username, &members[i], 20);
                        semop_ret=semop(sem_id, &semwait, 1);
                        if(search_online_member(&buf_online, shmid_hash_table, shmid_empty_list, shmid_online_table) == -1)
                        {
                            printf("can't find member!!\n");
                            semop(sem_id, &semsignal, 1);        
                            continue;
                        }
                        semop(sem_id, &semsignal, 1);        
                        if(buf_online.pid == getpid())
                        {
                            ptask = NULL;
                        
                            ptask = (task_t*)malloc(sizeof(task_t));//安全分配内存
                        
                            if (ptask == NULL)
                            {
                                fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                                while(ptask == NULL)
                                {
                                    ptask = (task_t*)malloc(sizeof(task_t));
                                }
                            }
                            bzero(ptask, sizeof(task_t));
                        
                            memcpy(ptask->head, head, 64);
                            memcpy(ptask->buffer, meeting_name, 40);
                            if(len > 0)
                                memcpy(&ptask->buffer[40], message, len);                                                
                            ptask->fd = buf_online.fd;
                            ev.data.ptr = ptask;
                            ev.events = EPOLLOUT|EPOLLET;    
                            epoll_ctl(epfd, EPOLL_CTL_MOD, ptask->fd, &ev);
                        }
                        else
                        {
                            sprintf(path, "%s%d", PATH, buf_online.pid);
                            //printf("436  transfer pid: %d, this pid %d, path:   %s\n", buf_online.pid, getpid(), path);
                            //int unixd_len = strlen(unixd_addr.sun_path)+sizeof(unixd_addr.sun_family);
                            int unixd_sockfd_transfer = 0;
                            struct sockaddr_un  unixd_addr_transfer;
                            bzero(&unixd_addr_transfer,sizeof(unixd_addr_transfer));
                            strcpy(unixd_addr_transfer.sun_path, path);
                            unixd_addr_transfer.sun_family = AF_UNIX;
                            unixd_sockfd_transfer = socket(AF_UNIX,SOCK_DGRAM,0);
                            if(unixd_sockfd_transfer < 0)
                            {
                                perror("socket error");
                                exit(-1);
                            }
                            int unixd_len_transfer = strlen(unixd_addr_transfer.sun_path)+sizeof(unixd_addr_transfer.sun_family);    
                            sendto(unixd_sockfd_transfer, head, HEADLENGTH, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);
                            sendto(unixd_sockfd_transfer, meeting_name, 40, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);
                            if(len > 0)
                                sendto(unixd_sockfd_transfer, message, len, 0, (struct sockaddr*)&unixd_addr_transfer, unixd_len_transfer);
                            //***********************在相应进程的域套接字接收在进行转发************
                        }                        
                        
                    }
                    
                    char logpath[120];
                    bzero(logpath, 120);
                    sprintf(logpath, "./log/meeting/meeting_log_%s", meeting_name);
                    int logfd = open(logpath, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
                    if (logfd < 0)
                    {
                        fprintf(stderr, "open log error: %s!!\n", strerror(errno));
                    }
                    else
                    {
                        memcpy(&head[42], &len, 4);
                        WriteData(logfd, head, 64);
                        WriteData(logfd, message, len);
                        close(logfd);
                    }
                    
                    bzero(head, 64);
                    free(members);
                    free(message);
                    members = NULL;
                    message = NULL;
                }
                else if(strncmp(head, "MH", 2) == 0)
                {
                    /*int meetingfd = open("./log/meeting/meeting");
                    if(meetingfd < 0)
                    {
                        fprintf(stderr, "open log error %s\n", strerror(errno));
                        continue;
                    }*/
                    
                    ptask = NULL;
                    ptask = (task_t*)malloc(sizeof(task_t));//安全分配内存
                    
                    if (ptask == NULL)
                    {
                        fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                        while(ptask == NULL)
                        {
                            ptask = (task_t*)malloc(sizeof(task_t));
                        }
                    }
                    bzero(ptask, sizeof(task_t));                    
                    memcpy(ptask->head, head, 64);
                    ptask->fd = sockfd;
                    ev.data.ptr = ptask;
                    ev.events = EPOLLOUT | EPOLLET;
                    //修改sockfd上要处理的事件为EPOLLOUT
                    epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
                }
                else if(strncmp(head, "ML", 2) == 0)
                {
                    char meeting_name[40];
                    bzero(meeting_name, 40);
                    RecvData(sockfd, meeting_name, 40);
                    ptask = NULL;
                    ptask = (task_t*)malloc(sizeof(task_t));//安全分配内存
                    
                    if (ptask == NULL)
                    {
                        fprintf(stderr, "malloc error : %s!!\n", strerror(errno));
                        while(ptask == NULL)
                        {
                            ptask = (task_t*)malloc(sizeof(task_t));
                        }
                    }
                    bzero(ptask, sizeof(task_t));                    
                    memcpy(ptask->head, head, 64);
                    memcpy(ptask->buffer, meeting_name, 40);
                    ptask->fd = sockfd;
                    ev.data.ptr = ptask;
                    ev.events = EPOLLOUT | EPOLLET;
                    //修改sockfd上要处理的事件为EPOLLOUT
                    epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);                    
                }
            }
            else if(events[i].events & EPOLLOUT) // 如果有数据发送
            {
                sockfd = ((task_t*)(events[i].data.ptr))->fd;
                ptask = (task_t*)events[i].data.ptr;
                
                printf("593 send msglength:%d, head[42]  :%s\n", msg_length, &head[42]);
                memcpy(&msg_length, &ptask->head[42], 4);
                
                if(strncmp(ptask->head, "ML", 2) == 0)
                {
                    char log_path[120], member_path[120];
                    bzero(log_path, 120);
                    bzero(member_path, 120);
                    sprintf(log_path, "./log/meeting/meeting_log_%s", ptask->buffer);
                    sprintf(member_path, "./log/meeting/meeting_member_%s", ptask->buffer);
                    printf("meeting name: %s\n", ptask->buffer);
                    int l_fd, m_fd;
                    if((l_fd = open(log_path, O_RDONLY)) < 0)
                    {
                        fprintf(stderr, "log error: %s\n", strerror(errno));
                    }
                    else if((m_fd = open(member_path, O_RDONLY)) < 0)
                    {
                        fprintf(stderr, "log error: %s\n", strerror(errno));
                    }
                    else
                    {
                        int m_len, l_len;
                        if((m_len = lseek(m_fd, 0, SEEK_END)) < 0)
                        {
                            fprintf(stderr, "lseek file log error: %s\n", strerror(errno));
                        }
                        char *m_buf = (char *)malloc(m_len*sizeof(char));
                        while(m_buf == NULL)
                        {
                            fprintf(stderr, "malloc error: %s!!\n", strerror(errno));
                            m_buf = (char *)malloc(m_len*sizeof(char));
                        }

                        if(lseek(m_fd, 0, SEEK_SET) < 0)
                        {
                            fprintf(stderr, "lseek file log error: %s\n", strerror(errno));
                        }
                        ReadData(m_fd, m_buf, m_len);

                        if((l_len = lseek(l_fd, 0, SEEK_END)) < 0)
                        {
                            fprintf(stderr, "lseek file log error: %s\n", strerror(errno));
                        }
                        char *l_buf = (char *)malloc(l_len*sizeof(char));
                        while(l_buf == NULL)
                        {
                            fprintf(stderr, "malloc error: %s!!\n", strerror(errno));
                            l_buf = (char *)malloc(l_len*sizeof(char));
                        }

                        if(lseek(l_fd, 0, SEEK_SET) < 0)
                        {
                            fprintf(stderr, "lseek file log error: %s\n", strerror(errno));
                        }
                        ReadData(l_fd, l_buf, l_len);                        
                        
                        memcpy(&ptask->head[42], &m_len, 4);
                        memcpy(&ptask->head[46], &l_len, 4);
                        
                        WriteData(ptask->fd, ptask->head, 64);
                        WriteData(ptask->fd, ptask->buffer, 40);
                        WriteData(ptask->fd, m_buf, m_len);
                        WriteData(ptask->fd, l_buf, l_len);
                        
                        free(m_buf);
                        free(l_buf);
                        m_buf = NULL;
                        l_buf = NULL;
                        /////////////
                    }
                    close(l_fd);
                    close(m_fd);
                }
                else if(strncmp(ptask->head, "MH", 2) == 0)
                {
                    int meetingfd = open("./log/meeting/meeting", O_RDONLY);
                    if(meetingfd < 0)
                    {
                        fprintf(stderr, "open log error %s\n", strerror(errno));
                        continue;
                    }
                    int log_len;
                    if((log_len = lseek(meetingfd, 0, SEEK_END)) < 0)
                    {
                        fprintf(stderr, "lseek file log error: %s\n", strerror(errno));
                    }
                    char *log_buf = (char*)malloc(log_len*sizeof(char));
                    while(log_buf == NULL)
                    {
                        fprintf(stderr, "malloc error :%s\n", strerror(errno));
                        log_buf = (char*)malloc(log_len*sizeof(char));
                    }
                    if(lseek(meetingfd, 0, SEEK_SET) < 0)
                    {
                        fprintf(stderr, "lseek file log error: %s\n", strerror(errno));
                        free(log_buf);
                        continue;
                    }
                    int count = log_len/40, i;
                    for(i = 0; i < count; i++)
                        ReadData(meetingfd, &log_buf[i*40], 40);
                    memcpy(&ptask->head[42], &log_len, 4);
                    SendData(ptask->fd, ptask->head, 64);
                    SendData(ptask->fd, log_buf, log_len);
                    free(log_buf);
                    log_buf = NULL;
                }
                else if(strncmp(ptask->head, "HF", 2) == 0)
                {
                    char file_path[100];
                    strncpy(file_path, ptask->buffer, 100);
                    bzero(ptask->buffer, 100);
                    int file_log = open(file_path, O_RDONLY);
                    //printf("HF  ptask->head : %s", ptask->head);
                    if(file_log < 0)
                    {
                        fprintf(stderr, "open file log error: %s\n", strerror(errno));
                    }
                    else
                    {
                        int file_len;
                        if((file_len = lseek(file_log, 0, SEEK_END)) < 0)
                        {
                            fprintf(stderr, "lseek file log error: %s\n", strerror(errno));
                        }
                        //printf("file_log len %d\n", file_len);
                        char *file_buf = NULL;
                        file_buf = (char*)malloc(file_len*sizeof(char));
                        while(file_buf == NULL)
                        {
                            file_buf = (char*)malloc(file_len*sizeof(char));
                        }
                        //printf("after malloc!!\n");
                        if(lseek(file_log, 0, SEEK_SET) < 0)
                        {
                            fprintf(stderr, "lseek file log error: %s\n", strerror(errno));
                        }
                        int count = 0;
                        while(1)
                        {
                            if(ReadData(file_log, &file_buf[count], 104) == -1)
                                break;
                            count += 104;
                            //printf("count = %d\n", count);
                            if (count == file_len)
                                break;
                        }
                        //printf("after read!!\n");
                        memcpy(&ptask->head[42], &file_len, 4);
                        SendData(ptask->fd , ptask->head, 64);
                        SendData(ptask->fd, file_buf, file_len);
                        free(file_buf);
                        close(file_log);
                    }
                }
                else if(strncmp(ptask->head, "FD", 2) == 0)
                {
                    int pos, len;
                    memcpy(&len, &ptask->head[42], 4);
                    memcpy(&pos, &ptask->head[46], 4);
                    char receiver[20], file_name[30];
                    bzero(receiver, 20);
                    bzero(file_name, 30);
                    strncpy(receiver, &ptask->head[22], 20);
                    memcpy(file_name, &ptask->head[50], 14);
                    memcpy(&file_name[14], &ptask->buffer, 16);
                    
                    char file_path[100];
                    bzero(file_path, 100);
                    sprintf(file_path, "./log/file/%s/%s", receiver, file_name);
                    
                    int fd = open(file_path, O_RDONLY);
                    if(fd == -1)
                    {
                        fprintf(stderr, "read file: %s error:  %s\n", file_path, strerror(errno));
                        bzero(head, 64);
                        continue;
                    }    
                    else
                    {
                        //bzero(ptask, sizeof(task_t));
                        
                        if(lseek(fd, pos, SEEK_SET) == -1)
                        {
                            fprintf(stderr,"lseek error: %s\n", strerror(errno));
                        }
                        else
                        {
                            int add_len;
                            char file_buffer[MAXLINE*10];
                            bzero(file_buffer, MAXLINE*10);
                            add_len = read(fd, file_buffer, MAXLINE*10);
                            //printf("add_len:  %d\n", add_len);
                            len += add_len;
                            printf("len : %d\n", len);
                            memcpy(&ptask->head[42], &len, 4);
                            int head_len = send(sockfd, ptask->head, HEADLENGTH, 0);
                            int buf_len = send(sockfd, ptask->buffer, msg_length, 0);
                            int file_len = send(sockfd, file_buffer, add_len, 0);
                            //printf("head_len: %d, buf_len: %d,send file_len %d!!\n", head_len, buf_len, file_len);
                        }
                        close(fd);
                    }
                }
                else
                {
                    int send_len = send(sockfd, ptask->head, HEADLENGTH, 0);
                    printf("send len: %d, : head %s\n", send_len, ptask->head);
                    if(msg_length != 0)
                    {
                        int buf_len = send(sockfd, ptask->buffer, msg_length, 0);
                        printf("send sock is %d, buf_len is %d, data is : %s\n", ptask->fd, buf_len, ptask->buffer);
                    }
                    //设置用于读操作的文件描述符
                    if(strncmp(ptask->head, "IM", 2) == 0)
                    {
                        write_chatlog_r(ptask->head, ptask->buffer);//写接收者的聊天日志
                    }
                }
                ev.data.fd =sockfd;
                //设置用于注测的读操作事件
                ev.events = EPOLLIN | EPOLLET;
                epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
                printf("free: %d\n", ptask);
                if(ptask != NULL)
                    free(ptask);
                else
                    fprintf(stderr, "free error: %s!!\n", strerror(errno));
                ptask = NULL;
                bzero(head, 64);
                //sleep(2);
            }
        }
    }
    return 0;
}

posted @ 2012-11-25 15:18  飞翔的蛋挞  阅读(193)  评论(0)    收藏  举报