一个worker thread服务一个客户端

服务器端对一个客户端来了就开启一个工作线程,最多可接受64个。

具体看代码:

#pragma once
#include <winsock.h>
#include <stdio.h>

#pragma comment(lib, "ws2_32.lib")

#define MaxClient 64

class MyTCPSocket
{
public:
    MyTCPSocket(void);
    ~MyTCPSocket(void);
    bool Init();
    bool UnInit();
    bool CreateSocket();
    bool Bind(unsigned aPost,const char* aAdress);
    bool Listen(int aBacklog=5);
    bool Connect(unsigned aPost,const char* aAdress);
    bool Send(const char* aBuf);
    bool Recv();
    void Accept();
    static DWORD WINAPI WorkerFun(PVOID aData);

public:
    SOCKET m_ClientSocket[MaxClient];

private:
    SOCKET m_Socket;

    sockaddr_in m_SockClientaddrIn ;
    HANDLE m_ClientHandle[MaxClient];
    CRITICAL_SECTION m_CriticalSection;
    DWORD m_Thread[MaxClient];
    int m_TotClient;
};
#include "MyTCPSocket.h"

struct Para
{
    MyTCPSocket* m_pMyTCPSocket;
    SOCKET m_CurSocket;
};

MyTCPSocket::MyTCPSocket(void)
:m_Socket(INVALID_SOCKET)
, m_TotClient(-1)
{
    InitializeCriticalSection(&m_CriticalSection);
}

MyTCPSocket::~MyTCPSocket(void)
{
    EnterCriticalSection(&m_CriticalSection);
    for (int i =0; i < m_TotClient;++i)
    {
        if (NULL != m_ClientHandle[i])
        {
            CloseHandle(m_ClientHandle[i]);
        }
    }
    LeaveCriticalSection(&m_CriticalSection);

    DeleteCriticalSection(&m_CriticalSection);
}

