这里封装成三个类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