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

📄 netplay.cpp

📁 著名的任天堂FC游戏机模拟器VirtuaNes 085版的源码!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	}

	// Frame control
	// 懍偡偓偐丠
	if( m_nRecvSize < SOCKET_BLOCK_SIZE ) {
		return	-1;	// 彮偟懸偭偰偔傟
	}
	// 抶偡偓偐丠
	if( m_nRecvSize > ((m_nLatency+2)*SOCKET_BLOCK_SIZE) ) {
		return	1;	// 彮偟恑傔偰偔傟
	}
	return	0;
}

// 摨婜慜張棟(儗僀僥儞僔偺暘偩偗愭偵憲怣偟偰摨婜傪庢傞)
INT	CNetPlay::Sync()
{
BYTE	senddata[SOCKET_BLOCK_SIZE];

DEBUGOUT( "CNetPlay::Sync\n" );

	ZEROMEMORY( senddata, sizeof(senddata) );

	m_nFrameCount = 0;
	m_nRingPtr = m_nSendPtr = m_nRecvPtr = 0;
	m_nRecvSize = 0;

DEBUGOUT( "CNetPlay::Sync sending...\n" );

	// 僨乕僞憲怣
	for( INT i = 0; i < m_nLatency+1; i++ ) {
		while( TRUE ) {
			if( ::send( m_SocketData, (char*)senddata, SOCKET_BLOCK_SIZE, 0 ) == SOCKET_ERROR ) {
				// 僽儘僢僋偝傟偨偐傕抦傟側偄偺偱嵞搙挧愴
				if( ::WSAGetLastError() == WSAEWOULDBLOCK ) {
DEBUGOUT( "send::WSAEWOULDBLOCK!!\n" );
					::Sleep(0);	// 屌傑傜側偄慬抲
					continue;
				} else {
				// 抳柦揑僄儔乕偭傐偄
DEBUGOUT( "CNetPlay:Sync send failed. [%s]\n", SocketErrorDump( ::WSAGetLastError() ) );
					Disconnect();
					return	-1L;
				}
			} else {
				break;
			}
		}
		m_nSendPtr = (m_nSendPtr+SOCKET_BLOCK_SIZE) & SOCKET_BUFFER_SIZE-1;
	}

	// 憡庤僨乕僞偺僶僢僼傽儕儞僌僨乕僞懸偪(10昩偱僞僀儉傾僂僩)
	DWORD	dwTime = ::timeGetTime();
	while( m_nRecvSize < (m_nLatency+1)*SOCKET_BLOCK_SIZE ) {
		if( !RecvBuffer() ) {
			DEBUGOUT( "CNetPlay:recv error.\n" );
			Disconnect();
			return	-1;
		}

		if( (::timeGetTime()-dwTime) > 10*1000 ) {
			DEBUGOUT( "CNetPlay:Sync recv timeout.\n" );
			Disconnect();
			return	-1;
		}
		::Sleep( 1 );
	}

DEBUGOUT( "CNetPlay::Sync OK!\n" );

	return	0;
}

// 僾儗僀儎乕僉乕偺峏怴
INT	CNetPlay::ModifyPlayer( LPBYTE p1, LPBYTE p2 )
{
	if( !m_hWnd || !m_bConnect || m_SocketData == INVALID_SOCKET )
		return	-1L;

	// 憲傞傋偒億僀儞僩偱憲怣
	if( m_nFrameCount == 0 ) {
		while( TRUE ) {
			if( ::send( m_SocketData, (char*)p1, SOCKET_BLOCK_SIZE, 0 ) == SOCKET_ERROR ) {
				// 僽儘僢僋偝傟偨偐傕抦傟側偄偺偱嵞搙挧愴
				if( ::WSAGetLastError() == WSAEWOULDBLOCK ) {
DEBUGOUT( "send::WSAEWOULDBLOCK!!\n" );
					::Sleep(0);	// 屌傑傜側偄慬抲
					continue;
				} else {
				// 抳柦揑僄儔乕偭傐偄
					DEBUGOUT( "CNetPlay:ModifyPlayer send failed. code=%d\n", ::WSAGetLastError() );
					Disconnect();
					return	-1L;
				}
			} else {
				break;
			}
		}

		// 僶僢僼傽偵曻傝崬傓
		for( INT i = 0; i < SOCKET_BLOCK_SIZE; i++ ) {
			m_SendBuffer[ m_nSendPtr ] = p1[i];
			m_nSendPtr = (m_nSendPtr+1) & SOCKET_BUFFER_SIZE-1;
		}
	}

	// 憡庤僨乕僞懸偪(10昩偱僞僀儉傾僂僩)
	DWORD	dwTime = ::timeGetTime();
	while( m_nRecvSize < SOCKET_BLOCK_SIZE ) {
		if( !RecvBuffer() ) {
			DEBUGOUT( "CNetPlay:ModifyPlayer recv error.\n" );
			Disconnect();
			return	-1;
		}
		if( (::timeGetTime()-dwTime) > 10*1000 ) {
			DEBUGOUT( "CNetPlay:ModifyPlayer recv timeout.\n" );
			Disconnect();
			return	-1;
		}
		::Sleep( 1 );
	}

	// 忣曬峏怴
	INT	p = m_nRingPtr;
	for( INT i = 0; i < SOCKET_BLOCK_SIZE; i++ ) {
		p1[i] = m_SendBuffer[ p ];
		p2[i] = m_RecvBuffer[ p ];
		p = (p+1) & SOCKET_BUFFER_SIZE-1;
	}

	INT	Count = m_nFrameCount;

	// 僗僥僢僾峏怴
	if( ++m_nFrameCount > m_nFrameStep ) {
		m_nFrameCount = 0;

		m_nRingPtr = (m_nRingPtr+SOCKET_BLOCK_SIZE) & SOCKET_BUFFER_SIZE-1;
		m_nRecvSize -= SOCKET_BLOCK_SIZE;
	}

	return	Count;
}

