socket 客户端 服务器

    这里封装成三个类CBlockingSocketException, CBlockingSocket, CHttpBlockingSocket,将头文件blocksock.h、源文件blocksock.cpp包含到工程里面,使用的时候只需包含头文件blocksock.h即可,下面是服务器与客户端的两个线程。

完整工程源代码在这里:https://download.csdn.net/download/a2311minghan/10874288

服务器

UINT ServerThreadProc(LPVOID pParam)
{
    
    CBlockingSocket        sConnect;
    CSockAddr            saClient;
    CBlockingSocket        g_sListen;
    CSockAddr saServer;
    saServer = CSockAddr(INADDR_ANY, (USHORT)1999);
    g_sListen.Create();
    g_sListen.Bind(saServer);
    g_sListen.Listen();

    int            ret = 0;
    CsocketDlg *pDlg = (CsocketDlg *)pParam;
    unsigned char g_Buf1[1024] = { 0 };
    while (TRUE)
    {
        g_sListen.Accept(sConnect, saClient);
        ret = sConnect.Receive((char *)g_Buf1, 1024, 100);
        
        CString strTemp = _T("");
        strTemp.Format(_T("%s"), g_Buf1);
        pDlg->GetDlgItem(IDC_EDIT1)->SetWindowText(strTemp);
        sConnect.Close();
    }
    return 0;

}

客户端

UINT THEAD(LPVOID pParam)
{
    CsocktclientDlg *pDlg = (CsocktclientDlg*)pParam;
    CString strTemp = _T("000");
    CBlockingSocket sClient;
    CSockAddr saServer;
    saServer = CSockAddr("192.168.137.22", 1999);
    while (true)
    {
        if (strTemp == _T("000"))
        {
            strTemp = _T("111");
        }
        else
        {
            strTemp = _T("000");
        }
        sClient.Create();
        
        if (sClient.Connect(saServer)==-1)
        {
            sClient.Close();
            continue;
        }
        //先发位图压缩前后的数据的大小
        sClient.Write((const char *)strTemp.GetBuffer(), strTemp.GetLength()*sizeof(TCHAR), 10);
        sClient.Close();
        
    }
}

// blocksock.h

// needs winsock.h in the precompiled headers

typedef const struct sockaddr* LPCSOCKADDR;

class CBlockingSocketException : public CException
{
    DECLARE_DYNAMIC(CBlockingSocketException)
public:
// Constructor
    CBlockingSocketException(char* pchMessage);

public:
    ~CBlockingSocketException() {}
    virtual BOOL GetErrorMessage(LPTSTR lpstrError, UINT nMaxError,
        PUINT pnHelpContext = NULL);
private:
    int m_nError;
    CString m_strMessage;
};

extern void LogBlockingSocketException(LPVOID pParam, char* pch, CBlockingSocketException* pe);

class CSockAddr : public sockaddr_in {
public:
    // constructors
    CSockAddr()
        { sin_family = AF_INET;
          sin_port = 0;
          sin_addr.s_addr = 0; } // Default
    CSockAddr(const SOCKADDR& sa) { memcpy(this, &sa, sizeof(SOCKADDR)); }
    CSockAddr(const SOCKADDR_IN& sin) { memcpy(this, &sin, sizeof(SOCKADDR_IN)); }
    CSockAddr(const ULONG ulAddr, const USHORT ushPort = 0) // parms are host byte ordered
        { sin_family = AF_INET;
          sin_port = htons(ushPort);
          sin_addr.s_addr = htonl(ulAddr); }
    CSockAddr(const char* pchIP, const USHORT ushPort = 0) // dotted IP addr string
        { sin_family = AF_INET;
          sin_port = htons(ushPort);
          sin_addr.s_addr = inet_addr(pchIP); } // already network byte ordered
    // Return the address in dotted-decimal format
    /*CString DottedDecimal()
        { return inet_ntoa(sin_addr); }*/ // constructs a new CString object
    // Get port and address (even though they're public)
    USHORT Port() const
        { return ntohs(sin_port); }
    ULONG IPAddr() const
        { return ntohl(sin_addr.s_addr); }
    // operators added for efficiency
    const CSockAddr& operator=(const SOCKADDR& sa)
        { memcpy(this, &sa, sizeof(SOCKADDR));
          return *this; }
    const CSockAddr& operator=(const SOCKADDR_IN& sin)
        { memcpy(this, &sin, sizeof(SOCKADDR_IN));
          return *this; }
    operator SOCKADDR()
        { return *((LPSOCKADDR) this); }
    operator LPSOCKADDR()
        { return (LPSOCKADDR) this; }
    operator LPSOCKADDR_IN()
        { return (LPSOCKADDR_IN) this; }
};

