“掌中”通讯

1.client

#include <stdio.h>
#include <string.h>
/*socket() connect()  recv()*/
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>  //struct sockaddr_in
#include <pthread.h>  //thread
#include "../protocol/protocol.h"
#include "../link/node.h"
#include "../fileLink/fileNode.h"
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <signal.h>

//#define SERVER 0;

int g_iId=0;
int g_ifOnline=2;
int g_iFlag=0;
int g_iPass=0;
int g_iSockfd=0;
Head *g_pHead=NULL;
//fileHead
#define MAXLEN 1024

void sendDataToServer(int sockfd,ChatPDU *pChatPDU)
{
    if(pChatPDU==NULL)
    {
        return ;
    }
    int iLen=pChatPDU->iChatPDULen;
    int iLeft=iLen;
    int iSend=0;
    int ret=0;

    ret=send(sockfd,pChatPDU,iLen,0);
    iLeft-=ret;
    iSend+=ret;
    while(ret>0&&iLen)
    {
        ret=send(sockfd,(char *)pChatPDU+iSend,iLeft,0);
        iLeft-=ret;
        iSend+=ret;

    }
}


//获取信息
ChatPDU * readDataFromServer(int sockfd)
{
    int ret=0;
    unsigned int iPDULen=0;
    ret=recv(sockfd,&iPDULen,sizeof(int),0);
    if(ret==-1)
    {
        perror("recv");
        return NULL;
    }
    ChatPDU *pChatPDU=(ChatPDU *)malloc(iPDULen);
    memset(pChatPDU,0,iPDULen);
    pChatPDU->iChatPDULen=iPDULen;
    int iLeft=iPDULen-ret;
    int iRecv=ret;
    while(ret>0&&iLeft)//不能保证一次性收完,循环接收
    {
        ret=recv(sockfd,(char *)pChatPDU+iRecv,iLeft,0);
        iRecv+=ret;
        iLeft-=ret;
    }
    return pChatPDU;
}

//私聊
void chatPrivate(int sockfd)
{
    printf("请输入你想聊天的对象id:");
    int iId=0;
    char caBuf[MAXLEN]={'\0'};
    int iLen=0;
    scanf("%d",&iId);
    ChatPDU *pChatPDU=NULL;
    while(1)
    {
        scanf("%s",caBuf);
        if(strcmp(caBuf,"quit")==0)
        {
            return ;
        }
        iLen=sizeof(ChatPDU)-sizeof(int)+strlen(caBuf)+1;
        pChatPDU=makeChatPDU(iLen);
        pChatPDU->iChatPDULen=iLen;
        pChatPDU->iChatDataLen=strlen(caBuf)+1;
        pChatPDU->iFROM=g_iId;
        pChatPDU->iTO=iId;
        strcpy(pChatPDU->chatData,caBuf);
        pChatPDU->iTYPE=ENUM_TYPE_CHAT_PRICATE_GO;
        sendDataToServer(sockfd,pChatPDU);
        free(pChatPDU);
        pChatPDU=NULL;
    }

    
}
//收获私聊信息
void getChatPrivateData(ChatPDU *pChatPDU)
{
    printf("                                 %s:%s\n",pChatPDU->data.caName,pChatPDU->chatData);
    free(pChatPDU);
    pChatPDU=NULL;
    
}

//收获私聊通知
void chatPrivateSend(ChatPDU *pChatPDU)
{
    printf("你的好友不在线\n");
    free(pChatPDU);
    pChatPDU=NULL;
}