void	CNetPlay::ChatSend( LPCSTR lpStr )
{
	if( !m_hWnd || !m_bConnect || m_SocketChat == INVALID_SOCKET )
		return;

	if( m_bServer ) {
DEBUGOUT( "ChatSend Server:%s", lpStr );
		if( ::sendto( m_SocketChat, (char*)lpStr, ::strlen(lpStr)+1, 0, (struct sockaddr *)&m_SAddr_Client, sizeof(m_SAddr_Client) ) == SOCKET_ERROR ) {
			DEBUGOUT( "ChatSend failed. Server:[%s]\n", SocketErrorDump( ::WSAGetLastError() ) );
		}
	} else {
DEBUGOUT( "ChatSend Client:%s", lpStr );
		if( ::sendto( m_SocketChat, (char*)lpStr, ::strlen(lpStr)+1, 0, (struct sockaddr *)&m_SAddr_Server, sizeof(m_SAddr_Server) ) == SOCKET_ERROR ) {
			DEBUGOUT( "ChatSend failed. Server:[%s]\n", SocketErrorDump( ::WSAGetLastError() ) );
		}
	}
}

HRESULT	CNetPlay::WndProc( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
	// 僄儔乕丠
	if( WSAGETSELECTERROR(lParam) ) {
		DEBUGOUT( "CNetPlay::WndProc error.[%s]\n", SocketErrorDump( WSAGETSELECTERROR(lParam) ) );

		Disconnect();
		if( m_hWndMsg ) {
			::PostMessage( m_hWndMsg, WM_NETPLAY_CLOSE, 0, 0 );
		}

		return	0L;
	}

	switch( WSAGETSELECTEVENT(lParam) ) {
		case	FD_ACCEPT: {
			DEBUGOUT( "Accepting...." );
			ZEROMEMORY( &m_SAddr_Client, sizeof(m_SAddr_Client) );
			int	len = sizeof(m_SAddr_Client);
			m_SocketData = ::accept( m_SocketConnect, (sockaddr*)&m_SAddr_Client, &len );

			// 愙懕梡僜働僢僩偼暵偠傞
			::shutdown( m_SocketConnect, SD_BOTH );
			CLOSESOCKET( m_SocketConnect );

			if( m_SocketData == INVALID_SOCKET ) {
				DEBUGOUT( "failed.\n" );
				if( m_hWndMsg ) {
					::PostMessage( m_hWndMsg, WM_NETPLAY_ERROR, 0, 0 );
				}
				return	0L;
			}

			DEBUGOUT( "done.\n" );

			// Nagle傾儖僑儕僘儉偺柍岠壔
			unsigned long ulOpt = 1;
			if( ::setsockopt( m_SocketData, IPPROTO_TCP, TCP_NODELAY, (const char*)&ulOpt, sizeof(ulOpt) ) == SOCKET_ERROR ) {
				DEBUGOUT( "CNetPlay:setsockopt failed.\n" );
				Disconnect();
				if( m_hWndMsg ) {
					::PostMessage( m_hWndMsg, WM_NETPLAY_ERROR, 0, 0 );
				}
				return	0L;
			}

			// 僽儘僢僉儞僌儌乕僪愝掕
			unsigned long ulArg = 1;
			if( ::ioctlsocket( m_SocketData, FIONBIO, &ulArg ) == SOCKET_ERROR ) {
				DEBUGOUT( "CNetPlay:ioctlsocket failed.\n" );
				Disconnect();
				if( m_hWndMsg ) {
					::PostMessage( m_hWndMsg, WM_NETPLAY_ERROR, 0, 0 );
				}
				return	0L;
			}

			// 旕摨婜僀儀儞僩偺愝掕
			if( ::WSAAsyncSelect( m_SocketChat, m_hWnd, WM_NETPLAY, FD_READ ) == SOCKET_ERROR ) {
				DEBUGOUT( "CNetPlay:WSAAsyncSelect failed.[CONNECT chat]\n" );
				Disconnect();
				if( m_hWndMsg ) {
					::PostMessage( m_hWndMsg, WM_NETPLAY_ERROR, 0, 0 );
				}
				return	0L;
			}

			// 旕摨婜僀儀儞僩偺愝掕
			if( ::WSAAsyncSelect( m_SocketData, m_hWnd, WM_NETPLAY, FD_CLOSE ) == SOCKET_ERROR ) {
				DEBUGOUT( "CNetPlay:WSAAsyncSelect failed.[ACCEPT data]\n" );
				Disconnect();
				if( m_hWndMsg ) {
					::PostMessage( m_hWndMsg, WM_NETPLAY_ERROR, 0, 0 );
				}
				return	0L;
			}

			m_bConnect = TRUE;
			if( m_hWndMsg ) {
				::PostMessage( m_hWndMsg, WM_NETPLAY_ACCEPT, 0, 0 );
			}
			break;
			}

		case	FD_CONNECT: {
			DEBUGOUT( "Connection done.\n" );

			// 1僶僀僩偩偗僟儈乕僨乕僞傪憲傞(壗偐娫堘偭偰傞婥傕偡傞乧)
			if( ::sendto( m_SocketChat, (char*)"", 1, 0, (struct sockaddr *)&m_SAddr_Server, sizeof(m_SAddr_Server) ) == SOCKET_ERROR ) {
				DEBUGOUT( "CNetPlay:send failed. Client:[%s]\n", SocketErrorDump( ::WSAGetLastError() ) );
				Disconnect();
				if( m_hWndMsg ) {
					::PostMessage( m_hWndMsg, WM_NETPLAY_ERROR, 0, 0 );
				}
				return	0L;
			}

			// 旕摨婜僀儀儞僩偺愝掕
			if( ::WSAAsyncSelect( m_SocketChat, m_hWnd, WM_NETPLAY, FD_READ ) == SOCKET_ERROR ) {
				DEBUGOUT( "CNetPlay:WSAAsyncSelect failed.[CONNECT chat]\n" );
				Disconnect();
				if( m_hWndMsg ) {
					::PostMessage( m_hWndMsg, WM_NETPLAY_ERROR, 0, 0 );
				}
				return	0L;
			}

			// 旕摨婜僀儀儞僩偺愝掕
			if( ::WSAAsyncSelect( m_SocketData, m_hWnd, WM_NETPLAY, FD_CLOSE ) == SOCKET_ERROR ) {
				DEBUGOUT( "CNetPlay:WSAAsyncSelect failed.[CONNECT data]\n" );
				Disconnect();
				if( m_hWndMsg ) {
					::PostMessage( m_hWndMsg, WM_NETPLAY_ERROR, 0, 0 );
				}
				return	0L;
			}
			m_bConnect = TRUE;
			if( m_hWndMsg ) {
				::PostMessage( m_hWndMsg, WM_NETPLAY_CONNECT, 0, 0 );
			}
			break;
			}

		case	FD_CLOSE: {
			DEBUGOUT( "Connection close.\n" );
			if( m_bConnect && m_hWndMsg ) {
				::PostMessage( m_hWndMsg, WM_NETPLAY_CLOSE, 0, 0 );
			}
			Disconnect();
			break;
			}

		case	FD_READ: {
// error is ignored :p
//			DEBUGOUT( "FD_READ\n" );
			INT	recvsize = 0;
			INT	size = sizeof(struct sockaddr_in);
			CHAR	szBuf[256+1];

			if( m_bServer ) {
				recvsize = ::recvfrom( m_SocketChat, (char*)szBuf, sizeof(szBuf)-1, 0, (struct sockaddr *)&m_SAddr_Client, &size );
			} else {
				recvsize = ::recvfrom( m_SocketChat, (char*)szBuf, sizeof(szBuf)-1, 0, (struct sockaddr *)&m_SAddr_Server, &size );
			}

			if( recvsize == SOCKET_ERROR ) {
if( m_bServer ) {
DEBUGOUT( "FD_READ failed. Server [%s]\n", SocketErrorDump( ::WSAGetLastError() ) );
} else {
DEBUGOUT( "FD_READ failed. Client [%s]\n", SocketErrorDump( ::WSAGetLastError() ) );
}
			} else if( recvsize > 0 ) {
				szBuf[recvsize] = '\0';

				if( m_hWndChat && ::IsWindow( m_hWndChat ) ) {
					COPYDATASTRUCT	cds;
					cds.dwData = 0;
					cds.lpData = (void*)szBuf;
					cds.cbData = ::strlen(szBuf)+1; //  廔抂偺NULL傕憲傞
					//  暥帤楍憲怣
					::SendMessage( m_hWndChat, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds );
				}
			}
			break;
			}
		default:
DEBUGOUT( "Unknown message.\n" );
			break;
	}

	return	0L;
}

