123345

/*********************************************************************************
Copyright (cpp) Novatek Microelectronics Corp., Ltd. All Rights Reserved.
\file client.cpp
\brief achieve two terninal communication
\for Liunx
\chip none
\Date 2024-08-13
\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 MYPORT (1111)
#define IP ("127.0.0.1")

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

enum EN_ERRO_RETURN
{
    ArgcFault     = -3,
    BindFail      = -2,
    ListenSocFail = -1,
    Success       = 0
};

static s32 giServerSocket = -1;
static s32 giClientSockets[MAX_CLIENTS] = {0};
static s32 giClientCount = 0;
static pthread_mutex_t gClientMutex = PTHREAD_MUTEX_INITIALIZER;
s32 g_PRINTAPI_level = g_PRINTAPI_msg;
volatile sig_atomic_t vsServerRunSig = 1;

/*!
@brisf:handle_signal

*@para[in] const u8 *message

*@return void:
*/
void handle_signal(s32 iSig) 
{
    PRINTAPI_trc("Enter handle_signal API\n");
    if (iSig == SIGINT) 
    {
        printf("\nServer interrupted by user (Ctrl+C). Exiting...\n");
        if(giServerSocket != -1)
        {
            close(giServerSocket);  
            giServerSocket = -1; 
        }
        exit(EXIT_SUCCESS);
    } 
    else if (iSig == SIGTSTP) 
    {
        printf("\nServer suspended by user (Ctrl+Z). Resuming...\n");
        if(giServerSocket != -1)
        {
            close(giServerSocket);  
            giServerSocket = -1; 
        }
        exit(EXIT_SUCCESS);
    }
    PRINTAPI_trc("out handle_signal API\n");
}

/*!
@brisf:handle_clien

*@para[in] void *pArg

*@return void*:
*/
void *HandleClient(void *pArg) 
{
    PRINTAPI_trc("Enter handle_client API\n");
    if(nullptr == pArg)
    {
        PRINTAPI_err("nullpointer\n");
        return NULL;
    }
    u8 cBuff[BUFFER_SIZE] = {0};
    s32 iBytesRead = 0;
    s32 iClientSocket = *(s32 *)pArg;
    PRINTAPI_dbg("iClientSocket is %d \n", iClientSocket);
    while (vsServerRunSig) 
    {
        iBytesRead = recv(iClientSocket, cBuff, BUFFER_SIZE - 1, 0);
        if (iBytesRead <= 0) //=0 close connenct
        {
            PRINTAPI_err("recv");
            //vsServerRunSig = 0;
            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("senderro");
                }
            }
        }
        pthread_mutex_unlock(&gClientMutex);
    }

    if (iBytesRead < 0) 
    {
        PRINTAPI_err("recv");
    } 
    else if (0 == iBytesRead)
    {
        PRINTAPI_err("Client %d disconnected\n",iClientSocket);
    }

    // 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);

    close(iClientSocket);
    PRINTAPI_trc("out handle_client API\n");
    return NULL;
}

/*!
@brisf:main

*@para[in]

*@return s32:
*\retval -2    If BindFail
*\retval -1    If ListenSocFail
*\retval 0     If success.
*/
s32 main()
{
    PRINTAPI_trc("Enter main API\n");
    // create server socket
    giServerSocket = socket(AF_INET, SOCK_STREAM, 0);
    s32 iClientSocket = -1;
    pthread_t tidClient = {};
    // 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 = handle_signal;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTSTP, &sa, NULL);

    // bind socket to addr
    if (bind(giServerSocket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) 
    {
        PRINTAPI_err("bindSocFail");
        close(giServerSocket);
        PRINTAPI_trc("out main API\n");
        return BindFail;
    }

    // listen connect request
    if (listen(giServerSocket, MAX_CLIENTS) < 0) 
    {
        PRINTAPI_err("ListenSocFail");
        close(giServerSocket);
        PRINTAPI_trc("out main API\n");
        return ListenSocFail;
    }

    PRINTAPI_msg("Server listening on port %d\n", MYPORT);
    while (vsServerRunSig) 
    {
        // recieive client connect request
         iClientSocket = accept(giServerSocket, NULL, NULL);
        if (iClientSocket < 0) 
        {
            PRINTAPI_err("accept");
            goto END;//enter next loop
        }

        // add new client to list
        pthread_mutex_lock(&gClientMutex);
        if (giClientCount < MAX_CLIENTS) 
        {
            giClientSockets[giClientCount++] = iClientSocket;
            PRINTAPI_msg("New client :% d connected\n", iClientSocket);
        } 
        else 
        {
            PRINTAPI_msg("Maximum number of clients reached\n");
            pthread_mutex_unlock(&gClientMutex);
            goto END;
        }
        pthread_mutex_unlock(&gClientMutex);

        // creat pthread of client connect
        if (pthread_create(&tidClient, NULL, HandleClient, &iClientSocket) != 0) 
        {
            PRINTAPI_err("pthread_create");
            goto END;
        }
        pthread_detach(tidClient);
END:
    if(iClientSocket != -1)
    {
        close(iClientSocket);  
        iClientSocket = -1; 
    }
    continue;
    }

    if(giServerSocket != -1)
    {
        close(giServerSocket);  
        giServerSocket = -1; 
    }
    PRINTAPI_trc("out main API\n");
    return Success;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值