⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpsocket.cpp

📁 很不错的TCP的类
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		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 + -