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

📄 tcpsocket.cpp

📁 很不错的TCP的类
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// TcpSocket.cpp: implementation of the CTcpSocket class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TcpSocket.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define TCP_BUFFER_LENGTH	512
#define TCP_DATA_QUEUE_SIZE	128

LPWSAPROTOCOL_INFO CTcpSocket::m_pProtocolsInfo;
LPWSAPROTOCOL_INFO CTcpSocket::m_pTcpInfo;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CTcpSocket::CTcpSocket()
{
	m_socket = INVALID_SOCKET;
	m_hIOThread = NULL;
	m_hNetEvent = m_hOutputEvent = m_hQuitEvent = NULL;
	m_bWriteOk = FALSE;
	m_bPDA = FALSE;
	m_bPDA_Audio = FALSE;
	OutputDebugString("no error!");
}

CTcpSocket::~CTcpSocket()
{
	if (m_socket != INVALID_SOCKET)
		Unprepare();
}

//////////////////////////////////////////////////////////////////////
// CTcpSocket public functions 
void CTcpSocket::SetPDA()
{
	m_bPDA = TRUE;
}
void CTcpSocket::SetPDAAudio()
{
	m_bPDA_Audio = TRUE;
}

BOOL CTcpSocket::Call(ULONG uPeerIP, HWND hWnd, int iPort)
{
	SOCKADDR_IN addr;
	int err;

	m_hWnd = hWnd;
	m_iPort = (iPort == 0) ? TCP_DEFAULT_PORT : iPort;

	if (Prepare() == FALSE)	
		return FALSE;

	// Create a socket for this connection.
	m_socket = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, m_pTcpInfo, 0, 0);
	if (m_socket == INVALID_SOCKET) 
	{
		OutputDebugString("Could not open a socket in Call\n");
		goto Error;
	} 
	else 
	{	// Set up socket for windows message event notification.
		int ppp=WSAAsyncSelect(m_socket, m_hWnd, WM_TCP_SOCKET_CONNECT, FD_CONNECT);
		int pp=WSAGetLastError();
	}

	addr.sin_family = AF_INET;
	addr.sin_port = htons(m_iPort);
	addr.sin_addr.s_addr = uPeerIP;

	err = WSAConnect(m_socket, (SOCKADDR *)&addr, m_pTcpInfo->iMaxSockAddr, NULL, NULL, NULL, NULL);
	if (err == SOCKET_ERROR) 
	{
		err = WSAGetLastError();
		if (err != WSAEWOULDBLOCK) 
		{
			OutputDebugString("WSAConnect failed\n");
			goto Error;
		}
	} 
	else 
	{
		OutputDebugString("WSAConnect should have returned SOCKET_ERROR\n");
		goto Error;
	}

	m_uPeerIP = addr.sin_addr.s_addr;
	m_strPeerName = inet_ntoa(addr.sin_addr);
	OutputDebugString("Calling " + m_strPeerName + "\n");
	return TRUE;

Error:
	Unprepare();
	return FALSE;
}

void CTcpSocket::Hangup()
{
	if (m_hQuitEvent != NULL)		SetEvent(m_hQuitEvent);
}

BOOL CTcpSocket::Write(char * pData, int iLength)
{
	if (m_hOutputEvent == NULL)	return FALSE;

	CSingleLock sLock(&m_critical);
	WSABUF * p = (WSABUF *)malloc(sizeof(WSABUF));
	if (p == NULL)
	{
		OutputDebugString("malloc failed in CTcpSocket::Write\n");
		return FALSE;
	}
	p->buf = (char *)malloc(TCP_BUFFER_LENGTH);
	if (p->buf == NULL)
	{
		free(p);
		OutputDebugString("malloc failed in CTcpSocket::Write\n");
		return FALSE;
	}
	memcpy(p->buf, pData, iLength);
	p->len = iLength;
	sLock.Lock();
	m_sendQueue.AddTail(p);
	sLock.Unlock();
	SetEvent(m_hOutputEvent);
//	Sleep(0);
	return TRUE;
}

