一个简单的C/S结构的通信类CServerSocket

 ServerSocket.h
#ifndef __SERVERSOCKET_H__
#define  __SERVERSOCKET_H__

//  #define WIN32_LEAN_AND_MEAN
#include  < windows.h >

#include 
" SocketManage.h "

#pragma  warning(disable:4786)
using   namespace  std;


#define  DEFAULT_PORT    6000
#define  LISTEN_NUM        20
#define  BUFFER_SIZE        32
#define  CLIENT_IP        50

/// class CServerSocket forward declaration
class  CServerSocket;

/// SInfo holds the data for thread parameter.
struct     tagSInfo 
{
    CServerSocket
* pThis;
    SOCKET    ClientSocket;
    
char    szMessage[BUFFER_SIZE];
    
char    szClientIP[CLIENT_IP];
}
;

class  CServerSocket
{
public:
    CServerSocket();
    
virtual    ~CServerSocket();
    
/// Start Server
    BOOL Start();
    
/// Stop Server
    void Stop();
    
/// pure virtual function for future's inheritance.
    virtual void OnMessage(LPSTR lpszIP, LPSTR lpszMessage) = 0;
    
/// Closing corresponding SOCKET's handle by its IP.
    void CloseSocketByIP(LPCSTR lpszIP);
    
/// Send a message to client.
    int SendMessageToClient(SOCKET hSocket, LPCSTR lpszMessage);
    
int SendMessageToClient(LPCSTR lpszIP, LPCSTR lpszMessage);
    
/// Send a message to all client.
    void SendMessageToAllClient(LPCSTR lpszMessage);
    
/// Send a message to all client except for lpszIP
    void SendMessageToAllClientExceptFor(LPCSTR lpszIP, LPCSTR lpszMessage);
    
    
/// recording SOCKET's status.
    enum State
    
{
        SOCK_ERR,
        SOCK_SUC
    }
;

private:
    
/// Initialize SOCKET environment.
    BOOL Initialization();
    
/// bind local with lPort
    SOCKET Bind(USHORT lPort = DEFAULT_PORT);
    
/// accept a client's request and obtain its IP address by lpszIP.
    SOCKET AcceptClient(SOCKET sListen, LPSTR lpszIP);
    
/// Worker Thraed that processing client's request.
    static UINT __stdcall WorkThread(LPVOID pParam);
    
protected:
    CSocketManage    ClientManage;
//! CSocketManage manages SOCKET and its IP address

private:
    
char szClientIP[50];
    
    CRITICAL_SECTION cs;
//! Critical_Section
}
;

#endif

 ServerSocket.cpp 

#include  " ServerSocket.h "
#include 
< process.h >
#include 
< stdio.h >
//  #include <WINSOCK2.H>

#pragma  comment(lib, "WS2_32")

/// Constructor
CServerSocket::CServerSocket()
{
    
/// Initialize Critical Section
    InitializeCriticalSection(&cs);
}


/// Destructor
CServerSocket::     ~ CServerSocket()
{
    
/// Delete Critical Section
    DeleteCriticalSection(&cs);
    
/// Cleanup
    Stop();
}


/// Initialize SOCKET environment.
BOOL CServerSocket::Initialization()
{
    WSADATA wsd;
    
/// Startup SOCKET library
    if( WSAStartup(MAKEWORD(22), &wsd) != 0)    //! if failed, return FALSE
    {
        
return FALSE;
    }


    
return TRUE;
}


