Beispiel #1
0
void CSocketClient::Write( const char *pData, size_t dataLength )
{
	if ( INVALID_SOCKET != m_connectSocket &&
		dataLength > 0 &&
		pData )
	{
		CIOBuffer *pBuffer = Allocate();
		
		/*
		 * Call to unqualified virtual function
		 */
		PreWrite( pBuffer, pData, dataLength );

		pBuffer->AddData( pData, dataLength );

		/*
		 * Begin to send data
		 */
		pBuffer->SetupWrite();
		
		DWORD dwFlags = 0;
		DWORD dwSendNumBytes = 0;
		
		if ( SOCKET_ERROR == ::WSASend(
					m_connectSocket,
					pBuffer->GetWSABUF(), 
					1, 
					&dwSendNumBytes,
					dwFlags,
					pBuffer, 
					NULL) )
		{
			DWORD lastError = ::WSAGetLastError();
			
			if ( ERROR_IO_PENDING != lastError )
			{
				Output( _T("CSocketClient::Write() - WSASend: ") + GetLastErrorMessage( lastError ) );
				
				if ( lastError == WSAECONNABORTED || 
					lastError == WSAECONNRESET ||
					lastError == WSAEDISCON)
				{
					StopConnections();
				}
			}
		}
		
		if ( pBuffer->GetUsed() != pBuffer->GetWSABUF()->len )
		{
			/*
			 * Call to unqualified virtual function
			 */
			//OnError(_T("CSocketClient::WriteCompleted - Socket write where not all data was written"));
		}

		pBuffer->Release();
	}
}
Beispiel #2
0
CIOBuffer *CGameClient::ProcessDataStream( OnlineGameLib::Win32::CIOBuffer *pBuffer)
{
	bool done;
	
//	DEBUG_ONLY( Output( _T("ProcessDataStream:\n") + DumpData( pBuffer->GetBuffer(), pBuffer->GetUsed(), 40 ) ) );
	
	do
	{
		done = true;
		
		const size_t used = pBuffer->GetUsed();
		
		if ( used >= GetMinimumMessageSize() )
		{
			const size_t messageSize = GetMessageSize( pBuffer );
			
			if ( messageSize == 0 )
			{
				/*
				 * havent got a complete message yet.
				
				 * we null terminate our messages in the buffer, so we need to reserve
				 * a byte of the buffer for this purpose...
				 */
				
				if ( used == ( pBuffer->GetSize() - 1 ) )
				{
					Output( _T("Too much data!") );
					
					/*
					 * Write this message and then shutdown the sending side of the socket.
					 */
					Output( "found error and close this connection!" );
		
					StopConnections();
					
					/*
					 * throw the rubbish away
					 */
					pBuffer->Empty();
					
					done = true;
				}
			}
			else if ( used == messageSize )
			{
				Output( _T("Got complete, distinct, message") );
				/*
				 * we have a whole, distinct, message
				 */
				
				pBuffer->AddData(0);   // null terminate the command string;
				
				ProcessCommand( pBuffer );
				
				pBuffer->Empty();
				
				done = true;
			}
			else if (used > messageSize)
			{
				Output(_T("Got message plus extra data"));
				/*
				 * we have a message, plus some more data
				 * 
				 * allocate a new buffer, copy the extra data into it and try again...
				 */
				
				CIOBuffer *pMessage = pBuffer->SplitBuffer( messageSize );
				
				pMessage->AddData(0);   // null terminate the command string;
				
				ProcessCommand( pMessage );
				
				pMessage->Release();
				
				/*
				 * loop again, we may have another complete message in there...
				 */
				
				done = false;
			}
		}
	}
	while ( !done );
	
	/*
	 * not enough data in the buffer, reissue a read into the same buffer to collect more data
	 */
	return pBuffer;
}
Beispiel #3
0
	void CTcpSocket::on_inter_close(int errid, bool bconnecting)
	{
		if (m_status != status_connect && m_status != status_common) return;

		XH_GUARD([&]{
			closetcpsocket(m_socket);
			m_socket = INVALID_SOCKET;

			if (m_io)
			{
				if ((m_bassign & 0x01) == 0x01)
					m_io->Del_Event(&m_ev_read);
				if ((m_bassign & 0x02) == 0x02)
					m_io->Del_Event(&m_ev_write);

				m_bassign = 0;
				m_io->Del_TcpSocket(this);
			}
		});

		m_status = status_null;

		switch (m_type)
		{
		case type_listener:
			if (m_lcb)
			{
				if (bconnecting)
				{
					m_lcb->On_Listen(GetSocketID(), errid);
				}

				m_lcb->On_Close(GetSocketID(), errid);
			}
			break;
		case type_accepter:
			if (m_acb)
			{
				if (bconnecting)
				{
					m_acb->On_Connect(GetSocketID(), errid);
				}

				while (!m_wait_send.empty())
				{
					CIOBuffer* tmpbuf = m_wait_send.front();
					XH_GUARD([&]{tmpbuf->Release(); });

					m_acb->On_Send(GetSocketID(), errid, tmpbuf);

					m_wait_send.pop();
				}

				while (!m_wait_recv.empty())
				{
					CIOBuffer* tmpbuf = m_wait_recv.front();
					XH_GUARD([&]{tmpbuf->Release(); });

					m_acb->On_Recv(GetSocketID(), errid, tmpbuf);

					m_wait_recv.pop();
				}

				m_acb->On_Close(GetSocketID(), errid);

				// 异常调度行为检查
				while (!m_wait_send.empty())
				{
					CIOBuffer* tmpbuf = m_wait_send.front();
					XH_GUARD([&]{tmpbuf->Release(); });

					m_wait_send.pop();
				}
				while (!m_wait_recv.empty())
				{
					CIOBuffer* tmpbuf = m_wait_recv.front();
					XH_GUARD([&]{tmpbuf->Release(); });

					m_wait_recv.pop();
				}
			}
			break;
		case type_connecter:
			if (m_ccb)
			{
				if (bconnecting)
				{
					m_ccb->On_Connect(GetSocketID(), errid);
				}

				while (!m_wait_send.empty())
				{
					CIOBuffer* tmpbuf = m_wait_send.front();
					XH_GUARD([&]{tmpbuf->Release(); });

					m_ccb->On_Send(GetSocketID(), errid, tmpbuf);

					m_wait_send.pop();
				}

				while (!m_wait_recv.empty())
				{
					CIOBuffer* tmpbuf = m_wait_recv.front();
					XH_GUARD([&]{tmpbuf->Release(); });

					m_ccb->On_Recv(GetSocketID(), errid, tmpbuf);

					m_wait_recv.pop();
				}

				m_ccb->On_Close(GetSocketID(), errid);

				// 异常调度行为检查
				while (!m_wait_send.empty())
				{
					CIOBuffer* tmpbuf = m_wait_send.front();
					XH_GUARD([&]{tmpbuf->Release(); });

					m_wait_send.pop();
				}
				while (!m_wait_recv.empty())
				{
					CIOBuffer* tmpbuf = m_wait_recv.front();
					XH_GUARD([&]{tmpbuf->Release(); });

					m_wait_recv.pop();
				}
			}
			break;
		default:
			break;
		}

		XH_LOG_INFO(logname_base, "[id:" << m_id << "] tcpsocket closed by errid : "<<errid);
	}
