📄 simplesocket.cpp
字号:
// SimpleSocket.cpp -- CSocket class plus TimeOut
//
#include "stdafx.h"
#include "SimpleSocket.h"
#include <process.h> // This is for _beginthread
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CSimpleSocket, CSocket)
CSimpleSocket::CSimpleSocket(UINT uTimeOut)
: m_uTimeOut(uTimeOut)
{
}
CSimpleSocket::~CSimpleSocket()
{
}
int CSimpleSocket::ReceiveLine(CString& szLine, int nFlags)
{
int nRet = 0;
if (m_szFullString.IsEmpty()) {
nRet = ReceiveString(m_szFullString, nFlags);
}
// Return next line in string
int nPos = m_szFullString.Find("\r\n");
if (nPos==-1) {
szLine = m_szFullString;
} else {
szLine = m_szFullString.Left(nPos+1);
m_szFullString = m_szFullString.Mid(nPos+2);
}
TRACE1("CSimpleSocket::ReceiveLine: \"%s\"\n", (LPCTSTR)szLine);
return(szLine.GetLength());
}
int CSimpleSocket::ReceiveString(CString& str, int nFlags)
{
static char szBuf[4096];
memset(szBuf, 0, sizeof(szBuf));
// Call generic-buffer function
int nRet = Receive((void *)szBuf, sizeof(szBuf), nFlags);
if (nRet==0) {
// Connection has been closed (?)
nRet=SOCKET_ERROR;
SetLastError(WSAECONNRESET);
}
// Fill in the CString reference
str = szBuf;
TRACE1("CSimpleSocket::ReceiveString: \"%s\"\n", (LPCTSTR)str);
return nRet;
}
int CSimpleSocket::Receive(void* lpBuf, int nBufLen, int nFlags)
{
int nResult = 0;
nResult = WaitForData(&m_hSocket, NULL, &m_hSocket);
if (nResult != SOCKET_ERROR) {
nResult = CSocket::Receive(lpBuf, nBufLen, nFlags);
}
return(nResult);
}
int CSimpleSocket::Send(LPCTSTR lpszString, int nFlags)
{
CString szString = lpszString;
// Use CString version of Send
return(Send(szString, nFlags));
}
int CSimpleSocket::Send(CString &szString, int nFlags)
{
// Use void* buffer version of Send
return(Send((void *)szString.GetBuffer(0), szString.GetLength(), nFlags));
}
int CSimpleSocket::Send(const void* lpBuf, int nBufLen, int nFlags)
{
int nResult = 0;
nResult = WaitForData(NULL, &m_hSocket, &m_hSocket);
if (nResult != SOCKET_ERROR) {
nResult = CSocket::Send(lpBuf, nBufLen, nFlags);
}
return(nResult);
}
void CSimpleSocket::SetTimeOut(UINT uTimeOut)
{
m_uTimeOut = uTimeOut;
}
UINT CSimpleSocket::GetTimeOut() const
{
return(m_uTimeOut);
}
int CSimpleSocket::WaitForData(SOCKET *pSocketForReceiving, SOCKET *pSocketForSending,SOCKET *pSocketForExceptions)
{
int nSocketsReady = 0;
fd_set FdSetReceive;
FD_ZERO(&FdSetReceive);
fd_set FdSetSend;
FD_ZERO(&FdSetSend);
fd_set FdSetError;
FD_ZERO(&FdSetError);
if (pSocketForReceiving) {
FD_SET(*pSocketForReceiving, &FdSetReceive);
}
if (pSocketForSending) {
FD_SET(*pSocketForSending, &FdSetSend);
}
if (pSocketForExceptions) {
FD_SET(*pSocketForExceptions, &FdSetError);
}
TIMEVAL tv;
TIMEVAL *ptv;
if (m_uTimeOut) {
tv.tv_sec = m_uTimeOut/1000;
tv.tv_usec = m_uTimeOut*1000 - tv.tv_sec * 1000000;
ptv = &tv;
} else {
ptv = NULL; // NULL for blocking operation (never times out)
}
nSocketsReady = select(0, &FdSetReceive, &FdSetSend, &FdSetError, ptv);
// If the operation timed out, set a more
// natural error message
if (nSocketsReady == 0) {
SetLastError(WSAETIMEDOUT);
nSocketsReady = SOCKET_ERROR;
}
return(nSocketsReady);
}
BOOL CSimpleSocket::Connect(LPCTSTR lpszHostAddress, UINT nHostPort, UINT uTimeOut)
{
BOOL bReturnCode = FALSE;
DWORD dwWaitStatus;
HANDLE lpWaitHandles = NULL;
SOCKET hSocket = INVALID_SOCKET;
HANDLE hConnectingThread = NULL;
DWORD dwConnectionErrorCode = 0;
// TODO: handle connect timer/timeout for other Connect method:
// BOOL Connect( const SOCKADDR* lpSockAddr, int nSockAddrLen );
void *pvIOParams[] = {
(char *)lpszHostAddress,
(char *)&nHostPort,
(char *)&hSocket,
(char *)&dwConnectionErrorCode
};
// Create 1 thread to make the connection
hConnectingThread = CreateConnectingThread((void *)pvIOParams);
if (!hConnectingThread) {
// Cannot create thread, and GetLastError() will return the error code
return(FALSE);
}
lpWaitHandles = hConnectingThread;
// Wait for thread to end (connection established) or for time-out
dwWaitStatus = WaitForSingleObject(lpWaitHandles, (DWORD)uTimeOut);
switch (dwWaitStatus) {
case WAIT_ABANDONED:
break;
case WAIT_TIMEOUT:
// Timeout occurred: Kill connecting thread and return error (WSAETIMEDOUT)
if (hConnectingThread) {
TerminateThread(hConnectingThread, (DWORD)HRESULT_FROM_WIN32(WSAETIMEDOUT));
}
// We must set the timeout error in current thread
WSASetLastError(WSAETIMEDOUT);
bReturnCode = FALSE;
break;
case WAIT_OBJECT_0: // Thread 1: Connecting thread
// Connection established or error?
if (dwConnectionErrorCode == 0) {
// Connection established: attach connected socket to 'this'
if (m_hSocket != INVALID_SOCKET) {
Close();
}
Attach(hSocket);
bReturnCode = TRUE;
} else {
// Connection failure: report error
WSASetLastError(dwConnectionErrorCode);
bReturnCode = FALSE;
}
break;
case 0xFFFFFFFF:
// Wait failure: abnormal
break;
default:
// Unexpected: error
break;
}
return(bReturnCode);
}
HANDLE CSimpleSocket::CreateConnectingThread(void *pvIOParams)
{
HANDLE hThread = NULL;
hThread = reinterpret_cast<HANDLE> (_beginthread(ThreadConnectSocket, 0, (void *)pvIOParams));
return(hThread);
}
void CSimpleSocket::ThreadConnectSocket(void *pvIOParams)
{
LPCTSTR lpszHostAddress = NULL;
UINT *puHostPort = NULL;
SOCKET *phSocket = NULL;
DWORD *pdwConnectionErrorCode = NULL;
// Really really dirty cast but how can you pass 4 pointers within a (void *)?
int *piIOParams = (int *)pvIOParams;
void *pIOParams[4] = {
(void *)piIOParams[0],
(void *)piIOParams[1],
(void *)piIOParams[2],
(void *)piIOParams[3]
};
if (pIOParams) {
lpszHostAddress = (LPCTSTR)pIOParams[0];
puHostPort = (UINT *)pIOParams[1];
phSocket = (SOCKET *)pIOParams[2];
pdwConnectionErrorCode = (DWORD *)pIOParams[3];
if (lpszHostAddress && puHostPort) {
CSocket oConnectingSocket;
if (oConnectingSocket.Create()) {
if (oConnectingSocket.Connect(lpszHostAddress, *puHostPort)) {
if (phSocket) {
*phSocket = oConnectingSocket.Detach();
}
if (pdwConnectionErrorCode) {
*pdwConnectionErrorCode = 0;
}
} else {
if (pdwConnectionErrorCode) {
*pdwConnectionErrorCode = GetLastError();
}
}
} else {
if (pdwConnectionErrorCode) {
*pdwConnectionErrorCode = oConnectingSocket.GetLastError();
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -