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;
}

相关文章

  • 20160818

    《把时间当作朋友》Day08

  • 8.synchronized 和 volatile 的区别

    /** * 每天一个知识点day08 TODO synchronized 和 volatile 的区别 * 被sy...

  • 2019-05-03java第八天

    day08【String类、static关键字、Arrays类、Math类】 今日内容 String类 stati...

  • 自律给我自由—Day008

    【叶子姑娘的自律100天挑战 Day08】 2019.01.22 Day8/100 【早起】第11天早起 【阅读】...

  • Java面向对象,继承,this,super,重写,final

    day08笔记【Java面向对象,继承,this,super,重写,final】 1_面向对象(代码块的概述和分类...

  • 晨起阅读 Day08:《冯唐成事心法》02章

    阅读日记-Day08:2021.01.19 周二 阅读时间:05:40-06:30阅读内容:《冯唐成事心法》第二...

  • day08

    A今天学了什么 1.公共样式的提取 2.CSS2d转化 3.过渡 B今天学到了什么 1.公共样式的提取 2.CSS...

  • day08

    类型信息 本章将讨论java是如何让我们在运行时识别对象和类的信息的.主要有两种方式:一种是"传统的"RTTI,它...

  • Day08

    二维数组 二维数组格式 二维数组初始化 二维数组的遍历 二维数组内存存储细节 二维数组与函数注意点: 主要是看函数...

  • Day08

    回顾与计划。昨天看群里情歌哥的一篇文章《我正在坚持的九个习惯》感觉不错。里面的第八个习惯是 统计与计划。 "每天睡...

网友评论

      本文标题:day08

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