+ Reply to Thread
Results 1 to 8 of 8

Thread: Требуется описание параметров сокетов, win32, протокол TCP/IP, примеры использования, оптимальность применения

  1. #1
    V3T's Avatar

    Exclamation Требуется описание параметров сокетов, win32, протокол TCP/IP, примеры использования, оптимальность применения

    Друзья, я тут в сети, пытался найти интересную информацию по сокетам, но черт ногу сломит, половина манов для линукса.

    Особенно интересуют варианты реализации отправки большого количества маленьких пакетов, с наименьшими задержками.

    Немного мануалов от себя: (http://www.opennet.ru/man.shtml?topi...ry=2&russian=0 )
    getsockopt, setsockopt - получить или установить флаги на сокете
    ОБЗОР
    #include <sys/types.h>
    #include <sys/socket.h>

    int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);

    int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
    ОПИСАНИЕ
    getsockopt и setsockopt манипулируют флагами, установленными на сокете. Флаги могут существовать на нескольких уровнях протоколов; они всегда присутствуют на самом верхнем из них.

    При манипулировании флагами сокета должен быть указан уровень, на котором находится этот флаг, и имя этого флага. Для манипуляции флагами на уровне сокета level задается как SOL_SOCKET. Для манипуляции флагами на любом другом уровне этим функциям передается номер соответствующего протокола, управляющего флагами. Например, для указания, что флаг должен интерпретироваться протоколом TCP, в параметре level должен передаваться номер протокола TCP; смотри описание getprotoent(3).

    Параметры optval и optlen используются в функции setsockopt для доступа к значениям флагов. Для getsockopt они задают буфер, в который нужно поместить запрошенное значение. Для getsockopt параметр optlen передается по ссылке. При вызове он содержит размер буфера, на который указывает параметр optval, а после вызова -- реальный размер возвращенного значения. Если значение флага не используется, то параметр optval может быть NULL.

    optname и все указанные флаги без изменений передаются для интерпретации соответствующему модулю протоколов. Файл <sys/socket.h> содержит определения флагов уровня сокета, описанные ниже. Флаги на других уровнях протоколов различаются по формату и по имени. Обращайтесь к соответствующим пунктам секции 4 руководства.

    Большинство флагов уровня сокета используют тип int для параметра optval. Для функции setsockopt, параметр должен быть ненулевым, чтобы установить флаг логического типа, или нуль, чтобы сбросить этот флаг.


    Описание доступных флагов сокетов находится в socket(7) и соответствующих протоколам страницах руководства.

    Вот например реализация добавления к сокету параметра отключения алгоритма Нагла, но говорят это не помогает: http://developerweb.net/viewtopic.php?id=3716
    Типо и CORK и NO_DELAY не лучше чем включенный нагл
    Code:
    void CTCPSocket :: SetNoDelay( bool noDelay )
    {
    	int OptVal = 0;
    
    	if( noDelay )
    		OptVal = 1;
    
    	setsockopt( m_Socket, IPPROTO_TCP, TCP_NODELAY, (const char *)&OptVal, sizeof( int ) );
    }
    Небольшое описание сокетов на майкрософте:
    http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx

    А теперь вопрос к знатокам, напишите пожалуйста все секреты сокетах о которых вы бы хотели рассказать новичкам, эффективно ли использование статичных буферов SO_RCVBUF \ SO_SNDBUF, как создать минимальную нагрузку на процессор и максимально снизить время обработки пакетов?

    Для тех кто хорошо владеет cpp предлагаю немного проанализировать эффективность небольшого кода, какие предложения по увеличению производительности стека вы порекоммендуете? Код рабочий
    Code:
    /*
    
       Copyright [2008] [Trevor Hogan]
    
       Licensed under the Apache License, Version 2.0 (the "License");
       you may not use this file except in compliance with the License.
       You may obtain a copy of the License at
    
           http://www.apache.org/licenses/LICENSE-2.0
    
       Unless required by applicable law or agreed to in writing, software
       distributed under the License is distributed on an "AS IS" BASIS,
       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       See the License for the specific language governing permissions and
       limitations under the License.
    
       CODE PORTED FROM THE ORIGINAL GHOST PROJECT: http://ghost.pwner.org/
    
       Socket R560 + CUSTOM FIXies http://ghostplusplus.googlecode.com/svn-history/r560/trunk/ghost/socket.cpp
    */
    
    #include "ghost.h"
    #include "util.h"
    #include "socket.h"
    
    #include <string.h>
    
    #ifndef WIN32
     int GetLastError( ) { return errno; }
    #endif
    
    //
    // CSocket
    //
    
    CSocket :: CSocket( ) :  m_Socket( INVALID_SOCKET ), m_HasError( false ), m_Error( 0 )
    {
            memset( &m_SIN, 0, sizeof( m_SIN ) );
    }
    
    CSocket :: CSocket( SOCKET nSocket, struct sockaddr_in nSIN ) : m_Socket( nSocket ), m_SIN( nSIN ), bool isConsolePrint , m_HasError( false ), m_Error( 0 )
    {
    
    }
    
    CSocket :: ~CSocket( )
    {
    	if( m_Socket != INVALID_SOCKET )
    		closesocket( m_Socket );
    }
    
    BYTEARRAY CSocket :: GetPort( )
    {
    	return UTIL_CreateByteArray( m_SIN.sin_port, false );
    }
    
    BYTEARRAY CSocket :: GetIP( )
    {
    	return UTIL_CreateByteArray( (uint32_t)m_SIN.sin_addr.s_addr, false );
    }
    
    string CSocket :: GetIPString( )
    {
    	return inet_ntoa( m_SIN.sin_addr );
    }
    
    string CSocket :: GetErrorString( )
    {
    	if( !m_HasError )
    		return "NO ERROR";
    
    	switch( m_Error )
    	{
    	case EWOULDBLOCK: return "EWOULDBLOCK";
    	case EINPROGRESS: return "EINPROGRESS";
    	case EALREADY: return "EALREADY";
    	case ENOTSOCK: return "ENOTSOCK";
    	case EDESTADDRREQ: return "EDESTADDRREQ";
    	case EMSGSIZE: return "EMSGSIZE";
    	case EPROTOTYPE: return "EPROTOTYPE";
    	case ENOPROTOOPT: return "ENOPROTOOPT";
    	case EPROTONOSUPPORT: return "EPROTONOSUPPORT";
    	case ESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT";
    	case EOPNOTSUPP: return "EOPNOTSUPP";
    	case EPFNOSUPPORT: return "EPFNOSUPPORT";
    	case EAFNOSUPPORT: return "EAFNOSUPPORT";
    	case EADDRINUSE: return "EADDRINUSE";
    	case EADDRNOTAVAIL: return "EADDRNOTAVAIL";
    	case ENETDOWN: return "ENETDOWN";
    	case ENETUNREACH: return "ENETUNREACH";
    	case ENETRESET: return "ENETRESET";
    	case ECONNABORTED: return "ECONNABORTED";
    	case ECONNRESET: return "ECONNRESET";
    	case ENOBUFS: return "ENOBUFS";
    	case EISCONN: return "EISCONN";
    	case ENOTCONN: return "ENOTCONN";
    	case ESHUTDOWN: return "ESHUTDOWN";
    	case ETOOMANYREFS: return "ETOOMANYREFS";
    	case ETIMEDOUT: return "ETIMEDOUT";
    	case ECONNREFUSED: return "ECONNREFUSED";
    	case ELOOP: return "ELOOP";
    	case ENAMETOOLONG: return "ENAMETOOLONG";
    	case EHOSTDOWN: return "EHOSTDOWN";
    	case EHOSTUNREACH: return "EHOSTUNREACH";
    	case ENOTEMPTY: return "ENOTEMPTY";
    	case EUSERS: return "EUSERS";
    	case EDQUOT: return "EDQUOT";
    	case ESTALE: return "ESTALE";
    	case EREMOTE: return "EREMOTE";
    	}
    
    	return "UNKNOWN ERROR (" + UTIL_ToString( m_Error ) + ")";
    }
    
    void CSocket :: SetFD( fd_set *fd, fd_set *send_fd, int *nfds )
    {
    	if( m_Socket == INVALID_SOCKET )
    		return;
    
    	FD_SET( m_Socket, fd );
    	FD_SET( m_Socket, send_fd );
    
    #ifndef WIN32
    	if( m_Socket > *nfds )
    		*nfds = m_Socket;
    #endif
    }
    
    void CSocket :: Allocate( int type )
    {
    	m_Socket = socket( AF_INET, type, 0 );
    
    	if( m_Socket == INVALID_SOCKET )
    	{
    		m_HasError = true;
    		m_Error = GetLastError( );
    		CONSOLE_Print( "[SOCKET] error (socket) - " + GetErrorString( ) );
    		return;
    	}
    }
    
    void CSocket :: Reset( )
    {
    	if( m_Socket != INVALID_SOCKET )
    		closesocket( m_Socket );
    
    	m_Socket = INVALID_SOCKET;
    	memset( &m_SIN, 0, sizeof( m_SIN ) );
    	m_HasError = false;
    	m_Error = 0;
    }
    
    //
    // CTCPSocket
    //
    
    CTCPSocket :: CTCPSocket( ) : CSocket( ), m_Connected( false ), m_LastRecv( GetTime( ) ), m_LastSend( GetTime( ) )
    {
    	Allocate( SOCK_STREAM );
    
    	// make socket non blocking
    
    #ifdef WIN32
    	int iMode = 1;
    	ioctlsocket( m_Socket, FIONBIO, (u_long FAR *)&iMode );
    #else
    	fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK );
    #endif
    }
    
    CTCPSocket :: CTCPSocket( SOCKET nSocket, struct sockaddr_in nSIN ) : CSocket( nSocket, nSIN )
    {
    	m_Connected = true;
    	m_LastRecv = GetTime( );
    	m_LastSend = GetTime( );
    
    	// make socket non blocking
    
    #ifdef WIN32
    	int iMode = 1;
    	ioctlsocket( m_Socket, FIONBIO, (u_long FAR *)&iMode );
    #else
    	fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK );
    #endif
    }
    
    CTCPSocket :: ~CTCPSocket( )
    {
    
    }
    
    void CTCPSocket :: Reset( )
    {
    	CSocket :: Reset( );
    
    	Allocate( SOCK_STREAM );
    	m_Connected = false;
    	m_RecvBuffer.clear( );
    	m_SendBuffer.clear( );
    	m_LastRecv = GetTime( );
    	m_LastSend = GetTime( );
    
    	// make socket non blocking
    
    #ifdef WIN32
    	int iMode = 1;
    	ioctlsocket( m_Socket, FIONBIO, (u_long FAR *)&iMode );
    #else
    	fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK );
    #endif
    
    	if( !m_LogFile.empty( ) )
    	{
    		ofstream Log;
    		Log.open( m_LogFile.c_str( ), ios :: app );
    
    		if( !Log.fail( ) )
    		{
    			Log << "----------RESET----------" << endl;
    			Log.close( );
    		}
    	}
    }
    
    void CTCPSocket :: PutBytes( string bytes )
    {
    	m_SendBuffer += bytes;
    }
    
    void CTCPSocket :: PutBytes( BYTEARRAY bytes )
    {
    	m_SendBuffer += string( bytes.begin( ), bytes.end( ) );
    }
    
    void CTCPSocket :: DoRecv( fd_set *fd )
    {
    	if( m_Socket == INVALID_SOCKET || m_HasError || !m_Connected )
    		return;
    
    	if( FD_ISSET( m_Socket, fd ) )
    	{
    		// data is waiting, receive it
    
    		char buffer[1024];
    		int c = recv( m_Socket, buffer, 1024, 0 );
    		
    		if( c > 0 )
    		{
    			// success! add the received data to the buffer
    
    			if( !m_LogFile.empty( ) )
    			{
    				ofstream Log;
    				Log.open( m_LogFile.c_str( ), ios :: app );
    
    				if( !Log.fail( ) )
    				{
    					Log << "					RECEIVE <<< " << UTIL_ByteArrayToHexString( UTIL_CreateByteArray( (unsigned char *)buffer, c ) ) << endl;
    					Log.close( );
    				}
    			}
    
    			m_RecvBuffer += string( buffer, c );
    			m_LastRecv = GetTime( );
    		}
    		else if( c == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK )
    		{
    			// receive error
    
    			m_HasError = true;
    			m_Error = GetLastError( );
    			CONSOLE_Print( "[TCPSOCKET] error (recv) - " + GetErrorString( ) );
    			return;
    		}
    		else if( c == 0 )
    		{
    			// the other end closed the connection
    
    			CONSOLE_Print( "[TCPSOCKET] closed by remote host" );
    			m_Connected = false;
    		}
    	}
    }
    
    void CTCPSocket :: DoSend( fd_set *send_fd )
    {
    	if( m_Socket == INVALID_SOCKET || m_HasError || !m_Connected || m_SendBuffer.empty( ) )
    		return;
    
    	if( FD_ISSET( m_Socket, send_fd ) )
    	{
    		// socket is ready, send it
    
    		int s = send( m_Socket, m_SendBuffer.c_str( ), (int)m_SendBuffer.size( ), MSG_NOSIGNAL );
    		
    		if( s > 0 )
    		{
    			// success! only some of the data may have been sent, remove it from the buffer
    
    			if( !m_LogFile.empty( ) )
    			{
    				ofstream Log;
    				Log.open( m_LogFile.c_str( ), ios :: app );
    
    				if( !Log.fail( ) )
    				{
    					Log << "SEND >>> " << UTIL_ByteArrayToHexString( BYTEARRAY( m_SendBuffer.begin( ), m_SendBuffer.begin( ) + s ) ) << endl;
    					Log.close( );
    				}
    			}
    
    			m_SendBuffer = m_SendBuffer.substr( s );
    			m_LastSend = GetTime( );
    		}
    		else if( s == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK )
    		{
    			// send error
    
    			m_HasError = true;
    			m_Error = GetLastError( );
    			CONSOLE_Print( "[TCPSOCKET] error (send) - " + GetErrorString( ) );
    			return;
    		}
    	}
    }
    
    void CTCPSocket :: Disconnect( )
    {
    	if( m_Socket != INVALID_SOCKET )
    		shutdown( m_Socket, SHUT_RDWR );
    
    	m_Connected = false;
    }
    
    void CTCPSocket :: SetNoDelay( bool noDelay )
    {
    	int OptVal = 0;
    
    	if( noDelay )
    		OptVal = 1;
    
    	setsockopt( m_Socket, IPPROTO_TCP, TCP_NODELAY, (const char *)&OptVal, sizeof( int ) );
    }
    
    //
    // CTCPClient
    //
    
    CTCPClient :: CTCPClient( ) : CTCPSocket( ), m_Connecting( false )
    {
    
    }
    
    CTCPClient :: ~CTCPClient( )
    {
    
    }
    
    void CTCPClient :: Reset( )
    {
    	CTCPSocket :: Reset( );
    	m_Connecting = false;
    }
    
    void CTCPClient :: Disconnect( )
    {
    	CTCPSocket :: Disconnect( );
    	m_Connecting = false;
    }
    
    void CTCPClient :: Connect( string localaddress, string address, uint16_t port )
    {
    	if( m_Socket == INVALID_SOCKET || m_HasError || m_Connecting || m_Connected )
    		return;
    
    	if( !localaddress.empty( ) )
    	{
    		struct sockaddr_in LocalSIN;
    		memset( &LocalSIN, 0, sizeof( LocalSIN ) );
    		LocalSIN.sin_family = AF_INET;
    
    		if( ( LocalSIN.sin_addr.s_addr = inet_addr( localaddress.c_str( ) ) ) == INADDR_NONE )
    			LocalSIN.sin_addr.s_addr = INADDR_ANY;
    
    		LocalSIN.sin_port = htons( 0 );
    // addf ixation if( bind( m_Socket, (struct sockaddr *)&LocalSIN, sizeof( LocalSIN ) ) == SOCKET_ERROR )
    		if( ::bind( m_Socket, (struct sockaddr *)&LocalSIN, sizeof( LocalSIN ) ) == SOCKET_ERROR )
    		{
    			m_HasError = true;
    			m_Error = GetLastError( );
    			CONSOLE_Print( "[TCPCLIENT] error (bind) - " + GetErrorString( ) );
    			return;
    		}
    	}
    
    	// get IP address
    
    	struct hostent *HostInfo;
    	uint32_t HostAddress;
    	HostInfo = gethostbyname( address.c_str( ) );
    
    	if( !HostInfo )
    	{
    		m_HasError = true;
    		// m_Error = h_error;
    		CONSOLE_Print( "[TCPCLIENT] error (gethostbyname)" );
    		return;
    	}
    
    	memcpy( &HostAddress, HostInfo->h_addr, HostInfo->h_length );
    
    	// connect
    
    	m_SIN.sin_family = AF_INET;
    	m_SIN.sin_addr.s_addr = HostAddress;
    	m_SIN.sin_port = htons( port );
    
    	if( connect( m_Socket, (struct sockaddr *)&m_SIN, sizeof( m_SIN ) ) == SOCKET_ERROR )
    	{
    		if( GetLastError( ) != EINPROGRESS && GetLastError( ) != EWOULDBLOCK )
    		{
    			// connect error
    
    			m_HasError = true;
    			m_Error = GetLastError( );
    			CONSOLE_Print( "[TCPCLIENT] error (connect) - " + GetErrorString( ) );
    			return;
    		}
    	}
    
    	m_Connecting = true;
    }
    
    bool CTCPClient :: CheckConnect( )
    {
    	if( m_Socket == INVALID_SOCKET || m_HasError || !m_Connecting )
    		return false;
    
    	fd_set fd;
    	FD_ZERO( &fd );
    	FD_SET( m_Socket, &fd );
    
    	struct timeval tv;
    	tv.tv_sec = 0;
    	tv.tv_usec = 0;
    
    	// check if the socket is connected
    
    #ifdef WIN32
    	if( select( 1, NULL, &fd, NULL, &tv ) == SOCKET_ERROR )
    #else
    	if( select( m_Socket + 1, NULL, &fd, NULL, &tv ) == SOCKET_ERROR )
    #endif
    	{
    		m_HasError = true;
    		m_Error = GetLastError( );
    		return false;
    	}
    
    	if( FD_ISSET( m_Socket, &fd ) )
    	{
    		m_Connecting = false;
    		m_Connected = true;
    		return true;
    	}
    
    	return false;
    }
    
    //
    // CTCPServer
    //
    
    CTCPServer :: CTCPServer( ) : CTCPSocket( )
    {
    	// set the socket to reuse the address in case it hasn't been released yet
    
    	int optval = 1;
    
    #ifdef WIN32
    	setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof( int ) );
    #else
    	setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof( int ) );
    #endif
    }
    
    CTCPServer :: ~CTCPServer( )
    {
    
    }
    
    bool CTCPServer :: Listen( string address, uint16_t port )
    {
    	if( m_Socket == INVALID_SOCKET || m_HasError )
    		return false;
    
    	m_SIN.sin_family = AF_INET;
    
    	if( !address.empty( ) )
    	{
    		if( ( m_SIN.sin_addr.s_addr = inet_addr( address.c_str( ) ) ) == INADDR_NONE )
    			m_SIN.sin_addr.s_addr = INADDR_ANY;
    	}
    	else
    		m_SIN.sin_addr.s_addr = INADDR_ANY;
    
    	m_SIN.sin_port = htons( port );
    
    //	if( bind( m_Socket, (struct sockaddr *)&m_SIN, sizeof( m_SIN ) ) == SOCKET_ERROR )
    	if( ::bind( m_Socket, (struct sockaddr *)&m_SIN, sizeof( m_SIN ) ) == SOCKET_ERROR )
    	{
    		m_HasError = true;
    		m_Error = GetLastError( );
    		CONSOLE_Print( "[TCPSERVER] error (bind) - " + GetErrorString( ) );
    		return false;
    	}
    
    	// listen, queue length 8
    
    	if( listen( m_Socket, 8 ) == SOCKET_ERROR )
    	{
    		m_HasError = true;
    		m_Error = GetLastError( );
    		CONSOLE_Print( "[TCPSERVER] error (listen) - " + GetErrorString( ) );
    		return false;
    	}
    
    	return true;
    }
    
    CTCPSocket *CTCPServer :: Accept( fd_set *fd )
    {
    	if( m_Socket == INVALID_SOCKET || m_HasError )
    		return NULL;
    
    	if( FD_ISSET( m_Socket, fd ) )
    	{
    		// a connection is waiting, accept it
    
    		struct sockaddr_in Addr;
    		int AddrLen = sizeof( Addr );
    		SOCKET NewSocket;
    
    #ifdef WIN32
    		if( ( NewSocket = accept( m_Socket, (struct sockaddr *)&Addr, &AddrLen ) ) == INVALID_SOCKET )
    #else
    		if( ( NewSocket = accept( m_Socket, (struct sockaddr *)&Addr, (socklen_t *)&AddrLen ) ) == INVALID_SOCKET )
    #endif
    		{
    			// accept error, ignore it
    		}
    		else
    		{
    			// success! return the new socket
    
    			return new CTCPSocket( NewSocket, Addr );
    		}
    	}
    
    	return NULL;
    }
    
    //
    // CUDPSocket
    //
    
    CUDPSocket :: CUDPSocket( ) : CSocket( )
    {
    	Allocate( SOCK_DGRAM );
    
    	// enable broadcast support
    
    	int OptVal = 1;
    	setsockopt( m_Socket, SOL_SOCKET, SO_BROADCAST, (const char *)&OptVal, sizeof( int ) );
    	
    	// set default broadcast target
    	m_BroadcastTarget.s_addr = INADDR_BROADCAST;
    }
    
    CUDPSocket :: ~CUDPSocket( )
    {
    
    }
    
    bool CUDPSocket :: SendTo( struct sockaddr_in sin, BYTEARRAY message )
    {
    	if( m_Socket == INVALID_SOCKET || m_HasError )
    		return false;
    
    	string MessageString = string( message.begin( ), message.end( ) );
    
    	if( sendto( m_Socket, MessageString.c_str( ), MessageString.size( ), 0, (struct sockaddr *)&sin, sizeof( sin ) ) == -1 )
    		return false;
    
    	return true;
    }
    
    bool CUDPSocket :: SendTo( string address, uint16_t port, BYTEARRAY message )
    {
    	if( m_Socket == INVALID_SOCKET || m_HasError )
    		return false;
    
    	// get IP address
    
    	struct hostent *HostInfo;
    	uint32_t HostAddress;
    	HostInfo = gethostbyname( address.c_str( ) );
    
    	if( !HostInfo )
    	{
    		m_HasError = true;
    		// m_Error = h_error;
    		CONSOLE_Print( "[UDPSOCKET] error (gethostbyname)" );
    		return false;
    	}
    
    	memcpy( &HostAddress, HostInfo->h_addr, HostInfo->h_length );
    	struct sockaddr_in sin;
    	sin.sin_family = AF_INET;
    	sin.sin_addr.s_addr = HostAddress;
    	sin.sin_port = htons( port );
    
    	return SendTo( sin, message );
    }
    
    bool CUDPSocket :: Broadcast( uint16_t port, BYTEARRAY message )
    {
    	if( m_Socket == INVALID_SOCKET || m_HasError )
    		return false;
    
    	struct sockaddr_in sin;
    	sin.sin_family = AF_INET;
    	sin.sin_addr.s_addr = m_BroadcastTarget.s_addr;
    	sin.sin_port = htons( port );
    
    	string MessageString = string( message.begin( ), message.end( ) );
    
    	if( sendto( m_Socket, MessageString.c_str( ), MessageString.size( ), 0, (struct sockaddr *)&sin, sizeof( sin ) ) == -1 )
    	{
    		CONSOLE_Print( "[UDPSOCKET] failed to broadcast packet (port " + UTIL_ToString( port ) + ", size " + UTIL_ToString( MessageString.size( ) ) + " bytes)" );
    		return false;
    	}
    
    	return true;
    }
    
    void CUDPSocket :: SetBroadcastTarget( string subnet )
    {
    	if( subnet.empty( ) )
    	{
    		CONSOLE_Print( "[UDPSOCKET] using default broadcast target" );
    		m_BroadcastTarget.s_addr = INADDR_BROADCAST;
    	}
    	else
    	{
    		// this function does not check whether the given subnet is a valid subnet the user is on
    		// convert string representation of ip/subnet to in_addr
    
    		CONSOLE_Print( "[UDPSOCKET] using broadcast target [" + subnet + "]" );
    		m_BroadcastTarget.s_addr = inet_addr( subnet.c_str( ) );
    
    		// if conversion fails, inet_addr( ) returns INADDR_NONE
    
    		if( m_BroadcastTarget.s_addr == INADDR_NONE )
    		{
    			CONSOLE_Print( "[UDPSOCKET] invalid broadcast target, using default broadcast target" );
    			m_BroadcastTarget.s_addr = INADDR_BROADCAST;
    		}
    	}
    }
    
    void CUDPSocket :: SetDontRoute( bool dontRoute )
    {
    	int OptVal = 0;
    
    	if( dontRoute )
    		OptVal = 1;
    
    	// don't route packets; make them ignore routes set by routing table and send them to the interface
    	// belonging to the target address directly
    
    	setsockopt( m_Socket, SOL_SOCKET, SO_DONTROUTE, (const char *)&OptVal, sizeof( int ) );
    }
    
    //
    // CUDPServer
    //
    
    CUDPServer :: CUDPServer( ) : CUDPSocket( )
    {
    	// make socket non blocking
    
    #ifdef WIN32
    	int iMode = 1;
    	ioctlsocket( m_Socket, FIONBIO, (u_long FAR *)&iMode );
    #else
    	fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK );
    #endif
    
    	// set the socket to reuse the address
    	// with UDP sockets this allows more than one program to listen on the same port
    
    	int optval = 1;
    
    #ifdef WIN32
    	setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof( int ) );
    #else
    	setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof( int ) );
    #endif
    }
    
    CUDPServer :: ~CUDPServer( )
    {
    
    }
    
    bool CUDPServer :: Bind( struct sockaddr_in sin )
    {
    	if( m_Socket == INVALID_SOCKET || m_HasError )
    		return false;
    
    	m_SIN = sin;
    
    //	if( bind( m_Socket, (struct sockaddr *)&m_SIN, sizeof( m_SIN ) ) == SOCKET_ERROR )
    	if( ::bind( m_Socket, (struct sockaddr *)&m_SIN, sizeof( m_SIN ) ) == SOCKET_ERROR )
    	{
    		m_HasError = true;
    		m_Error = GetLastError( );
    		CONSOLE_Print( "[UDPSERVER] error (bind) - " + GetErrorString( ) );
    		return false;
    	}
    
    	return true;
    }
    
    bool CUDPServer :: Bind( string address, uint16_t port )
    {
    	if( m_Socket == INVALID_SOCKET || m_HasError )
    		return false;
    
    	struct sockaddr_in sin;
    	sin.sin_family = AF_INET;
    
    	if( !address.empty( ) )
    	{
    		if( ( sin.sin_addr.s_addr = inet_addr( address.c_str( ) ) ) == INADDR_NONE )
    			sin.sin_addr.s_addr = INADDR_ANY;
    	}
    	else
    		sin.sin_addr.s_addr = INADDR_ANY;
    
    	sin.sin_port = htons( port );
    
    	return Bind( sin );
    }
    
    void CUDPServer :: RecvFrom( fd_set *fd, struct sockaddr_in *sin, string *message )
    {
    	if( m_Socket == INVALID_SOCKET || m_HasError || !sin || !message )
    		return;
    
    	int AddrLen = sizeof( *sin );
    
    	if( FD_ISSET( m_Socket, fd ) )
    	{
    		// data is waiting, receive it
    
    		char buffer[1024];
    
    #ifdef WIN32
    		int c = recvfrom( m_Socket, buffer, 1024, 0, (struct sockaddr *)sin, &AddrLen );
    #else
    		int c = recvfrom( m_Socket, buffer, 1024, 0, (struct sockaddr *)sin, (socklen_t *)&AddrLen );
    #endif
    
    		if( c > 0 )
    		{
    			// success!
    
    			*message = string( buffer, c );
    		}
    		else if( c == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK )
    		{
    			// receive error
    
    			m_HasError = true;
    			m_Error = GetLastError( );
    			CONSOLE_Print( "[UDPSERVER] error (recvfrom) - " + GetErrorString( ) );
    		}
    	}
    }
    Кстате как я понял в этом коде довольно общие приемы используются, вот ещё вопрос почему задают размер буферов в 1 кб?
    Code:
    recv( m_Socket, buffer, 1024, 0 );
    Примеры использования таких приемов:
    http://svn2.assembla.com/svn/Animati.../cWSClient.cpp
    http://forum.vingrad.ru/act-Print/cl.../t-343358.html
    http://www.gamedev.ru/code/forum/?id=152998

    В сети очень сильно разбросанна информация по всем этим сокетам и половина мануалов находится в состоянии "у меня не работает, помогите, вопрос оставлен без ответа" или какойто беглый мануал на английском языке.
    Реверсинг ПО для незрячих - благородная цель

  2. #2
    root's Avatar

    Default Re: Требуется описание параметров сокетов, win32, протокол TCP/IP, примеры использования, оптимальность применения

    Друзья, я тут в сети, пытался найти интересную информацию по сокетам, но черт ногу сломит, половина манов для линукса.
    Основной мануал для Windows - MSDN.

    у меня не работает, помогите, вопрос оставлен без ответа
    У нормальных людей такие вопросы не возникают. Все читают MSDN и радуются жизни. А различные копипастеры задают подобные вопросы.

    Небольшое описание сокетов на майкрософте:
    http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx
    Фигасе не большое. Там все, что нужно. Посмотрите по сторонам!

    Корень: http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
    Функции: http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx

    К ключевым функциям, в низу, есть примеры кода (например):
    Успех – это путь от провала до провала без потери энтузиазма. (В. Черчиль)

    Не бойся идти медленно, бойся остановиться. (Китайская пословица)

    When you lose fun and start doing things only for the payback, you're dead. (c) TCLH (Phrack 65, Intro)

  3. #3
    V3T's Avatar

    Default Re: Требуется описание параметров сокетов, win32, протокол TCP/IP, примеры использования, оптимальность применения

    Но это ведь все не нашенское и без реккомендаций :)
    хотелось бы мнение человека который в этой сфере давно
    Реверсинг ПО для незрячих - благородная цель

  4. #4
    REU's Avatar

    Default Re: Требуется описание параметров сокетов, win32, протокол TCP/IP, примеры использования, оптимальность применения

    Quote Originally Posted by V3T View Post
    Но это ведь все не нашенское и без реккомендаций :)
    хотелось бы мнение человека который в этой сфере давно
    Ну да, microsoft дети малые.

  5. #5
    V3T's Avatar

    Default Re: Требуется описание параметров сокетов, win32, протокол TCP/IP, примеры использования, оптимальность применения

    Я имею в виду английский язык мануала.
    Реверсинг ПО для незрячих - благородная цель

  6. #6
    REU's Avatar

    Default Re: Требуется описание параметров сокетов, win32, протокол TCP/IP, примеры использования, оптимальность применения

    Quote Originally Posted by V3T View Post
    Я имею в виду английский язык мануала.
    Учите английский на уровне чтения технической документации, без этого далеко не уедите.
    Last edited by REU; 27-03-2012 at 12:51.

  7. 2 пользователя(ей) сказали cпасибо:
    root (28-03-2012) ximera (27-03-2012)
  8. #7

    Default Re: Требуется описание параметров сокетов, win32, протокол TCP/IP, примеры использования, оптимальность применения

    Мне много встречалось хороших статей на тему программинга сокетов на русском языке , но почему-то сейчас их трудно найти через поисковик. Вот одна из ссылок из моих старых Избранных, которая ещё живая: http://sources.ru/cpp/cpp_network_evets_winsock2.shtml . Был ещё мануал развернутый также на тему винсока 2-го но для функций на делфи (очень хороший прям мануал), поищи возможно найдешь.

  9. #8
    V3T's Avatar

    Default Re: Требуется описание параметров сокетов, win32, протокол TCP/IP, примеры использования, оптимальность применения

    спасибо
    Реверсинг ПО для незрячих - благородная цель

+ Reply to Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
All times are GMT. The time now is 01:35
vBulletin® Copyright ©2000 - 2018
www.reverse4you.org