server.cpp

/*********************************************************************************
Copyright (cpp) Novatek Microelectronics Corp., Ltd. All Rights Reserved.
\file client.cpp
\brief achieve two terninal communication
\for Liunx
\chip none
\Date 2024-08-22
\version v0.0.1
*********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/select.h>
#include "PrintLevel.h"

#define BUFFER_SIZE  (1024)
#define MAX_CLIENTS  (2)
#define INITSOCKETE  (-1)
#define MYPORT       (2222)
#define IP           ("127.0.0.1")

typedef unsigned int   u32;
typedef unsigned short u16;
typedef char           u8;
typedef int            s32;

typedef enum _EN_ERRO_RETURN
{
    EN_BIND_FAIL      = -2,
    EN_LISTENSOC_FAIL = -1,
    EN_SUCCESS        = 0
}EN_ERRO_RETURN;

s32 gPrintAPILevel                      = EN_PRINTAPI_MSG;
static s32 giServerSocket               = INITSOCKETE;
static s32 giClientSockets[MAX_CLIENTS] = {0};
static s32 giClientCount                = 0;
static pthread_mutex_t gClientMutex     = PTHREAD_MUTEX_INITIALIZER;
volatile sig_atomic_t vsServerRunSig    = 1;

/*!
@brisf:handle_signal

*@para[in] const u8 *message

*@return void:
*/
void HandleSignal(s32 iSig)
{
    PRINTAPI_TRC("Enter HandleSignal API\n");
    PRINTAPI_DBG("HandleSignal API iSig %d \n", iSig);
    if (iSig == SIGINT) 
    {
        PRINTAPI_ERR("\n Server interrupted by user (Ctrl+C). Exiting...\n");
        vsServerRunSig = 0;
    }
    else if (iSig == SIGTSTP)
    {
        PRINTAPI_ERR("\n Server suspended by user (Ctrl+Z). Exiting...\n");
        vsServerRunSig = 0;
    }
    PRINTAPI_TRC("Out HandleSignal API\n");
    return;
}

/*!
@brisf:handle_clien

*@para[in] void *pArg

*@return void*:
*/
void *HandleClient(void *pArg) 
{
    PRINTAPI_TRC("Enter HandleClient API\n");
    u8 cBuff[BUFFER_SIZE] = {0};
    s32 iBytesRead        = 0;
    s32 iClientSocket     = 0;

    if(nullptr == pArg)
    {
        PRINTAPI_ERR("HandleClient pArg is nullpointer\n");
        return NULL;
    }
    iClientSocket = *(s32 *)pArg;
    PRINTAPI_DBG("HandleClient API iClientSocket is %d \n", iClientSocket);

    while(vsServerRunSig)
    {
        iBytesRead = recv(iClientSocket, cBuff, BUFFER_SIZE - 1, 0);
        if(iBytesRead < 0)
        {
            PRINTAPI_ERR("HandleClient recv fail\n");
            break;
        }
        else if(0 == iBytesRead)
        {
            PRINTAPI_ERR("Client id %d disconnected\n",iClientSocket);
            break;
        }
        cBuff[iBytesRead] = '\0';
        PRINTAPI_MSG("%s\n", cBuff);

        //Brocast news to other clients
        pthread_mutex_lock(&gClientMutex);
        for(s32 i = 0; i < giClientCount; i++)
        {
            if (giClientSockets[i] != iClientSocket)
            {
                if (send(giClientSockets[i], cBuff, strlen(cBuff), 0) < 0)
                {
                    PRINTAPI_ERR("HandleClient API send fail");
                }
            }
        }
        pthread_mutex_unlock(&gClientMutex);
    }

    //Remove client from clientlist
    pthread_mutex_lock(&gClientMutex);
    for(s32 i = 0; i < giClientCount; i++)
    {
        if(giClientSockets[i] == iClientSocket)
        {
            for(s32 j = i; j < giClientCount - 1; j++)
            {
                giClientSockets[j] = giClientSockets[j + 1];
            }
            giClientCount--;
            pthread_mutex_unlock(&gClientMutex);
            break;
        }
    }
    pthread_mutex_unlock(&gClientMutex);

    if(iClientSocket != INITSOCKETE)
    {
        close(iClientSocket);
        iClientSocket = INITSOCKETE;
    }
    pthread_exit(NULL);
    PRINTAPI_TRC("Out HandleClient API\n");
    return NULL;
}