bool MyTCPSocket::Init()
{
    int iResult;
    WORD wVersionRequested;
    WSADATA wsaData;

    wVersionRequested = MAKEWORD(2, 2);
    iResult = WSAStartup(wVersionRequested, &wsaData);
    if (iResult != 0) 
    {
        printf("WSAStartup failed with error: %d
", iResult);
        return false;
    } 
    else 
    {
        printf("WSAStartup succeeded!
");
        return true;
    }
}

bool MyTCPSocket::CreateSocket()
{
    m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (INVALID_SOCKET == m_Socket)
    {
        printf("INVALID_SOCKET
");
        return false;
    }
    printf("Create Socket(%d) successully.
",m_Socket);
    BOOL reuseaddr=TRUE;
    setsockopt(m_Socket,SOL_SOCKET,SO_REUSEADDR,(const char*)&reuseaddr,sizeof(reuseaddr));
    return true;
}

bool MyTCPSocket::Bind(unsigned aPost,const char* aAdress)
{
    struct sockaddr_in server_addr;    // server address information
    server_addr.sin_family = AF_INET;         // host byte order
    server_addr.sin_port = htons(aPost);     // short, network byte order
    server_addr.sin_addr.s_addr = inet_addr(aAdress); // automatically fill with my IP
    memset(server_addr.sin_zero, '', sizeof(server_addr.sin_zero));
    if (-1 == bind(m_Socket,(struct sockaddr *)&server_addr,sizeof(server_addr)))
    {
        printf("Bind Error.
");
        return false;
    }

    int nRecvBuf = 32 * 1024; //设置为32K
    if (setsockopt(m_Socket,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }
    return true;
}

bool MyTCPSocket::Connect( unsigned aPost,const char* aAdress )
{
    sockaddr_in lsockaddr_in;
    lsockaddr_in.sin_family = AF_INET;
    lsockaddr_in.sin_port = htons(aPost);
    lsockaddr_in.sin_addr.s_addr = inet_addr(aAdress);

    if (-1 == connect(m_Socket,(struct sockaddr *)&lsockaddr_in,sizeof(lsockaddr_in)))
    {
        printf("Conenct Error.
");
        return false;
    }
    return true;
}

bool MyTCPSocket::Listen( int aBacklog/*=5*/ )
{
    if (-1 == listen(m_Socket,aBacklog))
    {
        printf("Listen Error.
");
        return false;
    }
    return true;
}

bool MyTCPSocket::Send( const char* aBuf)
{
    if (-1 == send(m_Socket,aBuf,strlen(aBuf)+1,0))
    {
        printf("Send Error.
");
        return false;
    }
    return true;
}

bool MyTCPSocket::Recv()
{
    //char lBuf[2048];
    //int lLength = 0;
    //lLength = recv(m_ClientSocket,lBuf,sizeof(lBuf),0);
    //if (SOCKET_ERROR == lLength || 0 == lLength)
    //{
    //    closesocket(m_ClientSocket);
    //    return false;
    //}
    //int lBegin = 0;
    //int lEnd = 0;
    //for (;lEnd < lLength;++lEnd)
    //{
    //    if ('' == lBuf[lEnd])
    //    {
    //        char lData[1024];
    //        int lLen = lEnd-lBegin;
    //        memcpy(lData,lBuf+lBegin,lLen+1);
    //        printf("We successfully received %d byte: %s.
", lLen, lData);
    //        lBegin = lEnd+1;
    //    }
    //}
    //if (lEnd < lLength)
    //{
    //    char lData[1024];
    //    memcpy(lData,lBuf+lBegin,lEnd-lBegin);
    //    lData[lEnd] = '';
    //    printf("We successfully received %d byte: %s.
", lData);
    //}
    //return true;
    return true;
}

bool MyTCPSocket::UnInit()
{
    if (-1 == closesocket(m_Socket))
    {
        printf("Close Socket Error.
");
        return false;
    }
    printf("Close Socket(%d).
",m_Socket);
    return true;
}

void MyTCPSocket::Accept()
{
    while(true)
    {
        int lAddrLen = sizeof(m_SockClientaddrIn);

        if (m_TotClient == MaxClient-1)
        {
            printf("Exceed max clients.
");
            break;
        }

        EnterCriticalSection(&m_CriticalSection);
        m_ClientSocket[++m_TotClient] = accept(m_Socket, (sockaddr*)&m_SockClientaddrIn,&lAddrLen);
        
        Para* lpPara = new Para;
        lpPara->m_pMyTCPSocket = this;
        lpPara->m_CurSocket = m_ClientSocket[m_TotClient];
        LeaveCriticalSection(&m_CriticalSection);

        printf("We successfully got a connection from %s:%d.
",
            inet_ntoa(m_SockClientaddrIn.sin_addr), ntohs(m_SockClientaddrIn.sin_port));

        m_ClientHandle[m_TotClient] = ::CreateThread(NULL, 0, WorkerFun,PVOID(lpPara), 0, &m_Thread[m_TotClient]);

        printf("Create WorkThread(%x) success.
",m_Thread[m_TotClient]);
    }
}

DWORD WINAPI MyTCPSocket::WorkerFun( PVOID aData )
{
    if (NULL == aData)
    {
        printf("Exit Thread.
");
        return 0;
    }

    Para* lpPara = (Para*)(aData);
    MyTCPSocket* lTCPSocket = lpPara->m_pMyTCPSocket;

    if (lpPara->m_CurSocket == INVALID_SOCKET)
    {
        return 0;
    }
    
    while(true)
    {
        char lBuf[2048];
        int lLength = 0;
        lLength = recv(lpPara->m_CurSocket,lBuf,sizeof(lBuf),0);
        if (SOCKET_ERROR == lLength || 0 == lLength)
        {
            closesocket(lpPara->m_CurSocket);
            delete lpPara;
            printf("Exit Thread.
");
            return 0;
        }
        int lBegin = 0;
        int lEnd = 0;
        for (;lEnd < lLength;++lEnd)
        {
            if ('' == lBuf[lEnd])
            {
                char lData[1024];
                int lLen = lEnd-lBegin;
                memcpy(lData,lBuf+lBegin,lLen+1);
                printf("We successfully received %d byte: %s.
", lLen, lData);
                lBegin = lEnd+1;
            }
        }
        if (lEnd < lLength)
        {
            char lData[1024];
            memcpy(lData,lBuf+lBegin,lEnd-lBegin);
            lData[lEnd] = '';
            printf("We successfully received %d byte: %s.
", lData);
        }
    }

    return 0;
}

表示是很简陋的写法,肯定还是有问题的,同步的地方没怎么想清楚,测试代码可以看上一篇的介绍,好吧,今天暂时先写到这里,尼玛,公司写神码软件申请书,搓的一逼。

原文地址:https://www.cnblogs.com/xiangshancuizhu/p/3324295.html