// member functions truly block and must not be used in UI threads
// use this class as an alternative to the MFC CSocket class
class CBlockingSocket : public CObject
{
    DECLARE_DYNAMIC(CBlockingSocket)
public:
    SOCKET m_hSocket;
    CBlockingSocket() { m_hSocket = NULL; }
    void Cleanup();
    void Create(int nType = SOCK_STREAM);
    void Close();
    void Bind(LPCSOCKADDR psa);
    void Listen();
    int Connect(LPCSOCKADDR psa);
    BOOL Accept(CBlockingSocket& s, LPSOCKADDR psa);
    int Send(const char* pch, const int nSize, const int nSecs);
    int Write(const char* pch, const int nSize, const int nSecs);
    int Receive(char* pch, const int nSize, const int nSecs);
    int SendDatagram(const char* pch, const int nSize, LPCSOCKADDR psa,
        const int nSecs);
    int ReceiveDatagram(char* pch, const int nSize, LPSOCKADDR psa,
        const int nSecs);
    void GetPeerAddr(LPSOCKADDR psa);
    void GetSockAddr(LPSOCKADDR psa);
    static CSockAddr GetHostByName(const char* pchName,
        const USHORT ushPort = 0);
    static const char* GetHostByAddr(LPCSOCKADDR psa);
    operator SOCKET()
        { return m_hSocket; }
};

class CHttpBlockingSocket : public CBlockingSocket
{
public:
    DECLARE_DYNAMIC(CHttpBlockingSocket)
    enum {nSizeRecv = 1000}; // max receive buffer size (> hdr line length)
    CHttpBlockingSocket();
    ~CHttpBlockingSocket();
    int ReadHttpHeaderLine(char* pch, const int nSize, const int nSecs);
    int ReadHttpResponse(char* pch, const int nSize, const int nSecs);
private:
    char* m_pReadBuf; // read buffer
    int m_nReadBuf; // number of bytes in the read buffer
};

 

// blocksock.cpp (CBlockingSocketException, CBlockingSocket, CHttpBlockingSocket)


#include "stdafx.h"
#include "blocksock.h"

// Class CBlockingSocketException
IMPLEMENT_DYNAMIC(CBlockingSocketException, CException)

CBlockingSocketException::CBlockingSocketException(char* pchMessage)
{
    /*m_strMessage = pchMessage;
    m_nError = WSAGetLastError();*/
}

BOOL CBlockingSocketException::GetErrorMessage(LPTSTR lpstrError, UINT nMaxError,
        PUINT pnHelpContext /*= NULL*/)
{

    /*char text[2048] = { 0 };
    if(m_nError == 0) {
        wsprintf(text, "%s error", (const char*) m_strMessage);
    }
    else {
        wsprintf(text, "%s error #%d", (const char*) m_strMessage, m_nError);
    }
    strcpy(lpstrError, text);*/
    return TRUE;
}

// Class CBlockingSocket
IMPLEMENT_DYNAMIC(CBlockingSocket, CObject)

void CBlockingSocket::Cleanup()
{
    // doesn't throw an exception because it's called in a catch block
    if(m_hSocket == NULL) return;
    VERIFY(closesocket(m_hSocket) != SOCKET_ERROR);
    m_hSocket = NULL;
}

void CBlockingSocket::Create(int nType /* = SOCK_STREAM */)
{
    //ASSERT(m_hSocket == NULL);
    if((m_hSocket = socket(AF_INET, nType, 0)) == INVALID_SOCKET) {
        throw new CBlockingSocketException("Create");
    }
}

void CBlockingSocket::Bind(LPCSOCKADDR psa)
{
    ASSERT(m_hSocket != NULL);
    if(bind(m_hSocket, psa, sizeof(SOCKADDR)) == SOCKET_ERROR) {
        throw new CBlockingSocketException("Bind");
    }
}

void CBlockingSocket::Listen()
{
    ASSERT(m_hSocket != NULL);
    if(listen(m_hSocket, 5) == SOCKET_ERROR) {
        throw new CBlockingSocketException("Listen");
    }
}

BOOL CBlockingSocket::Accept(CBlockingSocket& sConnect, LPSOCKADDR psa)
{
    ASSERT(m_hSocket != NULL);
    ASSERT(sConnect.m_hSocket == NULL);
    int nLengthAddr = sizeof(SOCKADDR);
    sConnect.m_hSocket = accept(m_hSocket, psa, &nLengthAddr);
    if(sConnect == INVALID_SOCKET) {
        // no exception if the listen was canceled
        if(WSAGetLastError() != WSAEINTR) {
            throw new CBlockingSocketException("Accept");
        }
        return FALSE;
    }
    return TRUE;
}