ULONG CTcpSocket::Accept(SOCKET socketListen, LPARAM lParam, HWND hWnd, int iPort)
{
	SOCKADDR_IN addr;
	int iAddrLen = sizeof(addr);
	int err;
	DWORD dwThreadId;	// needed for CreateThread

	err = WSAGETSELECTERROR(lParam);
	// Check to see if there was an error on the connection attempt.
	if (err) 
	{	// Some kind of error occurred.
		if (err == WSAENETDOWN) 
		{
			OutputDebugString("The network is down\n");
        } 
		else 
		{
			OutputDebugString("Unknown error on FD_ACCEPT\n");
		}
		return 0;
	}

	m_hWnd = hWnd;

	//modified by zhb
	m_iPort = (iPort == 0) ? TCP_DEFAULT_PORT : iPort;

    //
	if (Prepare() == FALSE)		return 0;

	m_socket = WSAAccept(socketListen, (SOCKADDR *)&addr, &iAddrLen, NULL, (DWORD)NULL);
	if (m_socket == INVALID_SOCKET) 
	{
		err = WSAGetLastError();
		if (err != WSAECONNREFUSED) 
		{
			OutputDebugString("WSAAccept failed\n");
			goto Error;
		} 
		else 
		{
			OutputDebugString("The connection attempt has been refused\n");
			goto Error;
		}
	}
	m_uPeerIP = addr.sin_addr.s_addr;
	m_iPeerPort =addr.sin_port;
	m_strPeerName = inet_ntoa(addr.sin_addr);

	WSAAsyncSelect(m_socket, m_hWnd, 0, 0);
	// Put Connection in Event Object Notification Mode.
	WSAEventSelect(m_socket, m_hNetEvent, FD_READ | FD_WRITE | FD_CLOSE);

	// Start the I/O thread, and save the thread handle.
	m_hIOThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, this, 0, &dwThreadId);
	if (m_hIOThread == NULL) 
	{
		OutputDebugString("CreateThread() failed in HandleAcceptMessage()\n");
		goto Error;
	}

	OutputDebugString(m_strPeerName + " joined the meeting\n");
	return m_uPeerIP;

Error:
	Unprepare();
	return 0;
}

ULONG CTcpSocket::OnConnect(LPARAM lParam)
{
	int err;
	DWORD dwThreadId;	// needed for CreateThread

	err = WSAGETSELECTERROR(lParam);
	// Check to see if there was an error on the connection attempt.
	if (err) 
	{
		// Some kind of error occurred.
		if (err == WSAECONNREFUSED) 
		{
			OutputDebugString(m_strPeerName + " 处没有应用程序应答\n");
		} 
		else 
		{
			OutputDebugString(m_strPeerName + " 没有在网络上\n");
		}
		goto Error;
	}

	WSAAsyncSelect(m_socket, m_hWnd, 0, 0);
	// Put Connection in Event Object Notification Mode.
	WSAEventSelect(m_socket, m_hNetEvent, FD_READ | FD_WRITE | FD_CLOSE);

	// Start the I/O thread, and save the thread handle.
	m_hIOThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, this, 0, &dwThreadId);
	if (m_hIOThread == NULL) 
	{
		OutputDebugString("CreateThread() failed in OnConnect()\n");
		goto Error;
	}

	OutputDebugString(m_strPeerName + " joined the meeting\n");
	return m_uPeerIP;

Error:
	Unprepare();
	return 0;
}

void CTcpSocket::OnClose()
{
	Unprepare();
}

//////////////////////////////////////////////////////////////////////
// CTcpSocket protected functions 

BOOL CTcpSocket::Prepare()
{
	m_hNetEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_hOutputEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_hQuitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (!m_hNetEvent || !m_hOutputEvent || !m_hQuitEvent)
	{
		OutputDebugString("CreateEvent fail in Prepare connection data\n");
		goto Error;
	}

	m_eventArray[0] = m_hNetEvent;
	m_eventArray[1] = m_hOutputEvent;
	m_eventArray[2] = m_hQuitEvent;

	return TRUE;

Error:
	Unprepare();
	return FALSE;
}

void CTcpSocket::Unprepare()
{
	if (m_hNetEvent != NULL)
	{
		CloseHandle(m_hNetEvent);
		m_hNetEvent = NULL;
	}
	if (m_hOutputEvent != NULL)
	{
		CloseHandle(m_hOutputEvent);
		m_hOutputEvent = NULL;
	}
	if (m_hQuitEvent != NULL)
	{
		CloseHandle(m_hQuitEvent);
		m_hQuitEvent = NULL;
	}
	if (m_hIOThread != NULL)
	{
		CloseHandle(m_hIOThread);
		m_hIOThread = NULL;
	}
	while (!m_sendQueue.IsEmpty())
	{
		WSABUF * p = m_sendQueue.RemoveHead();
		free(p->buf);
		free(p);
	}
	if (m_socket != INVALID_SOCKET)
	{
		WSAEventSelect(m_socket, m_hNetEvent, 0);
		closesocket(m_socket);
		m_socket = INVALID_SOCKET;
	}
}

//////////////////////////////////////////////////////////////////////
// CTcpSocket Static functions 

BOOL CTcpSocket::Startup()
{
	int i, err;
	DWORD dwBufferSize = 0;		// size of m_pProtocolsInfo buffer
	WORD wVersionRequested;
	BOOL bFoundTcp = FALSE;
	WSADATA wsaData;

	m_pProtocolsInfo = NULL;

	// Asynchronous IO and multicast semantics we use supported starting only with WinSock 2.0 
	wVersionRequested = MAKEWORD (2, 2);
    // Start WinSock 2.  If it fails, we don't need to call WSACleanup().
	err = WSAStartup (wVersionRequested, &wsaData);
	if (err != 0)
	{
		OutputDebugString("Could not find high enough version of WinSock\n");
		return FALSE;
	}
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) !=2 ) 
	{	
		OutputDebugString("Could not find the correct version of WinSock\n");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -