⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpserver.cpp

📁 TCP的服务器与客户端基类
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    }

    return ret;
}
#endif

/*
 ****************************************************************************
 *                                                                          *
 *  Function Name : Write()                                                 *
 *  Description   : To send a content buffer.                               *
 *  Parameter(s)  : @fd  : The associated socket.                           *
 *                  @buf : A pointer to which the content is stored.        *
 *                  @len : The length of the buffer.                        *
 *  Return        : @>0  : The bytes of send is returned.                   *
 *                  @-1  : Failure.                                         *
 *                                                                          *
 ****************************************************************************
 */

#ifdef __linux
__int32_t CTcpServer::Write(int fd, void *buf, __u_int len)
{
    __int32_t ret = 0;

    ret = send(fd, buf, len, 0);
    if (ret < 0)
    {
        DBG("CTcpServer::Write() send error!\n");
	return -1;
    }

    return ret;
}
#endif

/*
 ****************************************************************************
 *                                                                          *
 *  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 shut down.                     *
 *                  @-1  : Failure.                                         * 
 *                                                                          *
 ****************************************************************************
 */

#ifdef WIN32
__int32_t CTcpServer::Read(SOCKET fd, void *buf, __u_int len)
{
    __int32_t ret = 0;

    ret = recv(fd, reinterpret_cast<char *>(buf), len, 0);
    if (ret == SOCKET_ERROR)
    {
        DBG("CTcpServer::Read() receive error!\n");
	return -1;
    }

    return ret;
}
#endif

/*
 ****************************************************************************
 *                                                                          *
 *  Function Name : Write()                                                 *
 *  Description   : To send a content buffer.                               *
 *  Parameter(s)  : @fd  : The associated socket.                           *
 *                  @buf : A pointer to which the content is stored.        *
 *                  @len : The length of the buffer.                        *
 *  Return        : @>0  : The bytes of send is returned.                   *
 *                  @-1  : Failure.                                         *
 *                                                                          *
 ****************************************************************************
 */

#ifdef WIN32
__int32_t CTcpServer::Write(SOCKET fd, void *buf, __u_int len)
{
    __int32_t ret = 0;

    ret = send(fd, reinterpret_cast<char *>(buf), len, 0);
    if (ret == SOCKET_ERROR)
    {
        DBG("CTcpServer::Write() send buffer error!\n");
	return -1;
    }

    return ret;
}
#endif

/*
 ****************************************************************************
 *                                                                          *
 *  Function Name : Init()                                                  *
 *  Description   : To initialize the tcp server for listening.             *
 *  Parameter(s)  : None.                                                   *
 *  Return        : @ 0 : success.                                          *
 *                  @-1 : failure.                                          *
 *                                                                          *
 ****************************************************************************
 */

int CTcpServer::Init(void)
{
    int  ret = 0;

    #ifdef WIN32
    WinVersion = MAKEWORD(2, 2);
    if (WSAStartup(WinVersion, &wsa) < 0)
    {
        DBG("TcpServer::Init() WSAStartup failure!\n");
	return -1;
    }
    #endif

    sock = socket(AF_INET, SOCK_STREAM, 0);
    #ifdef __linux
    if (sock < 0)
    #else
    if (sock == INVALID_SOCKET)
    #endif
    {
        DBG("TcpServer::Init() create socket error!\n");
        return -1;
    }

    int on = 1;
    #ifdef __linux
    ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    if (ret < 0)
    #else
    ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, \
    		reinterpret_cast<const char *>(&on), sizeof(on));
    if (ret == SOCKET_ERROR)
    #endif
    {
        DBG("TcpServer::Init() setsockopt() error!\n");
	return -1;
    }
    
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    
    addr.sin_family = AF_INET;
    addr.sin_port   = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;

    ret = bind(sock, (struct sockaddr *)(&addr), sizeof(addr));
    #ifdef __linux
    if (ret < 0)
    #else
    if (ret == SOCKET_ERROR)
    #endif
    {
        DBG("TcpServer::Init() bind error!\n");
	return -1;
    }

    ret = listen(sock, 10);
    #ifdef __linux
    if (ret < 0)
    #else
    if (ret == SOCKET_ERROR)
    #endif
    {
        DBG("TcpServer::Init() listen error!\n");
	return -1;
    }

    return ret;
}

/*
 ****************************************************************************
 *                                                                          *
 *  Function Name : WorkerThread()                                          *
 *  Description   : The worker thread begin to carry out the task by calling*
 *                  the virtual function which will be implemented by the   *
 *                  derived class.                                          *
 *  Parameter(s)  : @ A pointer to a struct of ThreadPack.                  *
 *  Return        : NULL pointer.                                           *
 *                                                                          *
 ****************************************************************************
 */