Beispiel #4
0
	void CTcpSocket::on_inter_send(short flag)
	{
		if (m_status == status_connect)
		{
			if ((flag&EV_WRITE) == EV_WRITE)
			{
				m_status = status_common;

				switch (m_type)
				{
				case type_accepter:
					if (m_acb)
					{
						m_acb->On_Connect(GetSocketID(), tcp_ok);
					}
					break;
				case type_connecter:
					if (m_ccb)
					{
						m_ccb->On_Connect(GetSocketID(), tcp_ok);
					}
					break;
				default:
					break;
				}
			}
			else
			{
				XH_LOG_ERROR(logname_base, "[id:" << m_id << "] tcpsocket connect timeout");
				on_inter_close(tcp_connectfail_timeout, true);

				return;
			}
		}
		else
		{
			while (!m_wait_send.empty())
			{
				CIOBuffer* buff = m_wait_send.front();

				if ( buff->AvailRead()==0 )
				{
					XH_LOG_ERROR(logname_base, "[id:" << m_id << "] tcpsocket::send close cmd");
					on_inter_close(tcp_close_byreset, false);
					return;
				}

				bool bneedbreak = false;
				int sendlen = ::send(m_socket, buff->GetCurRead(), buff->AvailRead(), 0);

				if ( sendlen>0 )
				{
					buff->SeekRead(sendlen);
				}
				else if (sendlen<0)
				{
					if (isnoblockerr())
					{
						bneedbreak = true;
					}
					else
					{
						XH_LOG_ERROR(logname_base, "[id:" << m_id << "] tcpsocket::send failed send - 1");
						on_inter_close(tcp_sendfail_senderr, false);
						return;
					}
				}
				else
				{
					bneedbreak = true;
				}

				//已经写完了,则回调通知
				if (buff->AvailRead()==0)
				{
					switch (m_type)
					{
					case type_accepter:
						if (m_acb)
						{
							m_acb->On_Send(GetSocketID(), tcp_ok, buff);
						}
						break;
					case type_connecter:
						if (m_ccb)
						{
							m_ccb->On_Send(GetSocketID(), tcp_ok, buff);
						}
						break;
					default:
						break;
					}

					m_wait_send.pop();
					buff->Release();
				}

				if (bneedbreak) break;
			}
		}

		if (m_wait_send.empty())
		{
			m_io->Del_Event(&m_ev_write);
		}
	}
Beispiel #5
0
	void CTcpSocket::on_inter_recv(short flag)
	{
		if (m_wait_recv.empty())
		{
			m_io->Del_Event(&m_ev_read);
			return;
		}

		CIOBuffer* recvbuff = m_wait_recv.front();

		int recvlen = ::recv(m_socket, recvbuff->GetCurWrite(), recvbuff->AvailWrite(), 0);
		if (recvlen == 0)
		{
			XH_LOG_INFO(logname_base, "[id:" << m_id << "] tcpsocket::recv failed, closed by peer");
			on_inter_close(tcp_recvfail_closedbypeer, false);
			return;
		}
		else if (recvlen < 0)
		{
			if (isnoblockerr())
			{
				;
			}
			else
			{
				XH_LOG_WARN(logname_base, "[id:" << m_id << "] tcpsocket::recv failed, recv - 1");
				on_inter_close(tcp_recvfail_recverr, false);
			}
			return;
		}

		bool bneedcb = false;
		recvbuff->SeekWrite(recvlen);
		// 如果是readsome
		if ( recvbuff->GetTag()==1 )
		{
			bneedcb = true;
		}
		// 如果是读固定长度
		else
		{
			// 如果读全了
			if (recvbuff->AvailWrite()==0)
			{
				bneedcb = true;
			}
		}

		if ( !bneedcb )
		{
			return;
		}

		switch (m_type)
		{
		case type_accepter:
			if (m_acb)
			{
				m_acb->On_Recv(GetSocketID(), tcp_ok, recvbuff);
			}
			break;
		case type_connecter:
			if (m_ccb)
			{
				m_ccb->On_Recv(GetSocketID(), tcp_ok, recvbuff);
			}
			break;
		default:
			break;
		}

		m_wait_recv.pop();
		recvbuff->Release();

		// 没有可以接收的缓存,则删除事件
		if (m_wait_recv.empty())
		{
			m_io->Del_Event(&m_ev_read);
		}
	}