/*!
@brisf:main

*@para[in]

*@return s32:
*\retval -2    If EN_BIND_FAIL
*\retval -1    If EN_LISTENSOC_FAIL
*\retval 0     If EN_SUCCESS.
*/
s32 main()
{
    PRINTAPI_TRC("Enter main API\n");
    //Create server socket
    EN_ERRO_RETURN enRet             = EN_SUCCESS;
    giServerSocket                   = socket(AF_INET, SOCK_STREAM, 0);
    s32 iClientSocket                = INITSOCKETE;
    s32 iThreadCount                 = 0;
    pthread_t tidClient[MAX_CLIENTS] = {0};

    //Set server address
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;//Use IPV4 address
    server_addr.sin_addr.s_addr = inet_addr(IP);//IP
    server_addr.sin_port = htons(MYPORT); //Port

    //Register signal handler
    struct sigaction sa;
    sa.sa_handler = HandleSignal;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTSTP, &sa, NULL);

    //Bbind socket to addr
    if((bind(giServerSocket, (struct sockaddr *)&server_addr, sizeof(server_addr))) < 0)
    {
        PRINTAPI_ERR("Server socket bind fail\n");
        enRet = EN_BIND_FAIL;
        PRINTAPI_DBG("enRet = %d\n", enRet);
        goto FREE_END;
    }

    //Listen connect request
    if((listen(giServerSocket, MAX_CLIENTS)) < 0)
    {
        PRINTAPI_ERR("Server socket listen fail\n");
        enRet = EN_LISTENSOC_FAIL;
        PRINTAPI_DBG("enRet = %d\n", enRet);
        goto FREE_END;
    }
    PRINTAPI_MSG("Server listening on port %d\n", MYPORT);

    //Loop to accpet client connect
    while(vsServerRunSig)
    {
        //Recieive client connect request
        iClientSocket = accept(giServerSocket, NULL, NULL);
        if(iClientSocket < 0) 
        {
            PRINTAPI_ERR("Server socket accept client fail\n");
            continue;;//Enter next loop
        }

        //Add new client to list
        pthread_mutex_lock(&gClientMutex);
        if(giClientCount < MAX_CLIENTS)
        {
            giClientSockets[giClientCount++] = iClientSocket;
            PRINTAPI_ERR("New client id :% d connected\n", iClientSocket);
        }
        else
        {
            PRINTAPI_ERR("Maximum number of clients reached\n");
            pthread_mutex_unlock(&gClientMutex);
            if(iClientSocket != INITSOCKETE)
            {
                close(iClientSocket);
                iClientSocket = INITSOCKETE;
            }
            continue;
        }
        pthread_mutex_unlock(&gClientMutex);

        //Creat pthread of client connect
        if((pthread_create(&tidClient[iThreadCount++], NULL, HandleClient, &iClientSocket)) != 0)
        {
            PRINTAPI_ERR("HandleClient pthread create fail\n");
            if(iClientSocket != INITSOCKETE)
            {
                close(iClientSocket);
                iClientSocket = INITSOCKETE;
            }
            continue;
        }
    }

    for(int i = 0; i < iThreadCount; i++)
    {
        if((pthread_join(tidClient[i], NULL)) != 0)
        {
            PRINTAPI_ERR("Thread %d join fail\n", i+1);
        }
    }

FREE_END:
    if(giServerSocket != INITSOCKETE)
    {
        close(giServerSocket);
        giServerSocket = INITSOCKETE;
    }
    PRINTAPI_TRC("Out main API, enRet = %d \n", enRet);
    return enRet;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值