//查看所有用户
void sendToAskAllUsr(int sockfd)
{
    ChatPDU *pChatPDU=makeChatPDU(sizeof(ChatPDU));
    pChatPDU->iTYPE=ENUM_TYPE_ASK_ALL_ID_GO;
    pChatPDU->iChatPDULen=sizeof(ChatPDU);
    sendDataToServer(sockfd,pChatPDU);
    printf("所有人员:\n");
    while(g_iFlag==0);
    g_iFlag=0;
    return ;
    
}
//收获查看所有用户返回
void getAskAllUsrBack(ChatPDU *pChatPDU)
{
    
    printf("id=%d,name=%s\n",pChatPDU->data.iId,pChatPDU->data.caName);
    if(pChatPDU->data.ifOnline==0)
    {
        g_iFlag=1;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}


//查看在线用户
void sendToAskOnlineUsr(int sockfd)
{
    ChatPDU *pChatPDU=makeChatPDU(sizeof(ChatPDU));
    pChatPDU->iTYPE=ENUM_TYPE_ASK_ID_GO;
    pChatPDU->iChatPDULen=sizeof(ChatPDU);
    sendDataToServer(sockfd,pChatPDU);
    printf("在线人员:\n");
    while(g_iFlag==0);
    g_iFlag=0;
    return ;

}
//收获查看在线用户返回
void getAskOnlineUsrBack(ChatPDU *pChatPDU)
{
    if(pChatPDU->data.ifLogin==0)
    {
        printf("id=%d,name=%s\n",pChatPDU->data.iId,pChatPDU->data.caName);
    }
    else if(pChatPDU->data.ifLogin==1)
    {
        g_iFlag=1;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}


//发送修改密码
void sendChangePasswordPlease(int sockfd)
{
    int iPass1=0,iPass2=0;
    ChatPDU *pChatPDU=makeChatPDU(sizeof(ChatPDU));
    pChatPDU->iChatPDULen=sizeof(ChatPDU);
    pChatPDU->iTYPE=ENUM_TYPE_CHANGE_PASSWORD_GO;
    pChatPDU->iFROM=g_iId;
    while(1)
    {
        printf("请输入你的旧密码:");
        system("stty -echo");
        scanf("%d",&iPass1);
        system("stty echo");
        printf("\n");
        if(iPass1==g_iPass)
        {
            while(1)
            {
                printf("请输入你的新密码:");
                system("stty -echo");
                scanf("%d",&iPass1);
                system("stty echo");
                printf("\n");
                printf("请再次输入你的新密码:");
                system("stty -echo");
                scanf("%d",&iPass2);
                system("stty echo");
                printf("\n");
                if(iPass1==iPass2)
                {
                    pChatPDU->data.iPassword=iPass1;
                    sendDataToServer(sockfd,pChatPDU);
                    free(pChatPDU);
                    pChatPDU=NULL;
                    sleep(1);
                    return ;
                }
                else
                {
                    printf("两次密码输入不一致\n");
                }
            
            }
        }
        else
        {
            printf("旧密码错误,请重新输入\n");
        }
    }
}

#if 1
//写日志
void sendWriteDailyData(int sockfd)
{
    char caBuf[64]={'\0'};
    scanf("%s",caBuf);
    int iLen=sizeof(ChatPDU)-sizeof(int)+strlen(caBuf)+1;
    ChatPDU *pChatPDU=makeChatPDU(iLen);
    pChatPDU->iFROM=g_iId;
    pChatPDU->iTYPE=ENUM_TYPE_WRITE_DAILY_GO;
    strcpy(pChatPDU->chatData,caBuf);
    pChatPDU->iChatPDULen=iLen;
    sendDataToServer(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;

}
//查看某人日志
void sendReadDailyData(int sockfd)
{

    int iId;
    printf("请输入你要查看的对象id:");
    scanf("%d",&iId);
    ChatPDU *pChatPDU=makeChatPDU(sizeof(ChatPDU));
    pChatPDU->iChatPDULen=sizeof(ChatPDU);
    pChatPDU->iTYPE=ENUM_TYPE_READ_DAILY_GO;
    pChatPDU->iFROM=g_iId;
    pChatPDU->iTO=iId;
    sendDataToServer(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
    while(g_iFlag==0);
    g_iFlag=0;
    return ;
}

//收取查看某人日志返回
void getReadDaileData(ChatPDU *pChatPDU)
{
    if(strcmp(pChatPDU->chatData,"\0")==0)
    {
        printf("%s没有写日志\n",pChatPDU->data.caName);
        g_iFlag=1;
    }
    else
    {
        printf("%s:%s\n",pChatPDU->data.caName,pChatPDU->chatData);
        g_iFlag=1;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}

#endif

//创建群组
void sendSetGroup(int sockfd)
{
    printf("请输入你的群组名:");
    char caBuf[32]={'\0'};
    scanf("%s",caBuf);
    int iLen=sizeof(ChatPDU)-sizeof(int)+strlen(caBuf)+1;
    ChatPDU *pChatPDU=makeChatPDU(iLen);
    pChatPDU->iChatPDULen=iLen;
    pChatPDU->iTYPE=ENUM_TYPE_SET_GROUP_GO;
    pChatPDU->iFROM=g_iId;
    strcpy(pChatPDU->chatData,caBuf);
    sendDataToServer(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
    while(g_iFlag==0);
    g_iFlag=0;
    return ;


}

//收获创建群组返回
void getSetGroupBack(ChatPDU *pChatPDU)
{
    if(pChatPDU->data.ifLogin==0)
    {
        printf("群组名已存在,请重新创建\n");
        g_iFlag=1;
    }
    else
    {
        printf("群组创建成功\n");
        g_iFlag=1;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}
#if 1
//拉人
void pullPeopleInGroup(int sockfd)
{
    printf("请输入你要邀请对象的id:");
    int iId;
    scanf("%d",&iId);
    int iLen=sizeof(ChatPDU);
    ChatPDU *pChatPDU=makeChatPDU(iLen);
    pChatPDU->iChatPDULen=iLen;
    pChatPDU->iTYPE=ENUM_TYPE_IN_GROUP_GO;
    pChatPDU->iFROM=g_iId;
    pChatPDU->iTO=iId;
    sendDataToServer(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
    while(g_iFlag==0);
    g_iFlag=0;
    return ;
}
//收获拉人返回
void getPullPeopleInGroupBack(ChatPDU *pChatPDU)
{
    if(pChatPDU->data.ifLogin==0)
    {
        printf("邀请失败:该用户不存在\n");
        g_iFlag=1;
    }
    else if(pChatPDU->data.ifLogin==1)
    {
        printf("邀请失败:该用户已经是群成员了\n");
        g_iFlag=1;
    }
    else 
    {
        printf("邀请成功\n");
        g_iFlag=1;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}

//邀请通知
void getPullPeopleInGroupSend(ChatPDU *pChatPDU)
{
    printf("你已被邀请入群---%s\n",pChatPDU->caFileName);
    free(pChatPDU);
    pChatPDU=NULL;
}
#endif


//群聊
void chatGroup(int sockfd)
{
    char caBuf[MAXLEN]={'\0'};
    int iLen=0;
    ChatPDU *pChatPDU=NULL;
    while(1)
    {
        scanf("%s",caBuf);
        if(strcmp(caBuf,"quit")==0)
        {
            return ;
        }
        iLen=sizeof(ChatPDU)-sizeof(int)+strlen(caBuf)+1;
        pChatPDU=makeChatPDU(iLen);
        pChatPDU->iChatPDULen=iLen;
        pChatPDU->iChatDataLen=strlen(caBuf)+1;
        pChatPDU->iFROM=g_iId;
        pChatPDU->iTO=SERVER;
        strcpy(pChatPDU->chatData,caBuf);
        pChatPDU->iTYPE=ENUM_TYPE_CHAT_GROUP_GO;
        sendDataToServer(sockfd,pChatPDU);
        free(pChatPDU);
        pChatPDU=NULL;
    }

    
}
//收获群聊信息
void getChatGroupData(ChatPDU *pChatPDU)
{
    printf("                                 %s:%s\n",pChatPDU->data.caName,pChatPDU->chatData);
    free(pChatPDU);
    pChatPDU=NULL;
    
}


//查看群成员
void sendToAskGroupUsr(int sockfd)
{
    ChatPDU *pChatPDU=makeChatPDU(sizeof(ChatPDU));
    pChatPDU->iTYPE=ENUM_TYPE_ASK_GROUP_ID_GO;
    pChatPDU->iChatPDULen=sizeof(ChatPDU);
    pChatPDU->iFROM=g_iId;
    sendDataToServer(sockfd,pChatPDU);
    printf("群成员:\n");
    while(g_iFlag==0);
    g_iFlag=0;
    return ;
    
}
//收获查看群成员返回
void getAskGroupUsrBack(ChatPDU *pChatPDU)
{
    if(pChatPDU->data.ifLogin==0)
    {
        printf("id=%d,name=%s\n",pChatPDU->data.iId,pChatPDU->data.caName);
    }
    else if(pChatPDU->data.ifLogin==1)
    {
        g_iFlag=1;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}


//设置管理员
void setAdministrator(int sockfd)
{
    printf("请输入你要设置对象的id:");
    int iId;
    scanf("%d",&iId);
    int iLen=sizeof(ChatPDU);
    ChatPDU *pChatPDU=makeChatPDU(iLen);
    pChatPDU->iChatPDULen=iLen;
    pChatPDU->iTYPE=ENUM_TYPE_SET_ADMINISTRATOR_GO;
    pChatPDU->iFROM=g_iId;
    pChatPDU->iTO=iId;
    sendDataToServer(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
    while(g_iFlag==0);
    g_iFlag=0;
    return ;
}
//收获设置管理员返回
void getSetAdministratorBack(ChatPDU *pChatPDU)
{
    if(pChatPDU->data.ifLogin==0)
    {
        printf("设置失败,该用户不存在或非群成员\n");
        g_iFlag=1;
    }
    else if(pChatPDU->data.ifLogin==1)
    {
        printf("设置失败,该用户已经是群主或管理员了\n");
        g_iFlag=1;
    }
    else if(pChatPDU->data.ifLogin==3)
    {
        printf("设置失败,权限不足\n");
        g_iFlag=1;
    }
    else 
    {
        printf("设置成功\n");
        g_iFlag=1;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}


///////上传文件//////
void sendDataToServerFromFile(int sockfd)
{
    printf("请输入你要上传的文件名:");
    char caFileName[64]={'\0'};
    scanf("%s",caFileName);
    int fd=open(caFileName,O_RDONLY);
    if(fd==-1)
    {
        perror("open");
        return ;
    }
    int iLen=lseek(fd,0,SEEK_END);
    lseek(fd,0,SEEK_SET);
    int iLeft=iLen;
    char caBuf[MAXLEN]={'\0'};
    int ret=read(fd,caBuf,iLeft);
    int iRead=ret;
    while(ret>0 && iLeft)
    {
        ret=read(fd,caBuf,iLeft);
        iLeft-=ret;
        iRead+=ret;     
    }
    int iLenAll=sizeof(ChatPDU)-sizeof(int)+iLen;
    ChatPDU *pChatPDU=makeChatPDU(iLenAll);
    pChatPDU->iTYPE=ENUM_TYPE_UP_FILE;
    pChatPDU->iFROM=g_iId;
    pChatPDU->iTO=SERVER;
    strcpy(pChatPDU->caFileName,caFileName);
    pChatPDU->iChatDataLen=iLen;
    pChatPDU->iChatPDULen=sizeof(ChatPDU)-sizeof(int)+iLen;
    strcpy(pChatPDU->chatData,caBuf);
    sendDataToServer(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
    printf("上传成功\n");
    
}


//请求查看服务器文件链表
void sendAskFileNameFromServer(int sockfd)
{
    
    ChatPDU *pChatPDU=makeChatPDU(sizeof(ChatPDU));
    pChatPDU->iChatPDULen=sizeof(ChatPDU);
    pChatPDU->iTYPE=ENUM_TYPE_ASK_FILE_GO;
    pChatPDU->iTO=SERVER;
    pChatPDU->iFROM=g_iId;
    sendDataToServer(sockfd,pChatPDU);
    while(g_iFlag==0);
    g_iFlag=0;
    return ;
}

//收获查看文件链表返回
void getAskFileName(ChatPDU *pChatPDU)
{
    if(strcmp(pChatPDU->data.caName,"\0")==0)
    {
        printf("暂无文件\n");
        g_iFlag=1;
    }
    else
    {
        printf("%s\n",pChatPDU->data.caName);
        if(pChatPDU->data.ifLogin==1)
        {
            g_iFlag=1;
        }
    }

}


//从服务器读取文件
void readFileFromServer(ChatPDU *pChatPDU)
{
    char caFileName[128]="./test/";
    strcat(caFileName,pChatPDU->caFileName);
    FILE *fd=fopen(caFileName,"w");
    if(fd==NULL)
    {
        perror("fopen");
        return ;
    }
    fprintf(fd,"%s",pChatPDU->chatData);
    fclose(fd);
    printf("下载成功\n");
    g_iFlag=1;
    free(pChatPDU);
    pChatPDU=NULL;
}


//发送下载请求
void sendPleaseToDownFileFromServer(int sockfd)
{
    printf("请输入要下载的文件名:");
    char caBuf[64]={'\0'};
    scanf("%s",caBuf);
    ChatPDU *pChatPDU=makeChatPDU(sizeof(ChatPDU));
    pChatPDU->iChatPDULen=sizeof(ChatPDU);
    pChatPDU->iTYPE=ENUM_TYPE_DOWN_FILE_GO;
    pChatPDU->iTO=SERVER;
    pChatPDU->iFROM=g_iId;
    strcpy(pChatPDU->caFileName,caBuf);
    sendDataToServer(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
    while(g_iFlag==0);
    g_iFlag=0;
    return ;


}


//禁言
void sendBannedToPost(int sockfd)
{
    ChatPDU *pChatPDU=makeChatPDU(sizeof(ChatPDU));
    pChatPDU->iChatPDULen=sizeof(ChatPDU);
    pChatPDU->iTYPE=ENUM_TYPE_BANNED_TO_POST_GO;
    pChatPDU->iFROM=g_iId;
    printf("1.全禁言  2.禁言个人\n");
    int select;
    scanf("%d",&select);
    if(select==1)
    {
        sendDataToServer(sockfd,pChatPDU);      
    }
    else
    {
        printf("请选择禁言对象的id:");
        int iId;
        scanf("%d",&iId);
        pChatPDU->iTO=iId;
        sendDataToServer(sockfd,pChatPDU);      
    }
    free(pChatPDU);
    pChatPDU=NULL;
    while(g_iFlag==0);
    g_iFlag=0;
    return ;
}

//禁言返回
void getBannedToPostBack(ChatPDU *pChatPDU)
{
    switch(pChatPDU->data.ifLogin)
    {
        case 0:
            printf("禁言失败:你未加入群组\n");
            break;
        case 1:
            printf("禁言失败:权限不足\n");
            break;
        case 2:
            printf("禁言成功\n");
            break;
        case 3:
            printf("禁言失败:该用户不存在\n");
            break;
        case 4:
            printf("禁言失败:该用户已经被禁言\n");
            break;
        case 5:
            printf("禁言成功\n");
            break;
    }
    g_iFlag=1;
    free(pChatPDU);
    pChatPDU=NULL;
}
//被禁言提醒
void getBannedToPostSend(ChatPDU *pChatPDU)
{
    if(pChatPDU->data.ifLogin==2)
    {
        printf("管理员已设置全员禁言\n");
    }
    else if(pChatPDU->data.ifLogin==5)
    {
        printf("你已被管理员禁言\n");
    }
    else if(pChatPDU->data.ifLogin==3)
    {
        printf("禁言中。。。\n");
    }
    else if(pChatPDU->data.ifLogin==4)
    {
        printf("未加入群组\n");
    }
    free(pChatPDU);
    pChatPDU=NULL;
}


//解禁言
void sendLiftBanned(int sockfd)
{
    ChatPDU *pChatPDU=makeChatPDU(sizeof(ChatPDU));
    pChatPDU->iChatPDULen=sizeof(ChatPDU);
    pChatPDU->iTYPE=ENUM_TYPE_LIFT_BAN_GO;
    pChatPDU->iFROM=g_iId;
    printf("1.全解禁言  2.解禁个人\n");
    int select;
    scanf("%d",&select);
    if(select==1)
    {
        sendDataToServer(sockfd,pChatPDU);      
    }
    else
    {
        printf("请选择解禁言对象的id:");
        int iId;
        scanf("%d",&iId);
        pChatPDU->iTO=iId;
        sendDataToServer(sockfd,pChatPDU);      
    }
    free(pChatPDU);
    pChatPDU=NULL;
    while(g_iFlag==0);
    g_iFlag=0;
    return ;
}


//解禁言返回
void getLiftBannedBack(ChatPDU *pChatPDU)
{
    switch(pChatPDU->data.ifLogin)
    {
        case 0:
            printf("解禁言失败:你未加入群组\n");
            break;
        case 1:
            printf("解禁言失败:权限不足\n");
            break;
        case 2:
            printf("解禁言成功\n");
            break;
        case 3:
            printf("解禁言失败:该用户不存在\n");
            break;
        case 4:
            printf("解禁言失败:该用户未被禁言\n");
            break;
        case 5:
            printf("解禁言成功\n");
            break;
    }
    g_iFlag=1;
    free(pChatPDU);
    pChatPDU=NULL;
}

//被禁言提醒
void getLiftBannedSend(ChatPDU *pChatPDU)
{
    if(pChatPDU->data.ifLogin==2)
    {
        printf("管理员已设置全员解禁言\n");
    }
    else if(pChatPDU->data.ifLogin==5)
    {
        printf("你已被管理员解禁言\n");
    }
    free(pChatPDU);
    pChatPDU=NULL;
}

//踢人
void pullPeopleOutGroup(int sockfd)
{
    printf("请输入你要踢出对象的id:");
    int iId;
    scanf("%d",&iId);
    int iLen=sizeof(ChatPDU);
    ChatPDU *pChatPDU=makeChatPDU(iLen);
    pChatPDU->iChatPDULen=iLen;
    pChatPDU->iTYPE=ENUM_TYPE_OUT_GROUP_GO;
    pChatPDU->iFROM=g_iId;
    pChatPDU->iTO=iId;
    sendDataToServer(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
    while(g_iFlag==0);
    g_iFlag=0;
    return ;
}
//收获踢出返回
void getPullPeopleOutGroupBack(ChatPDU *pChatPDU)
{
    if(pChatPDU->data.ifLogin==0)
    {
        printf("提出失败:该用户不存在\n");
        g_iFlag=1;
    }
    else if(pChatPDU->data.ifLogin==1)
    {
        printf("踢出失败:该用户不是群成员了\n");
        g_iFlag=1;
    }
    else 
    {
        printf("踢出成功\n");
        g_iFlag=1;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}
//踢出通知
void getPullPeopleOutGroupSend(ChatPDU *pChatPDU)
{
    printf("你已被管理员踢出群---%s\n",pChatPDU->caFileName);
    free(pChatPDU);
    pChatPDU=NULL;
}

//退出登录
void quitEnter(int sockfd)
{
    ChatPDU *pChatPDU=makeChatPDU(sizeof(ChatPDU));
    pChatPDU->iChatPDULen=sizeof(ChatPDU);
    pChatPDU->iTYPE=ENUM_TYPE_QUIT_ENTER_GO;
    pChatPDU->iFROM=g_iId;
    sendDataToServer(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
    return;

}
//退出登录通知
void quitEnterSend(ChatPDU *pChatPDU)
{
    printf("你的好友%s已下线\n",pChatPDU->data.caName);
    free(pChatPDU);
    pChatPDU=NULL;
}

//群聊界面
void chatGroupFace(int sockfd)
{
    while(1)
    {
        printf("01.创建群组\n");
        printf("02.拉人\n");
        printf("03.群聊\n");
        printf("04.查看群成员\n");
        printf("05.设置管理员\n");
        printf("06.上传群文件\n");
        printf("07.查看群文件\n");
        printf("08.下载群文件\n");
        printf("09.禁言\n");
        printf("10.解禁言\n");
        printf("11.踢人\n");
        printf("12.返回\n");
        int select;
        scanf("%d",&select);
        switch(select)
        {
            case 1:
                sendSetGroup(sockfd);
                break;
            case 2:
                pullPeopleInGroup(sockfd);
                break;
            case 3:
                chatGroup(sockfd);
                break;
            case 4:
                sendToAskGroupUsr(sockfd);
                break;
            case 5:
                setAdministrator(sockfd);
                break;
            case 6:
                sendDataToServerFromFile(sockfd);
                break;
            case 7:
                sendAskFileNameFromServer(sockfd);
                break;
            case 8:
                sendPleaseToDownFileFromServer(sockfd);
                break;
            case 9:
                sendBannedToPost(sockfd);
                break;
            case 10:
                sendLiftBanned(sockfd);
                break;
            case 11:
                pullPeopleOutGroup(sockfd);
                break;
            case 12:
                return ;
                break;
            default:
                printf("输入有误\n");
                break;
        }
    }

}

//用户界面
void clientFace(int sockfd)
{
    while(1)
    {
        printf("01.查看所有用户\n");
        printf("02.查看在线用户\n");
        printf("03.私聊\n");
        printf("04.群聊\n");
        printf("05.修改密码\n");
        printf("06.写日志\n");
        printf("07.查看某人日志\n");
        printf("08.退出登录\n");
        int select;
        scanf("%d",&select);
        switch(select)
        {
            case 1:
                sendToAskAllUsr(sockfd);
                break;
            case 2:
                sendToAskOnlineUsr(sockfd);
                break;
            case 3:
                chatPrivate(sockfd);
                break;
            case 4:
                chatGroupFace(sockfd);
                break;
            case 5:
                sendChangePasswordPlease(sockfd);
                return ;
                break;
            case 6:
                sendWriteDailyData(sockfd);
                break;
            case 7:
                sendReadDailyData(sockfd);
                break;
            case 8:
                quitEnter(sockfd);
                return; 
                break;
            default:
                printf("输入有误\n");
                break;
        }
    }
}

//发送登录请求
void sendEnterPleaseToServer(int sockfd)
{
    printf("请输入账号Id:");
    int iId=0;
    scanf("%d",&iId);
    printf("请输入密码password:");
    int iPass=0;
    system("stty -echo");
    scanf("%d",&iPass);
    system("stty echo");
    printf("\n");
    int iLen=sizeof(ChatPDU);
    ChatPDU *pChatPDU=makeChatPDU(iLen);
    pChatPDU->iChatPDULen=iLen;
    pChatPDU->iTYPE=ENUM_TYPE_ENTER_GO;
    pChatPDU->iFROM=iId;
    pChatPDU->iTO=SERVER;
    pChatPDU->data.iId=iId;
    pChatPDU->data.iPassword=iPass;
    sendDataToServer(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
    while(g_ifOnline==2);
    if(g_ifOnline==0)
    {
        printf("登录失败\n");
        g_ifOnline=2;
        return ;
    }
    else if(g_ifOnline==1)
    {
        printf("登陆成功\n");
        g_iId=iId;
        g_ifOnline=2;

        clientFace(sockfd);
        return ;
    }
}


//收获登录返回
void getEnterBack(ChatPDU *pChatPDU)
{
    if(pChatPDU->data.ifOnline==1)
    {
        g_iPass=pChatPDU->data.iPassword;
        g_ifOnline=1;
    }
    else if(pChatPDU->data.ifOnline==0)
    {
        g_ifOnline=0;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}

//好友登录通知
void getEnterSend(ChatPDU *pChatPDU)
{
    printf("你的好友 %s 已上线\n",pChatPDU->data.caName);
    free(pChatPDU);
    pChatPDU=NULL;
}


//发送注册请求
void sendLoginPleaseToServer(int sockfd)
{

    Data data;
    int iLen=sizeof(ChatPDU);
    ChatPDU *pChatPDU=makeChatPDU(iLen);
    while(1)
    {
        memset(pChatPDU,0,iLen);
        data=initData(data);
        data=inputData(data);
        pChatPDU->iChatPDULen=iLen;
        pChatPDU->data=data;
        pChatPDU->iTYPE=ENUM_TYPE_LOGIN_GO;
        pChatPDU->iTO=SERVER;
        pChatPDU->iFROM=data.iId;
        printf("iId=%d\n",pChatPDU->data.iId);
        sendDataToServer(sockfd,pChatPDU);
        while(1)
        {
            while(g_iFlag==0);
            g_iFlag=0;
            printf("是否继续注册?\n");
            printf("1.是            2.否\n");
            int select;
            scanf("%d",&select);
            if(select==1)
            {
                break;
            }
            else if(select==2)
            {
                free(pChatPDU);
                pChatPDU=NULL;
                return ;
            }
            else
            {
                printf("输入有误\n");
            }

        }
    }

}
//收获注册返回
void getLoginBack(ChatPDU *pChatPDU)
{
    if(pChatPDU->data.ifLogin==0)
    {
        printf("账号已存在,请重新注册\n");
        g_iFlag=1;
    }
    else
    {
        printf("账号注册成功\n");
        g_iFlag=1;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}





void* readData(void *arg)
{
    int sockfd =* (int*)arg;
    int iMsgType=0;
    ChatPDU *pChatPDU=NULL;
    while (1)
    {
        pChatPDU=readDataFromServer(sockfd);
        if(pChatPDU!=NULL)
        {
        /*解析PDU*/
            iMsgType=parsePDU(pChatPDU);
            switch(iMsgType)
            {
                case ENUM_TYPE_LOGIN_BACK:
                    getLoginBack(pChatPDU);
                    break;
                case ENUM_TYPE_ENTER_BACK:
                    getEnterBack(pChatPDU);
                    break;
                case ENUM_TYPE_ENTER_SEND:
                    getEnterSend(pChatPDU);
                    break;
                case ENUM_TYPE_ASK_ID_BACK:
                    getAskOnlineUsrBack(pChatPDU);
                    break;
                case ENUM_TYPE_CHAT_PRICATE_BACK:
                    getChatPrivateData(pChatPDU);
                    break;
                case ENUM_TYPE_CHAT_PRICATE_SEND:
                    chatPrivateSend(pChatPDU);
                    break;
                case ENUM_TYPE_READ_DAILY_BACK:
                    getReadDaileData(pChatPDU);
                    break;
                case ENUM_TYPE_ASK_ALL_ID_BACK:
                    getAskAllUsrBack(pChatPDU);
                    break;
                case ENUM_TYPE_SET_GROUP_BACK:
                    getSetGroupBack(pChatPDU);
                    break;
                case ENUM_TYPE_IN_GROUP_BACK:
                    getPullPeopleInGroupBack(pChatPDU);
                    break;
                case ENUM_TYPE_IN_GROUP_SEND:
                    getPullPeopleInGroupSend(pChatPDU);
                    break;
                case ENUM_TYPE_CHAT_GROUP_BACK:
                    getChatGroupData(pChatPDU);
                    break;
                case ENUM_TYPE_ASK_GROUP_ID_BACK:
                    getAskGroupUsrBack(pChatPDU);
                    break;
                case ENUM_TYPE_SET_ADMINISTRATOR_BACK:
                    getSetAdministratorBack(pChatPDU);
                    break;
                case ENUM_TYPE_ASK_FILE_BACK:
                    getAskFileName(pChatPDU);
                    break;
                case ENUM_TYPE_DOWN_FILE_BACK:
                    readFileFromServer(pChatPDU);
                    break;
                case ENUM_TYPE_BANNED_TO_POST_BACK:
                    getBannedToPostBack(pChatPDU);
                    break;
                case ENUM_TYPE_BANNED_TO_POST_SEND:
                    getBannedToPostSend(pChatPDU);
                    break;
                case ENUM_TYPE_LIFT_BAN_BACK:
                    getLiftBannedBack(pChatPDU);
                    break;
                case ENUM_TYPE_LIFT_BAN_SEND:
                    getLiftBannedSend(pChatPDU);
                    break;
                case ENUM_TYPE_OUT_GROUP_BACK:
                    getPullPeopleOutGroupBack(pChatPDU);
                    break;
                case ENUM_TYPE_OUT_GROUP_SEND:
                    getPullPeopleOutGroupSend(pChatPDU);
                    break;
                case ENUM_TYPE_QUIT_ENTER_SEND:
                    quitEnterSend(pChatPDU);
                    break;
                default:
                    break;

            }
        }

    }
}



void menu(int socketfd)
{
    while(1)
    {
        system("clear");
        printf("01.注册\n");
        printf("02.登录\n");
        printf("03.退出\n");
        int select;
        scanf("%d",&select);
        switch(select)
        {
            case 1:
                sendLoginPleaseToServer(socketfd);
                break;
            case 2:
                sendEnterPleaseToServer(socketfd);
                break;
            case 3:
                return ;
                //exit(1);
                break;
            default:
                printf("输入有误\n");
                break;
        }
    }
    return ;
}

void handle(int sig)
{
    if(sig==SIGINT)
    {
        quitEnter(g_iSockfd);
        exit(1);
    }
}

int main(int argc,char **argv)
{
    signal(SIGINT,handle);
    g_pHead=makeList();
    int socketfd = 0;
    //AF_INET: ipv4
    //SOCK_STREAM: tcp/ip
    socketfd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == socketfd)
    {
        perror("socket");
        return -1;
    }
    g_iSockfd=socketfd;
    struct sockaddr_in servaddr;
    //地址协议:ipv4
    servaddr.sin_family = AF_INET;
    //服务器端口
    servaddr.sin_port = htons(atoi(argv[2]));
    //服务器ip
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);
    bzero(&(servaddr.sin_zero), 8);
    int ret = connect(socketfd
                , (struct sockaddr *)&servaddr
                , sizeof(struct sockaddr));
    if (-1 == ret)
    {
        perror("connect");
        return -1;
    }
    
    printf("connect ok...\n");
    pthread_t pt;

    ret = pthread_create(&pt, NULL, readData
                         , (void *)&socketfd);
    if (0 != ret)
    {
        perror("pthread_create");
        return -1;
    }
    menu(socketfd);
    return 0;
}

2.server

#include <stdio.h>
#include <errno.h>
#include <string.h>
/*socket()  send()*/
#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <unistd.h>  //fork()

/*wait()*/
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>  //signal()

#include <pthread.h>  //thread
#include "../link/node.h"
#include "../protocol/protocol.h"
#include "../fileLink/fileNode.h"
#include <stdlib.h>

#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MAXLEN 1024        
Head *pHead=NULL;
fileHead *fHead=NULL;

void sendDataToClient(int sockClient,ChatPDU *pChatPDU)
{
    if(pChatPDU==NULL)
    {
        return ;
    }
    int ret=0;
    int iLen=pChatPDU->iChatPDULen;
    int iLeft=iLen;
    int iSend=0;

    ret=send(sockClient,pChatPDU,iLen,0);
    iLeft-=ret;
    iSend+=ret;
    while(ret>0&&iLeft)
    {
        ret=send(sockClient,(char *)pChatPDU+iSend,iLeft,0);
        iLeft-=ret;
        iSend+=ret;

    }

}


ChatPDU * readDataFromClient(int sockfd)
{
    int ret=0;
    unsigned int iPDULen=0;
    ret=recv(sockfd,&iPDULen,sizeof(int),0);
    if(ret==-1)
    {
        perror("recv");
        return NULL;
    }
    else if(ret == 0)
        return NULL;
    ChatPDU *pChatPDU=(ChatPDU *)malloc(iPDULen);
    memset(pChatPDU,0,iPDULen);
    pChatPDU->iChatPDULen=iPDULen;
    int iLeft=iPDULen-ret;
    int iRecv=ret;
    while(ret>0&&iLeft)//不能保证一次性收完,循环接收
    {
        ret=recv(sockfd,(char *)pChatPDU+iRecv,iLeft,0);
        iRecv+=ret;
        iLeft-=ret;
    }
    return pChatPDU;
}


//保存文件链表到文件
void saveFileNameToFile()
{
    int fd=open("file.dat",O_WRONLY);
    fileNode *fNode=NULL;
    fNode=fHead->pFirstNode;
    while(fNode!=NULL)
    {
        write(fd,fNode,sizeof(fileNode));
        fNode=fNode->pNext;
    }
    close(fd);
    
}
//读取文件链表文件
void readFileNameFromFile()
{
    int fd=open("file.dat",O_RDONLY);
    fileNode *fNode=NULL;
    int ret=0;
    while(1)
    {
        fNode=makeFileNode();
        ret=read(fd,fNode,sizeof(fileNode));
        if(ret==0)
        {
            break;
        }
        insertFileList(fHead,fNode);            
    }
    close(fd);
}


//保存到文件
void saveToFile()
{
    int fd=open("test.dat",O_WRONLY);
    Node *pNode=NULL;
    pNode=pHead->pFirstNode;
    while(pNode!=NULL)
    {
        write(fd,pNode,sizeof(Node));
        pNode=pNode->pNext;
    }
    close(fd);
    
}
//读取文件
void readFromFile()
{
    int fd=open("test.dat",O_RDONLY);
    Node *pNode=NULL;
    int ret=0;
    while(1)
    {
        pNode=makeNode();
        ret=read(fd,pNode,sizeof(Node));
        if(ret==0)
        {
            break;
        }
        insertList(pHead,pNode);            
    }
    close(fd);
}
//好友登录通知
void EnterSend(int iId)
{
    Node *pNode1=findNode(pHead,iId);
    ChatPDU *pChatPDU=makeChatPDU(sizeof(ChatPDU));
    pChatPDU->iChatPDULen=sizeof(ChatPDU);
    pChatPDU->iTYPE=ENUM_TYPE_ENTER_SEND;
    Node *pNode=pHead->pFirstNode;
    while(pNode!=NULL)
    {
        if(pNode->data.ifOnline==1&&pNode->data.iId!=iId)
        {
            printf("pNode->data.iId:%d---iId:%d\n",pNode->data.iId,iId);
            strcpy(pChatPDU->data.caName,pNode1->data.caName);
            sendDataToClient(pNode->sockfd,pChatPDU);
        }
        pNode=pNode->pNext;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}

//登录
void getEnterPleaseFromClient(int sockfd,ChatPDU *pChatPDU)
{
    Node *pNode=NULL;
    pNode=findNode(pHead,pChatPDU->data.iId);
    pChatPDU->iTYPE=ENUM_TYPE_ENTER_BACK;
    if(pNode!=NULL)
    {
        if(pNode->data.iPassword==pChatPDU->data.iPassword)
        {
            pNode->sockfd=sockfd;
            pNode->data.ifOnline=1;
            pChatPDU->data.iPassword=pNode->data.iPassword;
            pChatPDU->data.ifOnline=1;
            sendDataToClient(sockfd,pChatPDU);
            EnterSend(pNode->data.iId);
        }
        else
        {
            sendDataToClient(sockfd,pChatPDU);
        }
    }
    else
    {
        sendDataToClient(sockfd,pChatPDU);
    }
    free(pChatPDU);
    pChatPDU=NULL;

}






//注册接收
void getLoginpleaseFromClient(int sockfd,ChatPDU *pChatPDU)
{
    Node *pNode=NULL;
    pNode=findNode(pHead,pChatPDU->data.iId);
    pChatPDU->iTYPE=ENUM_TYPE_LOGIN_BACK;
    if(pNode==NULL)
    {
        pNode=makeNode();
        initNode(pNode,pChatPDU->data);
        insertList(pHead,pNode);
        pChatPDU->data.ifLogin=1;

        saveToFile();
    }
    sendDataToClient(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
}

//收到查看所有人员请求
void getAskToAllUsr(int sockfd)
{
    ChatPDU *pChatPDU=NULL;
    pChatPDU=makeChatPDU(sizeof(ChatPDU));
    Node *pNode=NULL;
    pNode=pHead->pFirstNode;
    while(pNode!=NULL)
    {
        memset(pChatPDU,0,sizeof(ChatPDU));
        pChatPDU->data=pNode->data;
        pChatPDU->iTYPE=ENUM_TYPE_ASK_ALL_ID_BACK;
        pChatPDU->iChatPDULen=sizeof(ChatPDU);
        if(pNode->pNext==NULL)
        {
            pChatPDU->data.ifOnline=0;
        }
        sendDataToClient(sockfd,pChatPDU);
        pNode=pNode->pNext;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}

//收到查看在线人员请求
void getAskToOnlineUsr(int sockfd)
{
    ChatPDU *pChatPDU=NULL;
    pChatPDU=makeChatPDU(sizeof(ChatPDU));
    //memset(pChatPDU,0,sizeof(ChatPDU));
    Node *pNode=NULL;
    pNode=pHead->pFirstNode;
    pChatPDU->iTYPE=ENUM_TYPE_ASK_ID_BACK;
    pChatPDU->iChatPDULen=sizeof(ChatPDU);
    while(pNode!=NULL)
    {
        if(pNode->data.ifOnline==1)
        {
            pChatPDU->data=pNode->data;
            pChatPDU->data.ifLogin=0;
            sendDataToClient(sockfd,pChatPDU);
        }
        pNode=pNode->pNext;
    }
    pChatPDU->data.ifLogin=1;
    sendDataToClient(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
}

//私聊
void chatPrivateToClient(int sockfd,ChatPDU *pChatPDU)
{
    Node *pNode=findNode(pHead,pChatPDU->iFROM);
    strcpy(pChatPDU->data.caName,pNode->data.caName);
    pChatPDU->iTYPE=ENUM_TYPE_CHAT_PRICATE_BACK;
    pNode=findNode(pHead,pChatPDU->iTO);
    if(pNode->data.ifOnline==0)
    {
        pChatPDU->iTYPE=ENUM_TYPE_CHAT_PRICATE_SEND;
        sendDataToClient(sockfd,pChatPDU);
        free(pChatPDU);
        pChatPDU=NULL;
        return;
    }
    sendDataToClient(pNode->sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
}


//修改密码
void changePassword(ChatPDU *pChatPDU)
{
    Node *pNode=NULL;
    pNode=findNode(pHead,pChatPDU->iFROM);
    pNode->data.iPassword=pChatPDU->data.iPassword;
    saveToFile();
    free(pChatPDU);
    pChatPDU=NULL;
}

#if 1
//写日志
void writeDaily(ChatPDU *pChatPDU)
{
    Node *pNode=NULL;
    pNode=findNode(pHead,pChatPDU->iFROM);
    strcpy(pNode->caDaily,pChatPDU->chatData);
    saveToFile();
    free(pChatPDU);
    pChatPDU=NULL;
}
//查看某人日志
void readDaily(int sockfd,ChatPDU *pChatPDU)
{
    Node *pNode=NULL;
    pNode=findNode(pHead,pChatPDU->iTO);
    free(pChatPDU);
    pChatPDU=NULL;
    int iLen=sizeof(ChatPDU)-sizeof(int)+strlen(pNode->caDaily)+1;
    pChatPDU=makeChatPDU(iLen);
    pChatPDU->iChatPDULen=iLen;
    strcpy(pChatPDU->chatData,pNode->caDaily);
    strcpy(pChatPDU->data.caName,pNode->data.caName);
    pChatPDU->iTYPE=ENUM_TYPE_READ_DAILY_BACK;
    sendDataToClient(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
    
}
#endif
//创建群组
void setChatGroup(int sockfd,ChatPDU *pChatPDU)
{
    Node *pNode=NULL;
    pNode=pHead->pFirstNode;
    pChatPDU->iTYPE=ENUM_TYPE_SET_GROUP_BACK;
    while(pNode!=NULL)
    {
        if(strcmp(pNode->caGroupName,pChatPDU->chatData)==0)
        {           
            sendDataToClient(sockfd,pChatPDU);
            free(pChatPDU);
            pChatPDU=NULL;
            return;
        }
        pNode=pNode->pNext;
    }
    pNode=findNode(pHead,pChatPDU->iFROM);
    strcpy(pNode->caGroupName,pChatPDU->chatData);
    pNode->iStatus=GROUP_GANAPATI;  
    saveToFile();
    pChatPDU->data.ifLogin=1;
    sendDataToClient(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
}
#if 1
//拉人
void pullPeopleInGroup(int sockfd,ChatPDU *pChatPDU)
{
    Node *pNode=findNode(pHead,pChatPDU->iFROM);
    Node *pNode1=findNode(pHead,pChatPDU->iTO); 
    pChatPDU->iTYPE=ENUM_TYPE_IN_GROUP_BACK;
    if(pNode1==NULL)
    {
        sendDataToClient(sockfd,pChatPDU);
        free(pChatPDU);
        pChatPDU=NULL;
        return ;
    }
    else
    {
        if(strcmp(pNode1->caGroupName,pNode->caGroupName)==0)
        {
            pChatPDU->data.ifLogin=1;
            sendDataToClient(sockfd,pChatPDU);
            free(pChatPDU);
            pChatPDU=NULL;
            return ;    
        }
        strcpy(pNode1->caGroupName,pNode->caGroupName);
        saveToFile();
        pChatPDU->data.ifLogin=2;
        sendDataToClient(sockfd,pChatPDU);
        pChatPDU->iTYPE=ENUM_TYPE_IN_GROUP_SEND;
        strcpy(pChatPDU->caFileName,pNode->caGroupName);
        sendDataToClient(pNode1->sockfd,pChatPDU);
        free(pChatPDU);
        pChatPDU=NULL;
        return ;
    }
}
#endif

//群聊
void chatGroupToClient(int sockfd,ChatPDU *pChatPDU)
{

    int sockfd1=0;
    Node *pNode1=findNode(pHead,pChatPDU->iFROM);
    if(pNode1->iIfBanned==1)//禁言
    {
        pChatPDU->data.ifLogin=3;
        pChatPDU->iTYPE=ENUM_TYPE_BANNED_TO_POST_SEND;
        sendDataToClient(sockfd,pChatPDU);
        free(pChatPDU);
        pChatPDU=NULL;
        return ;
    }
    else if(strcmp(pNode1->caGroupName,"\0")==0)//未加入群组
    {
        pChatPDU->data.ifLogin=4;
        pChatPDU->iTYPE=ENUM_TYPE_BANNED_TO_POST_SEND;
        sendDataToClient(sockfd,pChatPDU);
        free(pChatPDU);
        pChatPDU=NULL;
        return ;    
    }
    Node *pNode=pHead->pFirstNode;
    pChatPDU->iTYPE=ENUM_TYPE_CHAT_PRICATE_BACK;
    while(pNode!=NULL)
    {
        if(pNode->data.ifOnline==1 && strcmp(pNode->caGroupName,pNode1->caGroupName)==0 && pNode->data.iId!=pNode1->data.iId)
        {
            sockfd1=pNode->sockfd;
            strcpy(pChatPDU->data.caName,pNode1->data.caName);
            sendDataToClient(sockfd1,pChatPDU);
        }
        pNode=pNode->pNext;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}


//收到查看群成员请求
void getAskToGroupUsr(int sockfd,ChatPDU *pChatPDU)
{
    Node *pNode1=findNode(pHead,pChatPDU->iFROM);
    free(pChatPDU);
    pChatPDU=NULL;
    pChatPDU=makeChatPDU(sizeof(ChatPDU));
    pChatPDU->iTYPE=ENUM_TYPE_ASK_GROUP_ID_BACK;
    pChatPDU->iChatPDULen=sizeof(ChatPDU);
    Node *pNode=NULL;
    pNode=pHead->pFirstNode;
    while(pNode!=NULL)
    {
        if(strcmp(pNode->caGroupName,pNode1->caGroupName)==0)
        {
            pChatPDU->data=pNode->data;
            pChatPDU->data.ifLogin=0;
            sendDataToClient(sockfd,pChatPDU);
        }
        pNode=pNode->pNext;
    }
    pChatPDU->data.ifLogin=1;
    sendDataToClient(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
}


//设置管理员
void setAdministrtor(int sockfd,ChatPDU *pChatPDU)
{
    Node *pNode=findNode(pHead,pChatPDU->iFROM);
    Node *pNode1=findNode(pHead,pChatPDU->iTO); 
    pChatPDU->iTYPE=ENUM_TYPE_SET_ADMINISTRATOR_BACK;
    if(pNode->iStatus!=GROUP_GANAPATI&&pNode->iStatus!=GROUP_ADMINISTRATOR)
    {
        pChatPDU->data.ifLogin=3;
        sendDataToClient(sockfd,pChatPDU);
        free(pChatPDU);
        pChatPDU=NULL;
        return ;
        
    }
    if(pNode1==NULL||strcmp(pNode1->caGroupName,pNode->caGroupName)!=0)
    {
        sendDataToClient(sockfd,pChatPDU);
        free(pChatPDU);
        pChatPDU=NULL;
        return ;
    }
    else
    {
        if(pNode1->iStatus==GROUP_ADMINISTRATOR||pNode1->iStatus==GROUP_GANAPATI)
        {
            pChatPDU->data.ifLogin=1;
            sendDataToClient(sockfd,pChatPDU);
            free(pChatPDU);
            pChatPDU=NULL;
            return ;
        
        }
        pNode1->iStatus=GROUP_ADMINISTRATOR;
        saveToFile();
        pChatPDU->data.ifLogin=2;
        sendDataToClient(sockfd,pChatPDU);
        free(pChatPDU);
        pChatPDU=NULL;
        return ;
    }


}


//从客户端接收文件
void readFileFromClient(ChatPDU *pChatPDU)
{
    char caFileName[64]={'\0'};
    strcpy(caFileName,pChatPDU->caFileName);
    fileNode *fNode=makeFileNode();
    initFileNode(fNode,caFileName);
    insertFileList(fHead,fNode);
    saveFileNameToFile();

    printf("chadata:%s",pChatPDU->chatData);    
    FILE *fd=fopen(caFileName,"w");
    if(fd==NULL)
    {
        perror("fopen");
        return ;
    }
    int iLen=pChatPDU->iChatDataLen;
    printf("iLen:%d",iLen);
    fprintf(fd,"%s",pChatPDU->chatData);
    fclose(fd);
    printf("上传成功\n");
    free(pChatPDU);
    pChatPDU=NULL;
}

//查看文件链表
void AskFileName(int sockfd,ChatPDU *pChatPDU)
{
    
    pChatPDU->iTYPE=ENUM_TYPE_ASK_FILE_BACK;
    if(fHead==NULL)
    {
        sendDataToClient(sockfd,pChatPDU);
        free(pChatPDU);
        pChatPDU=NULL;
        return ;

    }
    fileNode *fNode=fHead->pFirstNode;
    while(fNode!=NULL)
    {
        strcpy(pChatPDU->data.caName,fNode->caFileName);
        if(fNode->pNext==NULL)
        {
            pChatPDU->data.ifLogin=1;
        }
        sendDataToClient(sockfd,pChatPDU);  
        fNode=fNode->pNext;

    }
    free(pChatPDU);
    pChatPDU=NULL;
    return ;
}



//发送文件到客户端
void sendFileToClient(int sockfd,ChatPDU *pChatPDU)
{
    
    char caFileNAME[64]={'\0'};
    strcpy(caFileNAME,pChatPDU->caFileName);
    int fd=open(caFileNAME,O_RDONLY);
    if(fd==-1)
    {
        perror("open");
        return ;
    }
    int iLen=lseek(fd,0,SEEK_END);
    lseek(fd,0,SEEK_SET);
    int iLeft=iLen;
    char caBuf[MAXLEN]={'\0'};
    int iRead=0;
    int ret=read(fd,caBuf,iLeft);
    while(ret>0 && iLeft)
    {
        ret=read(fd,caBuf,iLeft);
        iLeft-=ret;
        iRead+=ret;     
    }
    free(pChatPDU);
    pChatPDU=NULL;
    pChatPDU=(ChatPDU *)malloc(sizeof(ChatPDU)-sizeof(int)+iLen);
    pChatPDU->iTYPE=ENUM_TYPE_DOWN_FILE_BACK;
    pChatPDU->iFROM=SERVER;
    strcpy(pChatPDU->caFileName,caFileNAME);
    pChatPDU->iChatDataLen=iLen;
    pChatPDU->iChatPDULen=sizeof(ChatPDU)-sizeof(int)+iLen;
    strcpy(pChatPDU->chatData,caBuf);
    sendDataToClient(sockfd,pChatPDU);
    free(pChatPDU);
    pChatPDU=NULL;
    
}
//禁言
void bannedToPost(int sockfd,ChatPDU *pChatPDU)
{
    pChatPDU->iTYPE=ENUM_TYPE_BANNED_TO_POST_BACK;
    Node *pNode=findNode(pHead,pChatPDU->iFROM);
    Node *pNode1=NULL;
    if(strcmp(pNode->caGroupName,"\0")==0)//未加入群组
    {
        pChatPDU->data.ifLogin=0;
        sendDataToClient(sockfd,pChatPDU);      
        free(pChatPDU);
        pChatPDU=NULL;
        return ;
    }
    else if(pNode->iStatus==GROUP_CREW)//权限不足
    {
        pChatPDU->data.ifLogin=1;
        sendDataToClient(sockfd,pChatPDU);      
        free(pChatPDU);
        pChatPDU=NULL;
        return ;        
    }
    else if(pChatPDU->iTO==0)//全员禁言
    {
        pNode1=pHead->pFirstNode;
        while(pNode1!=NULL)
        {
            if(strcmp(pNode->caGroupName,pNode1->caGroupName)==0)
            {
                pNode1->iIfBanned=1;
                if(pNode1->data.ifLogin==1&&pNode->data.iId!=pNode1->data.iId)
                {
                    
                    pChatPDU->data.ifLogin=2;
                    pChatPDU->iTYPE=ENUM_TYPE_BANNED_TO_POST_SEND;
                    sendDataToClient(pNode1->sockfd,pChatPDU);
                }
            }
            pNode1=pNode1->pNext;
        }
        pChatPDU->data.ifLogin=2;
        sendDataToClient(sockfd,pChatPDU);      
        free(pChatPDU);
        pChatPDU=NULL;
        saveToFile();
        return ;        
    }
    else
    {
        pNode1=findNode(pHead,pChatPDU->iTO);
        if(pNode1==NULL)//用户不存在
        {
            pChatPDU->data.ifLogin=3;
            sendDataToClient(sockfd,pChatPDU);      
            free(pChatPDU);
            pChatPDU=NULL;
            return ;                    
        }
        else
        {
            if(pNode1->iIfBanned==1)//已经被禁言
            {
                pChatPDU->data.ifLogin=4;
                sendDataToClient(sockfd,pChatPDU);      
                free(pChatPDU);
                pChatPDU=NULL;
                return ;                    
            }
            else    //禁言成功
            {
                pNode1->iIfBanned=1;
                pChatPDU->data.ifLogin=5;
                sendDataToClient(sockfd,pChatPDU);      
                pChatPDU->iTYPE=ENUM_TYPE_BANNED_TO_POST_SEND;
                sendDataToClient(pNode1->sockfd,pChatPDU);
                free(pChatPDU);
                pChatPDU=NULL;
                saveToFile();
                return ;                    

            }
        }
    }
}

//解禁言
void liftBanned(int sockfd,ChatPDU *pChatPDU)
{
    pChatPDU->iTYPE=ENUM_TYPE_LIFT_BAN_BACK;
    Node *pNode=findNode(pHead,pChatPDU->iFROM);
    Node *pNode1=NULL;
    if(strcmp(pNode->caGroupName,"\0")==0)//未加入群组
    {
        pChatPDU->data.ifLogin=0;
        sendDataToClient(sockfd,pChatPDU);      
        free(pChatPDU);
        pChatPDU=NULL;
        return ;
    }
    else if(pNode->iStatus==GROUP_CREW)//权限不足
    {
        pChatPDU->data.ifLogin=1;
        sendDataToClient(sockfd,pChatPDU);      
        free(pChatPDU);
        pChatPDU=NULL;
        return ;        
    }
    else if(pChatPDU->iTO==0)//全员解禁言
    {
        pNode1=pHead->pFirstNode;
        while(pNode1!=NULL)
        {
            if(strcmp(pNode->caGroupName,pNode1->caGroupName)==0)
            {
                pNode1->iIfBanned=0;
                if(pNode1->data.ifLogin==1&&pNode->data.iId!=pNode1->data.iId)
                {
                    
                    pChatPDU->data.ifLogin=2;
                    pChatPDU->iTYPE=ENUM_TYPE_LIFT_BAN_SEND;
                    sendDataToClient(pNode1->sockfd,pChatPDU);
                }
            }
            pNode1=pNode1->pNext;
        }
        pChatPDU->data.ifLogin=2;
        sendDataToClient(sockfd,pChatPDU);      
        free(pChatPDU);
        pChatPDU=NULL;
        saveToFile();
        return ;        
    }
    else
    {
        pNode1=findNode(pHead,pChatPDU->iTO);
        if(pNode1==NULL)//用户不存在
        {
            pChatPDU->data.ifLogin=3;
            sendDataToClient(sockfd,pChatPDU);      
            free(pChatPDU);
            pChatPDU=NULL;
            return ;                    
        }
        else
        {
            if(pNode1->iIfBanned==0)//未被禁言,无需解禁
            {
                pChatPDU->data.ifLogin=4;
                sendDataToClient(sockfd,pChatPDU);      
                free(pChatPDU);
                pChatPDU=NULL;
                return ;                    
            }
            else    //解禁言成功
            {
                pNode1->iIfBanned=0;
                pChatPDU->data.ifLogin=5;
                sendDataToClient(sockfd,pChatPDU);      
                pChatPDU->iTYPE=ENUM_TYPE_LIFT_BAN_SEND;
                sendDataToClient(pNode1->sockfd,pChatPDU);
                free(pChatPDU);
                pChatPDU=NULL;
                saveToFile();
                return ;                    

            }
        }
    }
}


//踢人
void pullPeopleOutGroup(int sockfd,ChatPDU *pChatPDU)
{
    Node *pNode=findNode(pHead,pChatPDU->iFROM);
    Node *pNode1=findNode(pHead,pChatPDU->iTO); 
    pChatPDU->iTYPE=ENUM_TYPE_OUT_GROUP_BACK;
    if(pNode1==NULL)//用户不存在
    {
        sendDataToClient(sockfd,pChatPDU);
        free(pChatPDU);
        pChatPDU=NULL;
        return ;
    }
    else
    {
        if(strcmp(pNode1->caGroupName,pNode->caGroupName)!=0)//用户非本群成员
        {
            pChatPDU->data.ifLogin=1;
            sendDataToClient(sockfd,pChatPDU);
            free(pChatPDU);
            pChatPDU=NULL;
            return ;    
        }
        strcpy(pNode1->caGroupName,"\0");
        saveToFile();
        pChatPDU->data.ifLogin=2;
        sendDataToClient(sockfd,pChatPDU);
        pChatPDU->iTYPE=ENUM_TYPE_OUT_GROUP_SEND;
        strcpy(pChatPDU->caFileName,pNode->caGroupName);
        sendDataToClient(pNode1->sockfd,pChatPDU);
        free(pChatPDU);
        pChatPDU=NULL;
        return ;
    }
}

//退出登录
void quitEnter(ChatPDU *pChatPDU)
{
    Node *pNode=findNode(pHead,pChatPDU->iFROM);
    pNode->data.ifOnline=0;
    pNode->sockfd=0;
    saveToFile();
    strcpy(pChatPDU->data.caName,pNode->data.caName);
    pChatPDU->iTYPE=ENUM_TYPE_QUIT_ENTER_SEND;
    pNode=pHead->pFirstNode;
    while(pNode!=NULL)
    {
        if(pNode->data.ifOnline==1)
        {
            sendDataToClient(pNode->sockfd,pChatPDU);           
        }
        pNode=pNode->pNext;
    }
    free(pChatPDU);
    pChatPDU=NULL;
}

//线程
void *handleClient(void *arg)
{
    int sockClient = *(int*)arg;
    ChatPDU *pChatPDU=NULL;
    int iMsgType=0;
    while (1)
    {
        //获得PDU
        pChatPDU=readDataFromClient(sockClient);
        if(pChatPDU!=NULL)
        {
        /*解析PDU*/
            iMsgType=parsePDU(pChatPDU);
            switch(iMsgType)
            {
                case ENUM_TYPE_LOGIN_GO:
                    getLoginpleaseFromClient(sockClient,pChatPDU);
                    showList(pHead);
                    break;
                case ENUM_TYPE_ENTER_GO:
                    getEnterPleaseFromClient(sockClient,pChatPDU);
                    break;
                case ENUM_TYPE_ASK_ID_GO:
                    getAskToOnlineUsr(sockClient);
                    break;
                case ENUM_TYPE_ASK_ALL_ID_GO:
                    getAskToAllUsr(sockClient);
                    break;
                case ENUM_TYPE_CHAT_PRICATE_GO:
                    chatPrivateToClient(sockClient,pChatPDU);
                    break;
                case ENUM_TYPE_CHANGE_PASSWORD_GO:
                    changePassword(pChatPDU);
                    break;
                case ENUM_TYPE_WRITE_DAILY_GO:
                    writeDaily(pChatPDU);
                    break;
                case ENUM_TYPE_READ_DAILY_GO:
                    readDaily(sockClient,pChatPDU);
                    break;
                case ENUM_TYPE_SET_GROUP_GO:
                    setChatGroup(sockClient,pChatPDU);
                    break;
                case ENUM_TYPE_IN_GROUP_GO:
                    pullPeopleInGroup(sockClient,pChatPDU);
                    break;
                case ENUM_TYPE_CHAT_GROUP_GO:
                    chatGroupToClient(sockClient,pChatPDU);
                    break;
                case ENUM_TYPE_ASK_GROUP_ID_GO:
                    getAskToGroupUsr(sockClient,pChatPDU);
                    break;
                case ENUM_TYPE_SET_ADMINISTRATOR_GO:
                    setAdministrtor(sockClient,pChatPDU);
                    break;
                case ENUM_TYPE_UP_FILE:
                    readFileFromClient(pChatPDU);
                    break;
                case ENUM_TYPE_ASK_FILE_GO:
                    AskFileName(sockClient,pChatPDU);
                    break;
                case ENUM_TYPE_DOWN_FILE_GO:
                    sendFileToClient(sockClient,pChatPDU);
                    break;
                case ENUM_TYPE_BANNED_TO_POST_GO:
                    bannedToPost(sockClient,pChatPDU);
                    break;
                case ENUM_TYPE_LIFT_BAN_GO:
                    liftBanned(sockClient,pChatPDU);
                    break;
                case ENUM_TYPE_OUT_GROUP_GO:
                    pullPeopleOutGroup(sockClient,pChatPDU);
                    break;
                case ENUM_TYPE_QUIT_ENTER_GO:
                    quitEnter(pChatPDU);
                    break;
                default:
                    break;

            }
        }
        else
            return NULL;
    
    }
}

int main(int argc,char **argv)
{
    pHead=makeList();
    fHead=makeFileList();
    readFromFile();
    showList(pHead);
    readFileNameFromFile();
    

    int sockfd = 0;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == sockfd)
    {
        perror("socket");
        return -1;
    }
    struct sockaddr_in servaddr;
    //地址协议:ipv4
    servaddr.sin_family = AF_INET;
    //服务器端口
    servaddr.sin_port = htons(atoi(argv[2]));
    //服务器ip
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);
    bzero(&(servaddr.sin_zero), 8);
    int ret = bind(sockfd
                   , (struct sockaddr *)&servaddr
                   , sizeof(struct sockaddr));
    if (-1 == ret)
    {
        perror("bind");
        return -1;
    }
    ret = listen(sockfd, 10);
    if (-1 == ret)
    {
        perror("listen");
        return -1;
    }

    struct sockaddr_in clientaddr;
    int iLen = sizeof(struct sockaddr);
    int sockClient = 0;
    pthread_t pt;
    while (1)
    {
        printf("accepting client connect...\n");
        sockClient = accept(sockfd
                    , (struct sockaddr *)&clientaddr
                    ,(socklen_t *)&iLen);
        
        ret = pthread_create(&pt, NULL, handleClient
                             , (void *)&sockClient);
        if (0 != ret)
        {
            perror("pthread_create");
            return -1;
        }
    }
    pthread_detach(pt);

    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容