static	char*	SocketErrorDump( int eno )
{
	switch( eno ) {
	case	0:			return	"No error";

#if	defined(_DEBUG)||defined(_DEBUGOUT)
	case	WSAEINTR:		return	"Interrupted system call";
	case	WSAEBADF:		return	"Bad file number";
	case	WSAEACCES:		return	"Permission denied";
	case	WSAEFAULT:		return	"Bad address";
	case	WSAEINVAL:		return	"Invalid argument";
	case	WSAEMFILE:		return	"Too many open sockets";

	case	WSAEWOULDBLOCK:		return	"Operation would block";
	case	WSAEINPROGRESS:		return	"Operation now in progress";
	case	WSAEALREADY:		return	"Operation already in progress";
	case	WSAENOTSOCK:		return	"Socket operation on non-socket";
	case	WSAEDESTADDRREQ:	return	"Destination address required";
	case	WSAEMSGSIZE:		return	"Message too long";
	case	WSAEPROTOTYPE:		return	"Protocol wrong type for socket";
	case	WSAENOPROTOOPT:		return	"Bad protocol option";
	case	WSAEPROTONOSUPPORT:	return	"Protocol not supported";
	case	WSAESOCKTNOSUPPORT:	return	"Socket type not supported";
	case	WSAEOPNOTSUPP:		return	"Operation not supported on socket";
	case	WSAEPFNOSUPPORT:	return	"Protocol family not supported";
	case	WSAEAFNOSUPPORT:	return	"Address family not supported";
	case	WSAEADDRINUSE:		return	"Address already in use";
	case	WSAEADDRNOTAVAIL:	return	"Can't assign requested address";
	case	WSAENETDOWN:		return	"Network is down";
	case	WSAENETUNREACH:		return	"Network is unreachable";
	case	WSAENETRESET:		return	"Net connection reset";
	case	WSAECONNABORTED:	return	"Software caused connection abort";
	case	WSAECONNRESET:		return	"Connection reset by peer";
	case	WSAENOBUFS:		return	"No buffer space available";
	case	WSAEISCONN:		return	"Socket is already connected";
	case	WSAENOTCONN:		return	"Socket is not connected";
	case	WSAESHUTDOWN:		return	"Can't send after socket shutdown";
	case	WSAETOOMANYREFS:	return	"Too many references, can't splice";
	case	WSAETIMEDOUT:		return	"Connection timed out";
	case	WSAECONNREFUSED:	return	"Connection refused";
	case	WSAELOOP:		return	"Too many levels of symbolic links";
	case	WSAENAMETOOLONG:	return	"File name too long";
	case	WSAEHOSTDOWN:		return	"Host is down";
	case	WSAEHOSTUNREACH:	return	"No route to host";
	case	WSAENOTEMPTY:		return	"Directory not empty";
	case	WSAEPROCLIM:		return	"Too many processes";
	case	WSAEUSERS:		return	"Too many users";
	case	WSAEDQUOT:		return	"Disc quota exceeded";
	case	WSAESTALE:		return	"Stale NFS file handle";
	case	WSAEREMOTE:		return	"Too many levels of remote in path";

	case	WSAEDISCON:		return	"Graceful shutdown in progress";

	case	WSASYSNOTREADY:		return	"Network system is unavailable";
	case	WSAVERNOTSUPPORTED:	return	"Winsock version out of range";
	case	WSANOTINITIALISED:	return	"WSAStartup not yet called";

	case	WSAHOST_NOT_FOUND:	return	"Host not found";

	case	WSATRY_AGAIN:		return	"WSATRY_AGAIN";

	case	WSANO_RECOVERY:		return	"WSANO_RECOVERY";

	case	WSANO_DATA:		return	"No host data of that type was found";
#endif
	default:			return	"Unknown";
		break;
	}
	return	"";
}

⌨️ 快捷键说明

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