/// Startup server
BOOL CServerSocket::Start()
{
    
/// Initialize environment.
    if (Initialization() == FALSE)
    
{
        
return FALSE;
    }


    
/// bind
    SOCKET sockListen;
    
if ((sockListen = Bind(DEFAULT_PORT)) == NULL)
    
{
        
return FALSE;
    }


    
/// listen to client's request
    while (TRUE)
    
{
        SOCKET sockClient 
= NULL;
        
while(sockClient == NULL)
        
{
            sockClient 
= AcceptClient(sockListen, szClientIP);
        }


        
/// Insert Client's SOCKET and its IP address to ClientManage.
        ClientManage.AddIPToSocket(sockClient, szClientIP);

        
/// alloc a memory for struct SInfo in heap, release it in WorkThread()
         struct tagSInfo *SOCKINFO = new struct tagSInfo;

        SOCKINFO
->pThis = this;
        SOCKINFO
->ClientSocket = sockClient;
        strcpy(SOCKINFO
->szClientIP, szClientIP);
        memset(SOCKINFO
->szMessage, 0, BUFFER_SIZE);

        
/// Startup a thread , use SOCKINFO as its parameter.
        _beginthreadex(NULL, 0, WorkThread, (LPVOID)SOCKINFO, 0, NULL);
    }


    
return TRUE;
}


/// Startup a thread , use the SOCKINFO as its parameter.
UINT CServerSocket::WorkThread(LPVOID pParam)
{
    
struct tagSInfo Param;
    
/// obtaining SOCKINFO
    struct tagSInfo *lpParam = (struct tagSInfo*)pParam;

    Param.ClientSocket 
= lpParam->ClientSocket;
    Param.pThis 
= lpParam->pThis;
    strcpy(Param.szClientIP, lpParam
->szClientIP);    
    strcpy(Param.szMessage, lpParam
->szMessage);

    delete lpParam;    
//! release memory allocating in heap.
    
    
char recvbuf[BUFFER_SIZE];
    
    State    valState;

    
/// Receiving message from client and pass it to virtual function OnMessage()
    while (TRUE)
    
{
        
int nLeftToRecv = BUFFER_SIZE;
        
*recvbuf = 0;
        
        
/// do...while loop receives message until received it completely.
        do
        
{
            
char *pLeftBuf = (char *)( recvbuf + (BUFFER_SIZE - nLeftToRecv) );
            
            
int nRecvBytes = recv(Param.ClientSocket, pLeftBuf, nLeftToRecv, 0);
            
            
if(nRecvBytes == SOCKET_ERROR)
            
{
                valState 
= SOCK_ERR;
                
break;
            }

            
            nLeftToRecv 
-= nRecvBytes;
        }
 while(nLeftToRecv > 0);
        
        
/// if has no errors in receiving progress, pass message to OnMessage().
        if (valState != SOCK_ERR)
        
{
            Param.pThis
->OnMessage(Param.szClientIP, recvbuf);
        }

    }


    
return 1;
}


/// bind local with lPort
SOCKET CServerSocket::Bind(USHORT lPort)
{
    
/// creating a socket in tcp/ip protocol.
    SOCKET sServer = socket(AF_INET, SOCK_STREAM, 0);
    
    
/// initializing socket struct.
    struct sockaddr_in servAddr;
    servAddr.sin_family 
= AF_INET;
    servAddr.sin_port 
= htons(lPort);
     servAddr.sin_addr.s_addr 
= htonl(INADDR_ANY);

    
/// call socket api to bind
    if(bind(sServer, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0)
    
{
        
return NULL;
    }

    
    
/// set SOCKET sServer to listening mode,and listen LISTEN_NUM at one time.
    if(listen(sServer, LISTEN_NUM) != 0)
    
{
        
return NULL;
    }


    
return sServer;
}


/// accept a client's request and obtain its IP address by lpszIP.
SOCKET CServerSocket::AcceptClient(SOCKET sListen, LPSTR lpszIP)
{
    
struct sockaddr_in cliAddrTmp;

    
int cliAddrSize = sizeof(struct sockaddr_in);
    SOCKET sClient 
= accept(sListen, (struct sockaddr *)&cliAddrTmp, &cliAddrSize);

    
if(sClient == INVALID_SOCKET)
    
{
        
return NULL;
    }


    EnterCriticalSection(
&cs);

    sprintf(lpszIP, 
"%s", inet_ntoa(cliAddrTmp.sin_addr));

    LeaveCriticalSection(
&cs);
    
    
return sClient;    
}


/// Stop Server
void  CServerSocket::Stop()
{
    ClientManage.CloseAllSocket();
    WSACleanup();
}


/// close a socket by ip address.
void  CServerSocket::CloseSocketByIP(LPCSTR lpszIP)
{
    
if (lpszIP == NULL)
    
{
        
return;
    }


    SOCKET    sSocket 
= ClientManage.GetSocketByIP(lpszIP);
    
    
if (sSocket != NULL)
    
{
        closesocket(sSocket);
        ClientManage.DeleteIPSocket(lpszIP);
    }

}


/// Send a message to client.
int  CServerSocket::SendMessageToClient(SOCKET hSocket, LPCSTR lpszMessage)
{
     
int iResult = send(hSocket, lpszMessage, BUFFER_SIZE, 0);

    
return iResult;
}


/// Send a message to client.
int  CServerSocket::SendMessageToClient(LPCSTR lpszIP, LPCSTR lpszMessage)
{
    
int iResult;

    SOCKET hSocket 
= ClientManage.GetSocketByIP(lpszIP);

    iResult 
= send(hSocket, lpszMessage, BUFFER_SIZE, 0);

    
return iResult;
}


/// Send a message to all client.
void  CServerSocket::SendMessageToAllClient(LPCSTR lpszMessage)
{
    std::list
<std::string> lstIP;
    std::list
<std::string>::iterator iter;

    ClientManage.GetAllClientIP(lstIP);
    
for (iter = lstIP.begin(); iter != lstIP.end(); ++iter)
    
{
        
string IP = *iter;
        SOCKET hSocket 
= ClientManage.GetSocketByIP(IP.c_str());

        send(hSocket, lpszMessage, strlen(lpszMessage), 
0);
    }

}


/// Send a message to all client except for lpszIP
void  CServerSocket::SendMessageToAllClientExceptFor(LPCSTR lpszIP, LPCSTR lpszMessage)
{
    std::list
<std::string> lstIP;
    std::list
<std::string>::iterator iter;
    
    ClientManage.GetAllClientIP(lstIP);
    
for (iter = lstIP.begin(); iter != lstIP.end(); ++iter)
    
{
        
string IP = *iter;
        
/// except for lpszIP
        if (strcmp(IP.c_str(), lpszIP) == 0)
        
{
            
continue;
        }


        SOCKET hSocket 
= ClientManage.GetSocketByIP(IP.c_str());
        

        send(hSocket, lpszMessage, strlen(lpszMessage), 
0);
    }
    
}

 

 SocketManage.h

#ifndef __SOCKETMANAGE_H__
#define  __SOCKETMANAGE_H__

#pragma  warning(disable:4786)
#pragma  warning(disable:4503)
#include 
< vector >
#include 
< list >
#include 
< map >
#include 
< string >
#include 
< algorithm >

class  CSocketManage
{
public:
    
/// Constructor
    CSocketManage();
    
/// Destructor
    virtual ~CSocketManage();

    
/// return all client's IP address by list<>
    void GetAllClientIP(std::list<std::string> & list);

    
/// return client's number
    LONG GetSocketCount() const;

    
/// insert a client to CSocketManage
    void AddIPToSocket(SOCKET hSocket, LPCSTR lpszIP);

    
/// remove a client from CSocketManage
    void DeleteIPSocket(LPCSTR lpszIP);    

    
/// get socket by ip address
    SOCKET    GetSocketByIP(LPCSTR lpszIP);

    
/// close all socket connection.
    void CloseAllSocket();
    
private:
    std::map
< std::string, std::vector<std::string> > m_mapClientToMessage;

    std::map
< std::string,SOCKET > m_mapIPToSocket;
}
;

#endif   // __SOCKETMANAGE_H__

 

 SocketManage.cpp

 

#include  " stdafx.h "
#include 
" SocketManage.h "
#include 
< assert.h >

CSocketManage::CSocketManage()
{
    m_mapIPToSocket.clear();
}


CSocketManage:: 
~ CSocketManage()
{

}


void  CSocketManage::GetAllClientIP(std::list < std:: string >   &  listIP)
{
    
/// iterator's statement
    std::map< std::string,SOCKET >::iterator iter;

    
for (iter = m_mapIPToSocket.begin();iter != m_mapIPToSocket.end();++iter)
    
{
        listIP.push_back(iter
->first);
    }

}


LONG CSocketManage::GetSocketCount() 
const
{
    
return m_mapIPToSocket.size();
}


void  CSocketManage::AddIPToSocket(SOCKET hSocket, LPCSTR lpszIP)
{
    m_mapIPToSocket.insert(std::make_pair(lpszIP, hSocket));
    CString str;
    str.Format(
"%d",m_mapIPToSocket.size());
    AfxMessageBox(str);
}


void  CSocketManage::DeleteIPSocket(LPCSTR lpszIP)
{
    std::map
< std::string,SOCKET >::iterator iter;

    
for (iter = m_mapIPToSocket.begin();iter != m_mapIPToSocket.end();++iter)
    
{
        
/// if found out target IP,then break
        if(strcmp(iter->first.c_str(), lpszIP) == 0)
        
{
            
break;
        }

    }


    
/// remove it from CSocketManage
    m_mapIPToSocket.erase(iter);
}


SOCKET CSocketManage::GetSocketByIP(LPCSTR lpszIP)
{
    
if (lpszIP == NULL)
    
{
        
return NULL;
    }


    std::map
< std::string,SOCKET >::iterator iter;

    
for (iter = m_mapIPToSocket.begin();iter != m_mapIPToSocket.end();++iter)
    
{
        
if(strcmp(iter->first.c_str(), lpszIP) == 0)
        
{
            
break;
        }

    }


    
return iter->second;
}


/// close all client's socket.
void  CSocketManage::CloseAllSocket()
{
    std::map
< std::string,SOCKET >::iterator iter;
    
    
for (iter = m_mapIPToSocket.begin();iter != m_mapIPToSocket.end();++iter)
    
{
        closesocket(iter
->second);
    }

}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
是的,CServerSocket可以用于监听连接请求。CServerSocket是用于创建服务器端套接字的,它可以监听指定的端口,等待客户端的连接请求。一旦有客户端发起连接请求,CServerSocket就可以接受该连接,并创建一个新的CSocket对象来与客户端进行通信。 要使用CServerSocket进行监听,您可以按照以下步骤进行操作: 1. 创建一个CServerSocket对象。 2. 调用CServerSocket的Create函数来创建服务器套接字,并指定要监听的端口号。 3. 调用CServerSocket的Listen函数来开始监听连接请求。 4. 使用accept函数接受客户端的连接请求,并创建一个新的CSocket对象来与客户端进行通信。 以下是一个简单的示例代码,演示了如何使用CServerSocket进行监听: ```cpp // 创建并初始化CServerSocket对象 CServerSocket serverSocket; serverSocket.Create(12345); // 监听端口号为12345 // 开始监听连接请求 serverSocket.Listen(); while (true) { // 接受客户端连接请求 CSocket clientSocket; if (serverSocket.Accept(clientSocket)) { // 客户端连接成功,可以与客户端进行通信 // 处理客户端请求... } } // 关闭服务器套接字 serverSocket.Close(); ``` 请注意,上述代码只是一个简单示例,实际使用时可能需要进行错误处理和更全面的逻辑。同时,为了使代码更健壮,您可能需要在单独的线程中执行accept函数,以便能够同时处理多个客户端连接请求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值