void CBlockingSocket::Close()
{
    if (NULL == m_hSocket)
        return;

    if(closesocket(m_hSocket) == SOCKET_ERROR) {
        // should be OK to close if closed already
        throw new CBlockingSocketException("Close");
    }
    m_hSocket = NULL;
}

int CBlockingSocket::Connect(LPCSOCKADDR psa)
{
    ASSERT(m_hSocket != NULL);
    // should timeout by itself
    return connect(m_hSocket, psa, sizeof(SOCKADDR));
    
    /*if(Ret == SOCKET_ERROR) {
        throw new CBlockingSocketException("Connect");
    }*/
}

int CBlockingSocket::Write(const char* pch, const int nSize, const int nSecs)
{
    int nBytesSent = 0;
    int nBytesThisTime;
    const char* pch1 = pch;
    do {
        nBytesThisTime = Send(pch1, nSize - nBytesSent, nSecs);
        nBytesSent += nBytesThisTime;
        pch1 += nBytesThisTime;
    } while(nBytesSent < nSize);
    return nBytesSent;
}

int CBlockingSocket::Send(const char* pch, const int nSize, const int nSecs)
{
    ASSERT(m_hSocket != NULL);
    // returned value will be less than nSize if client cancels the reading
    FD_SET fd = {1, m_hSocket};
    TIMEVAL tv = {nSecs, 0};
    if(select(0, NULL, &fd, NULL, &tv) == 0) {
        throw new CBlockingSocketException("Send timeout");
    }
    int nBytesSent= send(m_hSocket, pch, nSize, 0);
    /*if((nBytesSent = ) == SOCKET_ERROR) {
        throw new CBlockingSocketException("Send");
    }*/
    return nBytesSent;
}

int CBlockingSocket::Receive(char* pch, const int nSize, const int nSecs)
{
    ASSERT(m_hSocket != NULL);
    FD_SET fd = {1, m_hSocket};
    TIMEVAL tv = {nSecs, 0};
    if(select(0, &fd, NULL, NULL, &tv) == 0) {
        throw new CBlockingSocketException("Receive timeout");
    }

    int nBytesReceived;
    if((nBytesReceived = recv(m_hSocket, pch, nSize, 0)) == SOCKET_ERROR) {
        throw new CBlockingSocketException("Receive");
    }
    return nBytesReceived;
}

int CBlockingSocket::ReceiveDatagram(char* pch, const int nSize, LPSOCKADDR psa, const int nSecs)
{
    ASSERT(m_hSocket != NULL);
    FD_SET fd = {1, m_hSocket};
    TIMEVAL tv = {nSecs, 0};
    if(select(0, &fd, NULL, NULL, &tv) == 0) {
        throw new CBlockingSocketException("Receive timeout");
    }

    // input buffer should be big enough for the entire datagram
    int nFromSize = sizeof(SOCKADDR);
    int nBytesReceived = recvfrom(m_hSocket, pch, nSize, 0, psa, &nFromSize);
    if(nBytesReceived == SOCKET_ERROR) {
        throw new CBlockingSocketException("ReceiveDatagram");
    }
    return nBytesReceived;
}

int CBlockingSocket::SendDatagram(const char* pch, const int nSize, LPCSOCKADDR psa, const int nSecs)
{
    ASSERT(m_hSocket != NULL);
    FD_SET fd = {1, m_hSocket};
    TIMEVAL tv = {nSecs, 0};
    if(select(0, NULL, &fd, NULL, &tv) == 0) {
        throw new CBlockingSocketException("Send timeout");
    }

    int nBytesSent = sendto(m_hSocket, pch, nSize, 0, psa, sizeof(SOCKADDR));
    if(nBytesSent == SOCKET_ERROR) {
        throw new CBlockingSocketException("SendDatagram");
    }
    return nBytesSent;
}

void CBlockingSocket::GetPeerAddr(LPSOCKADDR psa)
{
    ASSERT(m_hSocket != NULL);
    // gets the address of the socket at the other end
    int nLengthAddr = sizeof(SOCKADDR);
    if(getpeername(m_hSocket, psa, &nLengthAddr) == SOCKET_ERROR) {
        throw new CBlockingSocketException("GetPeerName");
    }
}

void CBlockingSocket::GetSockAddr(LPSOCKADDR psa)
{
    ASSERT(m_hSocket != NULL);
    // gets the address of the socket at this end
    int nLengthAddr = sizeof(SOCKADDR);
    if(getsockname(m_hSocket, psa, &nLengthAddr) == SOCKET_ERROR) {
        throw new CBlockingSocketException("GetSockName");
    }
}