void CThreadPoolWorkerThread::Process(
	ULONG_PTR completionKey,
	DWORD operation,
	OVERLAPPED *pOverlapped)
{
	CSocketServer::Socket *pSocket = reinterpret_cast<CSocketServer::Socket *>(completionKey);
	CIOBuffer *pBuffer = static_cast<CIOBuffer *>(pOverlapped);

	try
	{
		switch (operation)
		{
		case CThreadPool::ConnectionEstablished:

			OnConnectionEstablished(pSocket, pBuffer);

			break;

		case CThreadPool::ReadCompleted:

			ProcessMessage(pSocket, pBuffer);

			break;

		case CThreadPool::ConnectionClosing:

			OnConnectionClosing(pSocket);

			break;

		case CThreadPool::ConnectionClosed:

			OnConnectionClosed(pSocket);

			break;

		default:

			// do nothing

			break;
		}
	}
	catch (const CException &e)
	{
		Output(_T("Process - Exception - ") + e.GetWhere() + _T(" - ") + e.GetMessage());
		std::string strMsg = e.GetWhere() + _T(" - ") + e.GetMessage();
		pSocket->Write(strMsg.c_str(), strMsg.size());
		pSocket->Shutdown();
	}
	catch (...)
	{
		Output(_T("Process - Unexpected exception"));
		std::string strMsg = _T("Process - Unexpected exception");
		pSocket->Write(strMsg.c_str(), strMsg.size());
		pSocket->Shutdown();
	}

	pSocket->Release();

	if (pBuffer)
	{
		pBuffer->Release();
	}
}
Beispiel #7
0
int CSocketClient::Run()
{
	try
	{		
		HANDLE handlesToWaitFor[2];
		
		handlesToWaitFor[0] = m_shutdownEvent.GetEvent();
		handlesToWaitFor[1] = m_successConnectionsEvent.GetEvent();
		
		while ( !m_shutdownEvent.Wait( 0 ) )
		{
			DWORD waitResult = ::WaitForMultipleObjects( 2, handlesToWaitFor, false, INFINITE );
			
			if ( waitResult == WAIT_OBJECT_0 )
			{
				/*
				 * Time to shutdown
				 */
				break;
			}
			else if ( waitResult == WAIT_OBJECT_0 + 1 )
			{
				/*
				 * Allocate a buffer for required read
				 */
				CIOBuffer *pReadContext = Allocate();

				while ( !m_shutdownEvent.Wait( 0 ) && m_successConnectionsEvent.Wait( 0 ) )
				{
					if ( m_eventSelect.WaitForEnumEvent( m_connectSocket, 1000 ) )
					{
						/*
						 * Find some events and process it
						 */
						
						/*
						 * A event to connect
						 */
						if ( m_eventSelect.IsConnect() )
						{
							OnConnect();						
						}

						/*
						 * A event to close
						 */
						if ( m_eventSelect.IsClose() )
						{
							OnClose();						
						}

						/*
						 * A event to read
						 */
						if ( m_eventSelect.IsRead() )
						{
							OnRead( pReadContext );
						}

						/*
						 * A event to write
						 */
						if ( m_eventSelect.IsWrite() )
						{
							OnWrite();
						}
					}
				} // while (...

				pReadContext->Release();
			}
			else
			{
				/*
				 * Call to unqualified virtual function
				 */
				OnError( _T("CSocketClient::Run() - WaitForMultipleObjects: ") + GetLastErrorMessage( ::GetLastError() ) );
			}
			
		} // while ( ... 		
	}
	catch( const CException &e )
	{
		/*
		 * Call to unqualified virtual function
		 */
		OnError( _T("CSocketClient::Run() - Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
	}
	catch(...)
	{
		/*
		 * Call to unqualified virtual function
		 */
		OnError( _T("CSocketClient::Run() - Unexpected exception") );
	}
	
	/*
	 * Call to unqualified virtual function
	 */
	OnShutdownComplete();
	
	return 0;
}
Beispiel #8
0
int CSocketServer::WorkerThread::Run()
{
	try
	{
		while ( true )
		{
			/*
			 * Continually loop to service io completion packets
			 */
			
			bool closeSocket = false;
			
			DWORD dwIoSize = 0;
			Socket *pSocket = 0;
			CIOBuffer *pBuffer = 0;
			
			try
			{
				m_iocp.GetStatus( (PDWORD_PTR)&pSocket, &dwIoSize, (OVERLAPPED **)&pBuffer );
			}
			catch (const CWin32Exception &e)
			{
				if ( e.GetError() != ERROR_NETNAME_DELETED &&
					e.GetError() != WSA_OPERATION_ABORTED )
				{
					throw;
				}
				
				Output( _T("IOCP error [client connection dropped] - ") +
					GetLastErrorMessage( ::WSAGetLastError() ) );
				
				closeSocket = true;
			}
			
			if ( !pSocket )
			{
				/*
				 * A completion key of 0 is posted to the iocp to request us to shut down...
				 */
				
				break;
			}
			
			/*
			 * Call to unqualified virtual function
			 */
			OnBeginProcessing();
			
			if ( pBuffer )
			{
				const IO_Operation operation = static_cast<IO_Operation>( pBuffer->GetUserData() );
				
				switch ( operation )
				{
				case IO_Read_Request:
					
					Read( pSocket, pBuffer );
					
					break;
					
				case IO_Read_Completed :
					
					if ( 0 != dwIoSize )
					{
						pBuffer->Use( dwIoSize );
						
						//DEBUG_ONLY( Output(_T("RX: ") + ToString(pBuffer) + _T("\n") + DumpData(reinterpret_cast<const BYTE*>( pBuffer->GetWSABUF()->buf), dwIoSize, 40) ) );
						
						/*
						 * Call to unqualified virtual function
						 */
						ReadCompleted( pSocket, pBuffer );
					}
					else
					{
						/*
						 * client connection dropped...
						 */
						
						Output( _T("ReadCompleted - 0 bytes - client connection dropped") );
						
						closeSocket = true;
					}
					
					pSocket->Release();
					pBuffer->Release();
					
					break;
					
				case IO_Write_Request :
					
					Write( pSocket, pBuffer );
					
					if ( dwIoSize != 0 )
					{
						/*
						 * final write, now shutdown send side of connection
						 */
						pSocket->Shutdown( SD_SEND );
					}
					
					break;
					
				case IO_Write_Completed :
					
					pBuffer->Use( dwIoSize );
					
					//DEBUG_ONLY( Output(_T("TX: ") + ToString(pBuffer) + _T("\n") + DumpData(reinterpret_cast<const BYTE*>( pBuffer->GetWSABUF()->buf), dwIoSize, 40) ) );
					
					/*
					 * Call to unqualified virtual function
					 */
					WriteCompleted( pSocket, pBuffer );
					
					pSocket->Release();
					pBuffer->Release();
					
					break;
					
				case IO_Close :
					
					AbortiveClose( pSocket );
					
					pSocket->Release();
					pBuffer->Release();
					
					break;
					
				default :
					/*
					 * all to unqualified virtual function
					 */
					OnError( _T("CSocketServer::WorkerThread::Run() - Unexpected operation") );
					break;
				} 
			}
			else
			{
				/*
				 * Call to unqualified virtual function
				 */
				OnError( _T("CSocketServer::WorkerThread::Run() - Unexpected - pBuffer is 0") );
			}
			
			if ( closeSocket )
			{
				pSocket->Close();
			}
			
			/*
			 * Call to unqualified virtual function
			 */
			OnEndProcessing();
      } 
   }
   catch(const CException &e)
   {
	   /*
	    * Call to unqualified virtual function
		*/
	   OnError( _T("CSocketServer::WorkerThread::Run() - Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
   }
   catch(...)
   {
	   /*
	    * Call to unqualified virtual function
		*/
	   OnError( _T("CSocketServer::WorkerThread::Run() - Unexpected exception") );
   }
   
   return 0;
}
Beispiel #9
0
int CSocketServer::Run()
{
	try
	{
		vector<WorkerThread *> workers;
		
		workers.reserve( m_numThreads );
		
		for ( size_t i = 0; i < m_numThreads; ++i )
		{
			/*
			 * Call to unqualified virtual function
			 */
			WorkerThread *pThread = CreateWorkerThread( m_iocp ); 
			
			workers.push_back( pThread );
			
			pThread->Start();
		}
		
		HANDLE handlesToWaitFor[2];
		
		handlesToWaitFor[0] = m_shutdownEvent.GetEvent();
		handlesToWaitFor[1] = m_acceptConnectionsEvent.GetEvent();
		
		while ( !m_shutdownEvent.Wait( 0 ) )
		{
			DWORD waitResult = ::WaitForMultipleObjects( 2, handlesToWaitFor, false, INFINITE );
			
			if ( waitResult == WAIT_OBJECT_0 )
			{
				/*
				 * Time to shutdown
				 */
				break;
			}
			else if ( waitResult == WAIT_OBJECT_0 + 1 )
			{
				/*
				 * accept connections
				 */
				
				while ( !m_shutdownEvent.Wait( 0 ) && m_acceptConnectionsEvent.Wait( 0 ) )
				{
					CIOBuffer *pAddress = Allocate();
					
					int addressSize = (int)pAddress->GetSize();
					
					SOCKET acceptedSocket = ::WSAAccept(
									m_listeningSocket, 
									reinterpret_cast<sockaddr *>(const_cast<BYTE *>( pAddress->GetBuffer() ) ), 
									&addressSize, 
									0, 
									0);
					
					pAddress->Use( addressSize );
					
					if ( acceptedSocket != INVALID_SOCKET )
					{
						Socket *pSocket = AllocateSocket( acceptedSocket );
						
						/*
						 * Call to unqualified virtual function
						 */
						OnConnectionEstablished( pSocket, pAddress );
					}
					else if ( m_acceptConnectionsEvent.Wait( 0 ) )
					{
						/*
						 * Call to unqualified virtual function
						 */
						OnError( _T("CSocketServer::Run() - WSAAccept:") + GetLastErrorMessage( ::WSAGetLastError() ) );
					}
					
					pAddress->Release();
				}
			}
			else
			{
				/*
				 * Call to unqualified virtual function
				 */
				OnError( _T("CSocketServer::Run() - WaitForMultipleObjects: ") + GetLastErrorMessage( ::GetLastError() ) );
			}
		}
		
		for ( i = 0; i < m_numThreads; ++i )
		{
			workers[i]->InitiateShutdown();
		}  
		
		for ( i = 0; i < m_numThreads; ++i )
		{
			workers[i]->WaitForShutdownToComplete();
			
			delete workers[i];
			
			workers[i] = 0;
		}  
	}
	catch( const CException &e )
	{
		/*
		 * Call to unqualified virtual function
		 */
		OnError( _T("CSocketServer::Run() - Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
	}
	catch(...)
	{
		/*
		 * Call to unqualified virtual function
		 */
		OnError( _T("CSocketServer::Run() - Unexpected exception") );
	}
	
	/*
	 * Call to unqualified virtual function
	 */
	OnShutdownComplete();
	
	return 0;
}