day08

作者: 萌面大叔2 | 来源:发表于2016-12-10 13:59 被阅读0次

    client.h

    #ifndef CLIENT_H
    #define CLIENT_H
    
    #include "link.h"
    #include "protocol.h"
    #include <string.h>
    
    #define MAX_DATA_LEN 64
    
    int makeSocket();
    void makeConnect(int sockfd);
    void makeReadThread(int sockfd);
    
    void getUsrListFromPDU(PDU *pPDU);
    
    void showChatData(PDU *pPDU);
    
    void *readThread(void *arg);
    
    void readDataFromSTDIN(char caData[MAX_DATA_LEN]);
    
    #endif // CLIENT_H
    
    

    client.c

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h> //struct sockaddr_in
    #include <string.h>
    #include <errno.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include "client.h"
    
    List *pList = NULL;
    uint g_iId = 0;
    
    void getUsrListFromPDU(PDU *pPDU)
    {
        if (NULL == pPDU || NULL == pList)
        {
            return;
        }
        int iNum = pPDU->iDataLen / sizeof(int);
        Node *pNode = NULL;
        int i = 0;
        while (iNum)
        {
            pNode = makeNode();
            if (NULL == pNode)
            {
                return;
            }
            memcpy(&(pNode->iId), pPDU->caData+i*sizeof(int)
                   , sizeof(int));
            insertList(pList, pNode);
            i++;
            iNum--;
        }
        if (0 == g_iId)
        {
            pNode = pList->pFirstNode;
            while (NULL != pNode->pNext)
            {
                pNode = pNode->pNext;
            }
            g_iId = pNode->iId;
        }
        showList(pList);
    }
    
    void showChatData(PDU *pPDU)
    {
        if (NULL != pPDU)
        {
            char caMsg[MAX_DATA_LEN] = {'\0'};
            memcpy(caMsg, pPDU->caData, pPDU->iDataLen);
            printf("%d says: %s\n", pPDU->iFromId, caMsg);
        }
    }
    
    void *readThread(void *arg)
    {
        int sockfd = (int)arg;
        PDU *pPDU = NULL;
        uint iType = 0;
        while (1)
        {
            pPDU = readPDU(sockfd);
            iType = parsePDU(pPDU);
            switch (iType)
            {
            case ENUM_MSG_RESPONSE_USR_LIST:
                getUsrListFromPDU(pPDU);
                break;
            case ENUM_MSG_GROUP_CHAT:
            case ENUM_MSG_PRIVATE_CHAT:
                showChatData(pPDU);
                break;
            default:
                break;
            }
        }
        return NULL;
    }
    
    void readDataFromSTDIN(char caData[MAX_DATA_LEN])
    {
        memset(caData, '\0', MAX_DATA_LEN);
        int ret = read(STDIN_FILENO, caData, MAX_DATA_LEN);
        if (-1 == ret)
        {
            perror("read");
            return;
        }
        if ('\0' != caData[MAX_DATA_LEN-1]
            && '\n' != caData[MAX_DATA_LEN-1])
        {
            while ('\n' != getchar())
            {}
        }
        caData[MAX_DATA_LEN-1] = '\0';
    }
    
    
    
    
    int makeSocket()
    {
        int sockfd = socket(AF_INET
                            , SOCK_STREAM
                            , 0);
        if (-1 == sockfd)
        {
            perror("socket");
            exit(EXIT_FAILURE);
        }
        return sockfd;
    }
    
    
    void makeConnect(int sockfd)
    {
        int ret = -1;
        struct sockaddr_in serverAddr;
        serverAddr.sin_family = AF_INET;
        serverAddr.sin_port = htons(8888);
        serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
        bzero(&(serverAddr.sin_zero), 8);
    
        ret = connect(sockfd, (struct sockaddr *)&serverAddr
                      , sizeof(serverAddr));
        if (-1 == ret)
        {
            perror("connect");
            exit(EXIT_FAILURE);
        }
    }
    
    
    void makeReadThread(int sockfd)
    {
        int ret = -1;
        pthread_t thread;
        ret = pthread_create(&thread, NULL
                             , readThread, (void*)sockfd);
        if (0 != ret)
        {
            printf("%s\n", strerror(ret));
            exit(EXIT_FAILURE);
        }
    }
    

    main.c(client)

    #include "client.h"
    
    extern List *pList;
    extern uint g_iId;
    
    int main(void)
    {
        pList = makeList();
        if (NULL == pList)
        {
            return -1;
        }
    
        int sockfd = -1;
        sockfd = makeSocket();
        makeConnect(sockfd);
        makeReadThread(sockfd);
    
        //write data to server
        char caData[MAX_DATA_LEN] = {'\0'};
        int iLen = 0;
        PDU *pPDU = NULL;
        int iToId = 0;
        char caMsg[MAX_DATA_LEN] = {'\0'};
        while (1)
        {
            //1002 hello
            readDataFromSTDIN(caData);
            memset(caMsg, '\0', MAX_DATA_LEN);
            sscanf(caData, "%d%s", &iToId, caMsg);
    
            iLen = strlen(caMsg);
            if (iLen > 0)
            {
                pPDU = makePDU(iLen);
                memcpy(pPDU->caData, caMsg, iLen);
                pPDU->iFromId = g_iId;
                if (0 == iToId)
                {
                    pPDU->iType = ENUM_MSG_GROUP_CHAT;
                }
                else
                {
                    pPDU->iToId = iToId;
                    pPDU->iType = ENUM_MSG_PRIVATE_CHAT;
                }
                sendPDU(sockfd, pPDU);
            }
        }
    
        return 0;
    }
    

    server.h

    #ifndef SERVER_H
    #define SERVER_H
    
    #include <stdio.h>
    
    #include "link.h"
    #include "protocol.h"
    
    
    void sendUsrListToClient(int sockfd, const List *pList);
    
    void updateClientsUsrList(const List *pList);
    
    void handleGroupChat(PDU *pPDU);
    
    void handlePrivateChat(PDU *pPDU);
    
    void *handleClient(void *arg);
    
    int makeSocket();
    void makeBind(int sockfd);
    void makeListen(int sockfd);
    int makeAccept(int sockfd);
    void makeHandleClientThread(int sockfd);
    void storeClientInfo(int sockfd);
    
    
    #endif // SERVER_H
    
    

    server.c

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h> //struct sockaddr_in
    #include <errno.h>
    #include <string.h>
    #include <pthread.h>
    #include <stdlib.h>
    #include "server.h"
    
    List *pList = NULL;
    uint iBaseId = 1001;
    
    void sendUsrListToClient(int sockfd, const List *pList)
    {
        if (sockfd < 0 || NULL == pList)
        {
            return;
        }
        int iDataLen = pList->iLen * sizeof(int);
        PDU *pPDU = makePDU(iDataLen);
        if (NULL == pPDU)
        {
            return;
        }
    
        Node *pNode = pList->pFirstNode;
        int i = 0;
        while (NULL != pNode)
        {
            memcpy(pPDU->caData+i*sizeof(int)
                   , &(pNode->iId), sizeof(int));
            i++;
            pNode = pNode->pNext;
        }
        pPDU->iType = ENUM_MSG_RESPONSE_USR_LIST;   
        sendPDU(sockfd, pPDU);
    }
    
    void updateClientsUsrList(const List *pList)
    {
        if (NULL == pList)
        {
            return;
        }
        PDU *pPDU = makePDU(sizeof(int));
        if (NULL == pPDU)
        {
            return;
        }
        memcpy(pPDU->caData, &(pList->pFirstNode->iId)
               , sizeof(int));
        pPDU->iType = ENUM_MSG_RESPONSE_USR_LIST;
        Node *pNode = pList->pFirstNode->pNext;
        while (NULL != pNode)
        {
            sendPDU(pNode->sockfd, pPDU);
            pNode = pNode->pNext;
        }
    }
    
    
    void handleGroupChat(PDU *pPDU)
    {
        if (NULL != pPDU)
        {
            Node *pNode = pList->pFirstNode;
            while (NULL != pNode)
            {
                sendPDU(pNode->sockfd, pPDU);
                pNode = pNode->pNext;
            }
        }
    }
    
    void handlePrivateChat(PDU *pPDU)
    {
        if (NULL != pPDU)
        {
            Node *pNode = NULL;
            pNode = findNode(pList, pPDU->iToId);
            if (NULL != pNode)
            {
                sendPDU(pNode->sockfd, pPDU);
            }
        }
    }
    
    void *handleClient(void *arg)
    {
        int clientSockfd = (int)arg;
    
        storeClientInfo(clientSockfd);
    
        PDU *pPDU = NULL;
        uint iType = 0;
        while (1)
        {
            pPDU = readPDU(clientSockfd);
            if (NULL != pPDU)
            {
                iType = parsePDU(pPDU);
                switch (iType)
                {
                case ENUM_MSG_REQUEST_USR_LIST:
                    break;
                case ENUM_MSG_GROUP_CHAT:
                    handleGroupChat(pPDU);
                    break;
                case ENUM_MSG_PRIVATE_CHAT:
                    handlePrivateChat(pPDU);
                    break;
                default:
                    break;
                }
            }
        }
    }
    
    int makeSocket()
    {
        int sockfd = socket(AF_INET
                            , SOCK_STREAM
                            , 0);
        if (-1 == sockfd)
        {
            perror("socket");
            exit(EXIT_FAILURE);
        }
        return sockfd;
    }
    
    
    void makeBind(int sockfd)
    {
        int ret = -1;
        struct sockaddr_in serverAddr;
        serverAddr.sin_family = AF_INET;   //ipv4
        serverAddr.sin_port = htons(8888); //port
        //server ip
        serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
        bzero(&(serverAddr.sin_zero), 8);
        //将sockfd和地址进行绑定
        ret = bind(sockfd, (struct sockaddr *)&serverAddr
                       , sizeof(serverAddr));
        if (-1 == ret)
        {
            perror("bind");
            exit(EXIT_FAILURE);
        }
    }
    
    void makeListen(int sockfd)
    {
        int ret = -1;
        ret = listen(sockfd, 5);
        if (-1 == ret)
        {
            perror("listen");
            exit(EXIT_FAILURE);
        }
    }
    
    int makeAccept(int sockfd)
    {
        struct sockaddr_in clientAddr;
        int iLen = sizeof(clientAddr);
        int clientSockfd = -1;
        clientSockfd = accept(sockfd
                        , (struct sockaddr *)&clientAddr
                        , &iLen);
        if (-1 == clientSockfd)
        {
            perror("accept");
            exit(EXIT_FAILURE);
        }
        return clientSockfd;
    }
    
    
    void makeHandleClientThread(int sockfd)
    {
        pthread_t thread;
        pthread_create(&thread, NULL, handleClient
                       , (void *)sockfd);
    }
    
    
    void storeClientInfo(int sockfd)
    {
        Node *pNode = makeNode();
        if (NULL == pNode)
        {
            return;
        }
        pNode->iId = iBaseId;
        pNode->sockfd = sockfd;
        iBaseId++;
        insertList(pList, pNode);
    }
    

    main.c(server)

    #include "server.h"
    
    extern List *pList;
    
    int main(void)
    {
        pList = makeList();
        if (NULL == pList)
        {
            return -1;
        }
    
        int sockfd = -1;
        sockfd = makeSocket();
        makeBind(sockfd);
        makeListen(sockfd);
    
        int clientSockfd = -1;
        while (1)
        {
            clientSockfd = makeAccept(sockfd);
            makeHandleClientThread(clientSockfd);
    
            sendUsrListToClient(clientSockfd, pList);
            updateClientsUsrList(pList);
        }
    
        return 0;
    }
    

    link.h

    #ifndef LINK_H
    #define LINK_H
    
    #include <stdio.h>
    
    typedef struct Node
    {
        int iId;
        int sockfd;
        struct Node *pNext;
    }Node;
    
    typedef struct List
    {
        int iLen;
        Node *pFirstNode;
    }List;
    
    Node *makeNode();
    List *makeList();
    void insertList(List *pList, Node *pNode);
    Node *findNode(const List *pList, int iId);
    void showList(const List *pList);
    
    #endif
    
    

    link.c

    #include "link.h"
    #include <stdlib.h>
    
    Node *makeNode()
    {
        Node *pNode = NULL;
        pNode = (Node *)malloc(sizeof(Node));
        if (NULL != pNode)
        {
            pNode->iId = 0;
            pNode->sockfd = -1;
            pNode->pNext = NULL;
        }
        return pNode;
    }
    List *makeList()
    {
        List *pList = NULL;
        pList = (List *)malloc(sizeof(List));
        if (NULL != pList)
        {
            pList->iLen = 0;
            pList->pFirstNode = NULL;
        }
        return pList;
    }
    
    void insertList(List *pList, Node *pNode)
    {
        if (NULL == pList || NULL == pNode)
        {
            return;
        }
        if (NULL == pList->pFirstNode)
        {
            pList->pFirstNode = pNode;
        }
        else
        {
            pNode->pNext = pList->pFirstNode;
            pList->pFirstNode = pNode;
        }
        pList->iLen++;
    }
    Node *findNode(const List *pList, int iId)
    {
        if (NULL == pList)
        {
            return NULL;
        }
        Node *pNode = pList->pFirstNode;
        while (NULL != pNode)
        {
            if (pNode->iId == iId)
            {
                break;
            }
            pNode = pNode->pNext;
        }
        return pNode;
    }
    void showList(const List *pList)
    {
        if (NULL == pList)
        {
            return;
        }
        Node *pNode = pList->pFirstNode;
        while (NULL != pNode)
        {
            printf("id: %d, sockfd: %d\n", pNode->iId
                                         , pNode->sockfd);
            pNode = pNode->pNext;
        }
        printf("-------------------------------\n");
    }
    

    protocol.h

    #ifndef PROTOCOL_H
    #define PROTOCOL_H
    
    #include <stdio.h>
    
    typedef unsigned int uint;
    
    enum ENUM_MSG_TYPE
    {
        ENUM_MSG_MIN = 0,
        ENUM_MSG_PRIVATE_CHAT,   //私聊
        ENUM_MSG_GROUP_CHAT,     //群聊
        ENUM_MSG_REQUEST_USR_LIST,   //请求用户列表
        ENUM_MSG_RESPONSE_USR_LIST,  //回复用户列表
        ENUM_MSG_MAX = 0x0fffffff
    };
    
    typedef struct PDU
    {
        uint iPDULen;    //整个协议数据单元的大小
        uint iType;      //消息类型:群聊,私聊,获取用户列表
        uint iDataLen;   //消息的长度
        int iFromId;     //消息的发送者
        int iToId;       //消息的接收者
        char caData[4];  //要发送的消息
    }PDU;
    
    PDU *makePDU(int iDataLen);
    uint parsePDU(PDU *pPDU);
    void sendPDU(int sockfd, const PDU *pPDU);
    PDU *readPDU(int sockfd);
    
    #endif
    

    protocol.c

    #include "protocol.h"
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <unistd.h>
    
    PDU *makePDU(int iDataLen)
    {
        PDU *pPDU = NULL;
        uint iLen = sizeof(PDU) - 4*sizeof(char) + iDataLen;
        pPDU = (PDU *)malloc(iLen);
        if (NULL != pPDU)
        {
            memset(pPDU, 0, iLen);
            pPDU->iPDULen = iLen;
            pPDU->iType = ENUM_MSG_MIN;
            pPDU->iDataLen = iDataLen;
        }
        return pPDU;
    }
    
    uint parsePDU(PDU *pPDU)
    {
        uint iType = ENUM_MSG_MIN;
        if (NULL != pPDU)
        {
            iType = pPDU->iType;
        }
    
        return iType;
    }
    
    
    void sendPDU(int sockfd, const PDU *pPDU)
    {
        if (sockfd < 0 || NULL == pPDU)
        {
            return;
        }
    
        int ret = -1;
        int iLeft = pPDU->iPDULen;
        int iSended = 0;
        while (iLeft)
        {
            ret = write(sockfd, (char *)pPDU+iSended, iLeft);
            if (-1 == ret)
            {
                if (EINTR == errno)
                {
                    continue;
                }
                perror("write");
                return;
            }
            iSended += ret;
            iLeft -= ret;
        }
    }
    
    
    PDU *readPDU(int sockfd)
    {
        int ret = -1;
        uint iPDULen = 0;
        ret = read(sockfd, &iPDULen, sizeof(uint));
        if (-1 == ret)
        {
            perror("read");
            return NULL;
        }
        PDU *pPDU = makePDU(iPDULen-3*sizeof(int));
        if (NULL == pPDU)
        {
            return NULL;
        }
        pPDU->iPDULen = iPDULen;
        int iLeft = iPDULen - sizeof(int);
        int iReaded = sizeof(int);
        while (iLeft)
        {
            ret = read(sockfd, (char *)pPDU+iReaded, iLeft);
            if (-1 == ret)
            {
                if (EINTR == errno)
                {
                    continue;
                }
                perror("while read");
                return NULL;
            }
            iLeft -= ret;
            iReaded += ret;
        }
        return pPDU;
    }
    

    相关文章

      网友评论

          本文标题:day08

          本文链接:https://www.haomeiwen.com/subject/urxumttx.html