“掌中”通訊

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)//不能保證一次性收完,循環(huán)接收
    {
        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;
}


//發(fā)送修改密碼
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

//創(chuàng)建群組
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 ;


}

//收獲創(chuàng)建群組返回
void getSetGroupBack(ChatPDU *pChatPDU)
{
    if(pChatPDU->data.ifLogin==0)
    {
        printf("群組名已存在,請重新創(chuàng)建\n");
        g_iFlag=1;
    }
    else
    {
        printf("群組創(chuàng)建成功\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("邀請失敗:該用戶已經(jīng)是群成員了\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("設置失敗,該用戶已經(jīng)是群主或管理員了\n");
        g_iFlag=1;
    }
    else if(pChatPDU->data.ifLogin==3)
    {
        printf("設置失敗,權(quán)限不足\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;
}


//發(fā)送下載請求
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("禁言失敗:權(quán)限不足\n");
            break;
        case 2:
            printf("禁言成功\n");
            break;
        case 3:
            printf("禁言失敗:該用戶不存在\n");
            break;
        case 4:
            printf("禁言失敗:該用戶已經(jīng)被禁言\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("解禁言失敗:權(quán)限不足\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.創(chuàng)建群組\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;
        }
    }
}

//發(fā)送登錄請求
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;
}


//發(fā)送注冊請求
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("是否繼續(xù)注冊?\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;
    //地址協(xié)議: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)//不能保證一次性收完,循環(huán)接收
    {
        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
//創(chuàng)建群組
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 ;
}



//發(fā)送文件到客戶端
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)//權(quán)限不足
    {
        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)//已經(jīng)被禁言
            {
                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)//權(quán)限不足
    {
        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;
    //地址協(xié)議: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;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,412評論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,514評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,373評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,975評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,743評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,199評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,262評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,414評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,951評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,780評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,527評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,218評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,649評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,889評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,673評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內(nèi)容