#ifdef __linux
void* CTcpServer::WorkerThread(void *arg)
{
    pthread_detach(pthread_self());

    ThreadPack *pArg = reinterpret_cast<ThreadPack *>(arg);
    CTcpServer *pServer = reinterpret_cast<CTcpServer *>(pArg->obj);
    int fd = pArg->pt;
    struct sockaddr_in peer = pArg->addr;

    pServer->Engine(fd, peer);

    free(pArg);
    return NULL;
}
#endif

#ifdef WIN32
DWORD CTcpServer::WorkerThread(LPVOID arg)
{
    ThreadPack *pArg = reinterpret_cast<ThreadPack *>(arg);
    CTcpServer *pServer = reinterpret_cast<CTcpServer *>(pArg->obj);
    SOCKET fd = pArg->pt;
    struct sockaddr_in peer = pArg->addr;

    pServer->Engine(fd, peer);

    free(pArg);
    return 0;
}
#endif

/*
 ****************************************************************************
 *                                                                          *
 *  Function Name : ListenThread()                                          *
 *  Description   : To listen the public service port and then deliver it to*
 *                  the worker thread.                                      *
 *  Parameter(s)  : @ arg : A pointer to the object of TcpServer.           *
 *  Return        : NULL pointer.                                           *
 *                                                                          *
 ****************************************************************************
 */

#ifdef __linux
void* CTcpServer::ListenThread(void *arg)
{
    CTcpServer *pServer = reinterpret_cast<CTcpServer *>(arg);

    int    ret = 0;
    fd_set read_set;
    struct timeval tv;
    memset(&tv, 0, sizeof(tv));

    tv.tv_sec  = WAIT_TIME;
    tv.tv_usec = 0; 
    while (!pServer->over)
    {
        struct sockaddr_in peer;
	int    len = sizeof(peer);
        
	FD_ZERO(&read_set);
	FD_SET(pServer->sock, &read_set);

	ret = select(pServer->sock + 1, &read_set, NULL, NULL, &tv);
	if (ret < 0)
	{
	    DBG("CTcpServer::ListenThread select() error!\n");
	    continue;
	}
	if (ret == 0)
	{   /* need to check the flag of over */
	    continue;
	}
	
        int fd = accept(pServer->sock, (struct sockaddr *)(&peer), \
			(socklen_t *)(&len));
	if (fd < 0)
	{
	    DBG("CTcpServer::ListenThread() accept error\n");
	    DBG("Continue to listen!\n");
	    continue;
	}

        ThreadPack *pTmp = (ThreadPack *)malloc(sizeof(ThreadPack));
	pTmp->obj = arg;
	pTmp->pt  = fd;
	memmove(&(pTmp->addr), &peer, sizeof(peer));

	pthread_t self;
	pthread_create(&self, NULL, WorkerThread, \
			reinterpret_cast<void *>(pTmp));
    }

    return NULL;
}
#endif

#ifdef WIN32
DWORD CTcpServer::ListenThread(LPVOID arg)
{
    CTcpServer *pServer = reinterpret_cast<CTcpServer *>(arg);

    int    ret = 0;
    fd_set read_set;
    struct timeval tv;
    memset(&tv, 0, sizeof(tv));

    tv.tv_sec  = WAIT_TIME;
    tv.tv_usec = 0;

    while (!pServer->over)
    {
        struct sockaddr_in peer;
	int    len = sizeof(peer);

	FD_ZERO(&read_set);
	FD_SET(pServer->sock, &read_set);

	ret = select(0, &read_set, NULL, NULL, &tv);
	if (ret == SOCKET_ERROR)
	{
	    DBG("CTcpServer:;ListenThread() select error!\n");
	    continue;
	}
	if (ret == 0)
	{   /* need to check the flag of over */
	    continue;
	}
	
        SOCKET fd = accept(pServer->sock, (struct sockaddr *)(&peer), &len);
	if (fd == INVALID_SOCKET)
	{
	    DBG("CTcpServer::ListenThread() accept error\n");
	    DBG("Continue to listen!\n");
	    continue;
	}

	ThreadPack *pTmp = (ThreadPack *)malloc(sizeof(ThreadPack));
	pTmp->obj = arg;
	pTmp->pt  = fd;
	memmove(&(pTmp->addr), &peer, sizeof(peer));

	HANDLE hdl;
	DWORD  self;
	hdl = CreateThread(NULL, 0, WorkerThread, \
			reinterpret_cast<LPVOID>(pTmp), 0, &self);
        if (hdl)
	{
	    DBG("CTcpServer::ListenThread() Create worker thread success!\n");
	}
	else 
	{
	    DBG("CTcpServer::ListenThread() Fail to create worker thread!\n");
	}
    }

    return 0;
}
#endif

/* The end */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -