📄 tcpserver.cpp
字号:
#include "TcpServer.h"
/*
****************************************************************************
* CLASS IMPLEMENTATION *
****************************************************************************
*/
/* For CTcpServer */
/*
****************************************************************************
* *
* Function Name : CTcpServer() *
* Description : The construction function. *
* Parameter(s) : @pt : the public service port. *
* Return : None. *
* *
****************************************************************************
*/
CTcpServer::CTcpServer(short pt) : port(pt), over(false)
{
#ifdef __linux
sock = 0;
listen_thread = 0;
#endif
#ifdef WIN32
listen_thread = NULL;
#endif
}
/*
****************************************************************************
* *
* Function Name : ~CTcpServer() *
* Description : The deconstruction function. *
* Parameter(s) : None. *
* Return : None. *
* *
****************************************************************************
*/
CTcpServer::~CTcpServer(void)
{
this->over = true;
#ifdef __linux
if (listen_thread != 0)
{
pthread_join(listen_thread, NULL);
}
if (sock > 0)
{
close(sock);
}
#endif
#ifdef WIN32
if (listen_thread)
{
WaitForSingleObject(listen_thread, INFINITE);
CloseHandle(listen_thread);
listen_thread = NULL;
}
closesocket(sock);
WSACleanup();
#endif
}
/*
****************************************************************************
* *
* Function Name : NonBlockStart() *
* Description : To start the TCP server and create a new thread to *
* watch the public socket. *
* Parameter(s) : None. *
* Return : @ 0 : success. *
* @-1 : failure. *
* *
****************************************************************************
*/
int CTcpServer::NonBlockStart(void)
{
int ret = 0;
ret = Init();
if (ret < 0)
{
DBG("TcpServer::NonBlockStart() Init error!\n");
return ret;
}
#ifdef __linux
ret = pthread_create(&listen_thread, NULL, ListenThread, \
reinterpret_cast<void *>(this));
#endif
#ifdef WIN32
DWORD self;
listen_thread = CreateThread(NULL, 0, ListenThread, \
reinterpret_cast<LPVOID>(this), 0, &self);
if (listen_thread)
{
DBG("CTcpServer::NonBlockStart() Create listening thread success!\n");
}
else
{
DBG("CTcpServer::NonBlockStart() Create thread failed!\n");
ret = -1;
}
#endif
return ret;
}
/*
****************************************************************************
* *
* Function Name : BlockStart() *
* Description : To start the TCP server, there is no thread would be *
* created to listen the public port. Instead, the main *
* thread will do it by itself. *
* Parameter(s) : None. *
* Return : @ 0 : success. *
* @-1 : failure. *
* *
****************************************************************************
*/
int CTcpServer::BlockStart(void)
{
int ret = 0;
ret = Init();
if (ret < 0)
{
DBG("CTcpServer::BlockStart() Init error!\n");
return ret;
}
fd_set read_set;
struct timeval tv;
memset(&tv, 0, sizeof(tv));
tv.tv_sec = WAIT_TIME;
tv.tv_usec = 0;
while (!over)
{
struct sockaddr_in peer;
int len = sizeof(peer);
#ifdef __linux
FD_ZERO(&read_set);
FD_SET(sock, &read_set);
ret = select(sock + 1, &read_set, NULL, NULL, &tv);
if (ret < 0)
{
DBG("CTcpServer::BlockStart select() error!\n");
continue;
}
if (ret == 0)
{ /* need to check the flag of over */
continue;
}
int fd = accept(sock, (struct sockaddr *)(&peer), \
(socklen_t *)(&len));
if (fd < 0)
{
DBG("CTcpServer::BlockStart() accept error!\n");
DBG("Continue to listen!\n");
continue;
}
ThreadPack *pTem = (ThreadPack *)malloc(sizeof(ThreadPack));
pTem->obj = this;
pTem->pt = fd;
memmove(&(pTem->addr), &peer, sizeof(peer));
pthread_t self;
pthread_create(&self, NULL, WorkerThread, \
reinterpret_cast<void *>(pTem));
#endif
#ifdef WIN32
FD_ZERO(&read_set);
FD_SET(sock, &read_set);
ret = select(0, &read_set, NULL, NULL, &tv);
if (ret == SOCKET_ERROR)
{
DBG("CTcpServer::BlockStart select() error!\n");
continue;
}
if (ret == 0)
{ /* need to check the flag of over */
continue;
}
SOCKET fd = accept(sock, (struct sockaddr *)(&peer), &len);
if (fd == INVALID_SOCKET)
{
DBG("CTcpServer::BlockStart() accept() error!\n");
DBG("Continue to listen!\n");
continue;
}
ThreadPack *pTem = (ThreadPack *)malloc(sizeof(ThreadPack));
pTem->obj = this;
pTem->pt = fd;
memmove(&(pTem->addr), &peer, sizeof(peer));
HANDLE hdl;
DWORD self;
hdl = CreateThread(NULL, 0, WorkerThread, \
reinterpret_cast<LPVOID>(pTem), 0, &self);
if (hdl)
{
DBG("CTcpServer::BlockStart() Create worker thread success!\n");
}
else
{
DBG("CTcpServer::BlockStart() Fail to create worker thread!\n");
}
#endif
}
return ret;
}
/*
****************************************************************************
* *
* Function Name : Stop() *
* Description : To stop the listening service. *
* Parameter(s) : None. *
* Return : @ 0 : success. *
* *
****************************************************************************
*/
int CTcpServer::Stop(void)
{
this->over = true;
#ifdef __linux
if (listen_thread != 0)
{
pthread_join(listen_thread, NULL);
listen_thread = 0;
}
if (sock > 0)
{
close(sock);
sock = 0;
}
#endif
#ifdef WIN32
if (listen_thread)
{
WaitForSingleObject(listen_thread, INFINITE);
CloseHandle(listen_thread);
listen_thread = NULL;
}
closesocket(sock);
WSACleanup();
#endif
this->over = false;
return 0;
}
/*
****************************************************************************
* *
* Function Name : ReStart() *
* Description : To restart the TCP server. *
* Parameter(s) : *
* Return : *
* *
****************************************************************************
*/
int CTcpServer::ReStart(void)
{
Stop();
return this->NonBlockStart();
}
/*
****************************************************************************
* *
* Function Name : SetPort() *
* Description : To set the port number. *
* Parameter(s) : @pt : the desired port number. *
* Return : None. *
* *
****************************************************************************
*/
void CTcpServer::SetPort(short pt)
{
port = pt;
return ;
}
/*
****************************************************************************
* *
* Function Name : GetPort() *
* Description : To get the port number. *
* Parameter(s) : @pt : a reference which receives the port number. *
* Return : None. *
* *
****************************************************************************
*/
void CTcpServer::GetPort(short &pt)
{
pt = port;
return ;
}
/*
****************************************************************************
* *
* Function Name : Read() *
* Description : To receive a content buffer from a socket. *
* Parameter(s) : @fd : The associated socket. *
* @buf : A pointer to which the content will be stored. *
* @len : The length of the buffer. *
* Return : @>0 : The bytes of read is returned. *
* @ 0 : The peer has been shutdown. *
* @-1 : Failure. *
* *
****************************************************************************
*/
#ifdef __linux
__int32_t CTcpServer::Read(int fd, void *buf, __u_int len)
{
__int32_t ret = 0;
ret = recv(fd, buf, len, 0);
if (ret < 0)
{
DBG("CTcpServer::Read() receive error!\n");
return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -