📄 tcpsocket.cpp
字号:
goto Error;
}
// Call WSAEnumProtocols to figure out how big of a buffer we need.
err = WSAEnumProtocols(NULL, NULL, &dwBufferSize);
if (err != SOCKET_ERROR && WSAGetLastError() != WSAENOBUFS)
{
OutputDebugString("WSAEnumProtocols is broken\n");
goto Error;
}
// Allocate a buffer, call WSAEnumProtocols to get an array of WSAPROTOCOL_INFO structs.
m_pProtocolsInfo = (LPWSAPROTOCOL_INFO)malloc(dwBufferSize);
if (m_pProtocolsInfo == NULL)
{
OutputDebugString("malloc m_pProtocolsInfo failed\n");
goto Error;
}
err = WSAEnumProtocols(NULL, m_pProtocolsInfo, &dwBufferSize);
if (err == SOCKET_ERROR)
{
OutputDebugString("WSAEnumProtocols failed\n");
goto Error;
}
for (i = 0; i < err; i ++)
{
m_pTcpInfo = &m_pProtocolsInfo[i];
ASSERT(m_pTcpInfo != NULL);
if (m_pTcpInfo->iAddressFamily == AF_INET)
{
bFoundTcp = TRUE;
break;
}
// OutputDebugString(m_pTcpInfo->szProtocol);
// OutputDebugString("\n");
}
if (!bFoundTcp) goto Error;
OutputDebugString("WinSock2 Init\n");
return TRUE;
Error:
Shutdown();
return FALSE;
}
void CTcpSocket::Shutdown()
{
OutputDebugString("WinSock2 Free\n");
if (m_pProtocolsInfo != NULL)
{
free(m_pProtocolsInfo);
}
WSACleanup( );
}
CString CTcpSocket::GetHostName()
{
static CString strName;
char szHostname[80];
gethostname(szHostname, 80);
strName = szHostname;
return strName;
}
CString CTcpSocket::GetProtocols()
{
static CString strProto;
int i;
PROTOENT * proto;
strProto = "";
for (i = 0; i < 20; i ++)
{
proto = getprotobynumber(i);
if (proto != NULL)
{
strProto += proto->p_name;
strProto += " / ";
}
}
return strProto;
}
CString CTcpSocket::GetProviders()
{
static CString strProviders;
WSANAMESPACE_INFO info[20];
DWORD dwBufferLength = (sizeof(WSANAMESPACE_INFO) * 20);
int i, iNumber;
iNumber = WSAEnumNameSpaceProviders(&dwBufferLength, &info[0]);
strProviders = "";
for (i = 0; i < iNumber; i ++)
{
strProviders += info[i].lpszIdentifier;
strProviders += "\n";
}
return strProviders;
}
ULONG CTcpSocket::Name2IP(CString strName)
{
ULONG uIP = 0;
HOSTENT *host;
uIP = inet_addr(strName);
if (uIP == INADDR_NONE)
{
host = gethostbyname(strName);
if (host)
{
uIP = *((ULONG *)host->h_addr_list[0]);
}
}
return uIP;
}
CString CTcpSocket::IP2Name(ULONG uIP)
{
static CString str;
IN_ADDR dotIP;
dotIP.S_un.S_addr = uIP;
str = inet_ntoa(dotIP);
return str;
}
ULONG CTcpSocket::GetLocalIP()
{
char szNameBuf[128];
gethostname(szNameBuf,127);
HOSTENT * host = gethostbyname(szNameBuf);
return *((long*)host->h_addr);
}
BOOL CTcpSocket::HandleNetworkEvent()
{
WSANETWORKEVENTS networkEvents; // tells us what events happened
int err;
// Find out what happened and act accordingly.
err = WSAEnumNetworkEvents(m_socket, m_hNetEvent, &networkEvents);
if (err == SOCKET_ERROR)
{ // Handle the fatal error, break out to end.
OutputDebugString("WSAEnumNetworkEvents failed\n");
return FALSE;
}
// The following three if statements all execute unless one gets
// an error or closed socket, in which case we return immediately.
if (networkEvents.lNetworkEvents & FD_READ)
{ // An FD_READ event has occurred on the connected socket.
if (networkEvents.iErrorCode[FD_READ_BIT] == WSAENETDOWN)
{ // There is an error.
OutputDebugString("Error in FD_READ\n");
return FALSE;
}
else
{ // Read data off the socket...
DWORD dwNumBytes; // stores how many bytes we received
DWORD dwFlags = 0; // flags for WSARecv
WSABUF * p = (WSABUF *)malloc(sizeof(WSABUF));
if (p == NULL)
{
OutputDebugString("malloc failed in CTcpSocket::HandleNetworkEvent()\n");
return FALSE;
}
p->buf = (char *)malloc(TCP_BUFFER_LENGTH);
if (p->buf == NULL)
{
free(p);
OutputDebugString("malloc failed in CTcpSocket::HandleNetworkEvent()\n");
return FALSE;
}
p->len = TCP_BUFFER_LENGTH - 1;
err = WSARecv(m_socket, p, 1, &dwNumBytes, &dwFlags, NULL, NULL);
if (err == SOCKET_ERROR)
{
err = WSAGetLastError();
if (err != WSAEWOULDBLOCK)
{
free(p->buf);
free(p);
OutputDebugString("The remote party has reset the connection or other err\n");
return FALSE;
}
}
p->len = dwNumBytes;
// PostMessage(m_hWnd, WM_TCP_SOCKET_DATA, (WPARAM)m_uPeerIP, (LPARAM)p);
PostMessage(m_hWnd, WM_TCP_SOCKET_DATA, (WPARAM)m_socket, (LPARAM)p);
}
}
if (networkEvents.lNetworkEvents & FD_WRITE)
{ // An FD_WRITE event has occurred on the connected socket.
if (networkEvents.iErrorCode[FD_WRITE_BIT] == WSAENETDOWN)
{ // There is an error.
OutputDebugString("Error in FD_WRITE\n");
return FALSE;
}
else
{ // Allow to send on this socket, and signal the hOuputEvent in case
// there is pending output that is not completed due to WSAEWOULDBLOCK.
m_bWriteOk = TRUE;
SetEvent(m_hOutputEvent);
// OutputDebugString("Set hOutputEvent\n");
}
}
if (networkEvents.lNetworkEvents & FD_CLOSE)
{
if (networkEvents.iErrorCode[FD_CLOSE_BIT] == 0)
{ // A graceful shutdown has occurred...
return FALSE;
}
else
{ // This is some other type of abortive close or failure...
OutputDebugString("Socket aborted\n");
return FALSE;
}
}
return TRUE;
}
BOOL CTcpSocket::HandleOutputEvent()
{
if (!m_bWriteOk)
{ // Wait for next FD_WRITE
return TRUE;
}
BOOL bRet = TRUE;
CSingleLock sLock(&m_critical);
WSABUF * p;
DWORD dwBytesSent; // needed in WSASend
int err;
sLock.Lock();
while (!m_sendQueue.IsEmpty() && m_bWriteOk)
{
p = m_sendQueue.RemoveHead();
err = WSASend(m_socket, p, 1, &dwBytesSent, 0, NULL, NULL);
if (err == SOCKET_ERROR)
{
err = WSAGetLastError();
m_bWriteOk = FALSE;
if (err == WSAEWOULDBLOCK)
{ // WSAEWOULDBLOCK means we have to wait for an FD_WRITE before we can send.
m_sendQueue.AddHead(p);
}
else
{
OutputDebugString("Unexpected error with WSASend\n");
bRet = FALSE;
free(p->buf);
free(p);
}
}
else
{
if (dwBytesSent != p->len)
{
OutputDebugString("Not all data sent out in CTcpSocket::HandleOutputEvent()!\n");
}
free(p->buf);
free(p);
}
}
sLock.Unlock();
return bRet;
}
void CTcpSocket::CleanUp()
{
PostMessage(m_hWnd, WM_TCP_SOCKET_CLOSE, (WPARAM)m_socket, (LPARAM)m_uPeerIP);
}
DWORD WINAPI CTcpSocket::ThreadFunc(LPVOID pParam)
{
DWORD dwWaitStatus; // holds return value of the wait
CTcpSocket * p = (CTcpSocket *)pParam; // connection-specific data
while (TRUE)
{
// Wait for an event
dwWaitStatus = WSAWaitForMultipleEvents(3, p->m_eventArray,
FALSE, // fWaitAll
WSA_INFINITE, // dwTimeout
FALSE); // fAlertable
switch (dwWaitStatus)
{
case WSA_WAIT_FAILED: // A fatal error
OutputDebugString("WSAWaitForMultipleEvents() failed\n");
break;
case WSA_WAIT_EVENT_0: // The hNetEvent has been signaled.
if (p->HandleNetworkEvent())
{
continue;
}
break;
case WSA_WAIT_EVENT_0+1: // The hOutputEvent has been signaled.
if (p->HandleOutputEvent())
{
continue;
}
break;
case WSA_WAIT_EVENT_0+2: // Quit time;
OutputDebugString("Hangup by myself\n");
break;
default:
OutputDebugString("Unknown error in WSAWaitForMultipleEvents()\n");
break;
} // switch (dwWaitStatus)
// Break out of the while loop.
break;
} // while (1)
// Thread is ending because the connection was closed or an error occurred
p->CleanUp(); //modified by liuyebin
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -