服务器端对一个客户端来了就开启一个工作线程,最多可接受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\n", iResult);
return false;
}
else
{
printf("WSAStartup succeeded!\n");
return true;
}
}

bool MyTCPSocket::CreateSocket()
{
m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == m_Socket)
{
printf("INVALID_SOCKET\n");
return false;
}
printf("Create Socket(%d) successully.\n",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, '\0', sizeof(server_addr.sin_zero));
if (-1 == bind(m_Socket,(struct sockaddr *)&server_addr,sizeof(server_addr)))
{
printf("Bind Error.\n");
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.\n");
return false;
}
return true;
}

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

bool MyTCPSocket::Send( const char* aBuf)
{
if (-1 == send(m_Socket,aBuf,strlen(aBuf)+1,0))
{
printf("Send Error.\n");
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 ('\0' == lBuf[lEnd])
// {
// char lData[1024];
// int lLen = lEnd-lBegin;
// memcpy(lData,lBuf+lBegin,lLen+1);
// printf("We successfully received %d byte: %s.\n", lLen, lData);
// lBegin = lEnd+1;
// }
//}
//if (lEnd < lLength)
//{
// char lData[1024];
// memcpy(lData,lBuf+lBegin,lEnd-lBegin);
// lData[lEnd] = '\0';
// printf("We successfully received %d byte: %s.\n", lData);
//}
//return true;
return true;
}

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

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

if (m_TotClient == MaxClient-1)
{
printf("Exceed max clients.\n");
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.\n",
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.\n",m_Thread[m_TotClient]);
}
}

DWORD WINAPI MyTCPSocket::WorkerFun( PVOID aData )
{
if (NULL == aData)
{
printf("Exit Thread.\n");
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.\n");
return 0;
}
int lBegin = 0;
int lEnd = 0;
for (;lEnd < lLength;++lEnd)
{
if ('\0' == lBuf[lEnd])
{
char lData[1024];
int lLen = lEnd-lBegin;
memcpy(lData,lBuf+lBegin,lLen+1);
printf("We successfully received %d byte: %s.\n", lLen, lData);
lBegin = lEnd+1;
}
}
if (lEnd < lLength)
{
char lData[1024];
memcpy(lData,lBuf+lBegin,lEnd-lBegin);
lData[lEnd] = '\0';
printf("We successfully received %d byte: %s.\n", lData);
}
}

return 0;
}


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