//static
CSockAddr CBlockingSocket::GetHostByName(const char* pchName, const USHORT ushPort /* = 0 */)
{
    hostent* pHostEnt = gethostbyname(pchName);
    if(pHostEnt == NULL) {
        throw new CBlockingSocketException("GetHostByName");
    }
    ULONG* pulAddr = (ULONG*) pHostEnt->h_addr_list[0];
    SOCKADDR_IN sockTemp;
    sockTemp.sin_family = AF_INET;
    sockTemp.sin_port = htons(ushPort);
    sockTemp.sin_addr.s_addr = *pulAddr; // address is already in network byte order
    return sockTemp;
}

//static
const char* CBlockingSocket::GetHostByAddr(LPCSOCKADDR psa)
{
    hostent* pHostEnt = gethostbyaddr((char*) &((LPSOCKADDR_IN) psa)
                ->sin_addr.s_addr, 4, PF_INET);
    if(pHostEnt == NULL) {
        throw new CBlockingSocketException("GetHostByAddr");
    }
    return pHostEnt->h_name; // caller shouldn't delete this memory
}

// Class CHttpBlockingSocket
IMPLEMENT_DYNAMIC(CHttpBlockingSocket, CBlockingSocket)

CHttpBlockingSocket::CHttpBlockingSocket()
{
    m_pReadBuf = new char[nSizeRecv];
    m_nReadBuf = 0;
}

CHttpBlockingSocket::~CHttpBlockingSocket()
{
    delete [] m_pReadBuf;
}

int CHttpBlockingSocket::ReadHttpHeaderLine(char* pch, const int nSize, const int nSecs)
// reads an entire header line through CRLF (or socket close)
// inserts zero string terminator, object maintains a buffer
{
    int nBytesThisTime = m_nReadBuf;
    int nLineLength = 0;
    char* pch1 = m_pReadBuf;
    char* pch2;
    do {
        // look for lf (assume preceded by cr)
        if((pch2 = (char*) memchr(pch1 , '\n', nBytesThisTime)) != NULL) {
            ASSERT((pch2) > m_pReadBuf);
            ASSERT(*(pch2 - 1) == '\r');
            nLineLength = (pch2 - m_pReadBuf) + 1;
            if(nLineLength >= nSize) nLineLength = nSize - 1;
            memcpy(pch, m_pReadBuf, nLineLength); // copy the line to caller
            m_nReadBuf -= nLineLength;
            memmove(m_pReadBuf, pch2 + 1, m_nReadBuf); // shift remaining characters left
            break;
        }
        pch1 += nBytesThisTime;
        nBytesThisTime = Receive(m_pReadBuf + m_nReadBuf, nSizeRecv - m_nReadBuf, nSecs);
        if(nBytesThisTime <= 0) { // sender closed socket or line longer than buffer
            throw new CBlockingSocketException("ReadHeaderLine");
        }
        m_nReadBuf += nBytesThisTime;
    }
    while(TRUE);
    *(pch + nLineLength) = '\0';
    return nLineLength;
}

int CHttpBlockingSocket::ReadHttpResponse(char* pch, const int nSize, const int nSecs)
// reads remainder of a transmission through buffer full or socket close
// (assume headers have been read already)
{
    int nBytesToRead, nBytesThisTime, nBytesRead = 0;
    if(m_nReadBuf > 0) { // copy anything already in the recv buffer
        memcpy(pch, m_pReadBuf, m_nReadBuf);
        pch += m_nReadBuf;
        nBytesRead = m_nReadBuf;
        m_nReadBuf = 0;
    }
    do { // now pass the rest of the data directly to the caller
        nBytesToRead = min(nSizeRecv, nSize - nBytesRead);
        nBytesThisTime = Receive(pch, nBytesToRead, nSecs);
        if(nBytesThisTime <= 0) break; // sender closed the socket
        pch += nBytesThisTime;
        nBytesRead += nBytesThisTime;
    }
    while(nBytesRead <= nSize);
    return nBytesRead;
}

void LogBlockingSocketException(LPVOID pParam, char* pch, CBlockingSocketException* pe)
{    // pParam holds the HWND for the destination window (in another thread)
    /*CString strGmt = CTime::GetCurrentTime().FormatGmt("%m/%d/%y %H:%M:%S GMT");
    char text1[200], text2[50];
    pe->GetErrorMessage(text2, 49);
    wsprintf(text1, "WINSOCK ERROR--%s %s -- %s\r\n", pch, text2, (const char*) strGmt);
    ::SendMessage((HWND) pParam, EM_SETSEL, (WPARAM) 65534, 65535);
    ::SendMessage((HWND) pParam, EM_REPLACESEL, (WPARAM) 0, (LPARAM) text1);*/
}

完整工程源代码在这里:https://download.csdn.net/download/a2311minghan/10874288

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值