Module: Winsock

Winsock

v0.1
This is a Windows-only sockets module that is easy to use and efficient for detecting events that have occurred on a socket. When a socket change (connected, closed, data arrival, connection request) occurs, the library is notified and the appropriate forwards are called, there is no looping involved to poll for changes. The errors returned by the functions are actual winsock library errors. I've included many of the error codes in the winsock.inc file, if your error code is not defined there then you can look in the link posted above, in the C++ winsock header file (winsock2.h), or google "winsock #errorcode". As said above, this module is for Windows only so if you plan to make your plugin compatible for both Windows and Linux, you cannot use this module. I did make a module & include combo that provide the same type of forward notifications but it does use a thinking entity to constantly check for changes (Sockets Forwards in Code Snip pets\Tuts section).



.: Winsock Library Information

.: Functions

These functions are for the most part self explanatory in terms of usage. I will try to add descriptions when I get some time.
  • SocketHandle:Winsock_Connect( Hostname[] , Port , Protocol , &Error )
    • Hostname[] - The remote host\ip to connect to.

    • Port - The remote port to connect to.

    • Protocol - The protocol to use, SOCK_TCP or SOCK_UDP.

    • &Error - Error variable which will be assigned an error value byref.
      • Return Value: SocketHandle on success, Invalid_Socket on error and &Error will hold the error code.




  • Winsock_Close( SocketHandle:Socket )
    • Socket - The socket handle to close.
      • Return Value: 0 on success, error code on failure.




  • SocketHandle:Winsock_Listen( Port , Protocol , &Error )
    • Port - The local port to listen on.

    • Protocol - The protocol to use, SOCK_TCP or SOCK_UDP.

    • &Error - Error variable which will be assigned an error value byref.
      • Return Value: SocketHandle on success, Invalid_Socket on error and &Error will hold the error code.




  • SocketHandle:Winsock_Accept( SocketHandle:Socket , &Error )
    • Socket - The socket handle of the socket that received a connection request.

    • &Error - Error variable which will be assigned an error value byref.
      • Return Value: SocketHandle on success; this is a newly created socket for this connection, Invalid_Socket on error and &Error will hold the error code.




  • Winsock_RecvData( SocketHandle:Socket , Data[] , Length , &Error )
    • Socket - The socket handle of the socket that received a connection request.

    • Data[] - The data buffer used to retreive data.

    • Length - Length of data to receive, use sizeof( Data ) in most cases.

    • &Error - Error variable which will be assigned an error value byref.
      • Return Value: Bytes received on success, Socket_Error on error and &Error will hold the error code.




  • Winsock_SendText( SocketHandle:Socket , Data[] , Length , &Error )
    • Socket - The socket handle of the socket that received a connection request.

    • Data[] - The data buffer to send.

    • Length - Length of data being sent, use sizeof( Data ) in most cases.

    • &Error - Error variable which will be assigned an error value byref.
      • Return Value: Bytes sent on success, Socket_Error on error and &Error will hold the error code.




  • Winsock_SendBinary( SocketHandle:Socket , Data[] , Length , &Error )
    • Socket - The socket handle of the socket that received a connection request.

    • Data[] - The data buffer to send.

    • Length - Length of data being sent, use sizeof( Data ) in most cases.

    • &Error - Error variable which will be assigned an error value byref.
      • Return Value: Bytes sent on success, Socket_Error on error and &Error will hold the error code.




  • Winsock_GetPeerAddr( SocketHandle:Socket , DestString[] , MaxChars , &Port , &Error )
    • Socket - The socket handle of the socket you wish to determine the remote address of.

    • DestString[] - The string variable that will hold the remote address.

    • MaxChars - Max characters that can be stored in DestString, use charsmax( DestString ).

    • &Port - The remote port that socket is connected to, passed byref.

    • &Error - Error variable which will be assigned an error value byref.
      • Return Value: Length of DestString[] on success, Socket_Error on error and &Error will hold the error code.




  • Winsock_BytesAvailable( SocketHandle:Socket , &Error )
    • Socket - The socket handle of the socket you wish to check for data available to be retrieved.

    • &Error - Error variable which will be assigned an error value byref.
      • Return Value: Number of bytes available for reading on success, Socket_Error on error and &Error will hold the error code.







.: Forwards

The forwards for socket events all have the same parameters. Socket being the socket handle that the event occurred on and ErrorCode being any errors that may have occurred. You MUST check error codes in the forward to ensure nothing bad happened. For example, after a connection request is made, Socket_Connected() will fire and there is a chance that no successful connection has been made, the socket may have timed out or the connection could have been refused.
  • Winsock_Connected( SocketHandle:Socket , ErrorCode )
    • A socket connection has been made. Check ErrorCode for errors such as timed out etc.



  • Winsock_Disconnected( SocketHandle:Socket , ErrorCode )
    • A socket has disconnected on the remote side. Check ErrorCode for errors.



  • Winsock_ConnectionRequest( SocketHandle:Socket , ErrorCode )
    • A socket connection request has occurred, use Socket_Accept( Socket , iError ) to accept. Check ErrorCode for errors.



  • Winsock_DataArrival( SocketHandle:Socket , ErrorCode )
    • A socket has received data and is ready to be read. Check ErrorCode for errors.






.: Requirements
  • Windows



Some code was borrowed, and modified, from the original sockets module.



Please let me know of any errors/typos or if any fixes\changes\additions are needed.





.: Example

Below is a sample plugin using a separate server and client plugin that can communicate with each other. It's good practice to check the socket in the forward to make sure you are manipulating the intended socket; always required when using multiple sockets or are using multiple plugins using winsock.



Server


PHP Code:









#include <amxmodx>

#include <winsock>



new const Version[] = "0.1";



const 
ListenPort = 5934;



new 
SocketHandle:g_sListenSocket;

new 
SocketHandle:g_sAcceptSocket;



public 
plugin_init() 

{

    
register_plugin( "Winsock Server" , Version , "bugsy" );

    

    
register_concmd( "server_listen" , "StartServer" );

    
register_concmd( "server_close" , "CloseSocket" );

    
register_concmd( "server_send" , "SendMessage" );

}



public 
plugin_end()

{

    
CloseSocket();

}



public 
StartServer()

{

    new 
iError;

    

    if ( ( ( 
g_sListenSocket = Winsock_Listen( ListenPort , SOCKET_TCP , iError ) ) != Invalid_Socket ) && !iError )

    {

        
server_print( "Server Listening on Port %d. [Socket=%d]" , ListenPort , g_sListenSocket );

    }

    else

    {

        
server_print( "Listen error occurred: Socket=%d iError=%d" , g_sListenSocket , iError );

    }

}



public 
CloseSocket()

{

    
Winsock_Close( g_sListenSocket );

    
Winsock_Close( g_sAcceptSocket );

}



public 
SendMessage()

{

    new 
iError , szPacket[] = "This is a message from the server to client";

    
Winsock_SendText( g_sAcceptSocket , szPacket , sizeof( szPacket ) , iError );

}



public 
Winsock_ConnectionRequest( SocketHandle:Socket , Error )

{

    if ( 
Socket == g_sListenSocket )

    {

        if ( !
Error )

        {

            new 
iError;

            

            if ( ( ( 
g_sAcceptSocket = Winsock_Accept( Socket , iError ) ) != Invalid_Socket ) && !iError )

            {

                
server_print( "Connection request Accepted. [AcceptSocket=%d][Error=%d]" , g_sAcceptSocket , Error );

                

                new 
iSendError , szPacket[] = "SERVER: Welcome, thanks for connecting";

                
Winsock_SendText( g_sAcceptSocket , szPacket , sizeof( szPacket ) , iSendError );

            }

            else

            {

                
server_print( "Accept error occurred: Socket=%d iError=%d" , g_sAcceptSocket , iError );

            }

        }

        else

        {

            
server_print( "Error in connection request: %d" , Error );

        }

    }

}



public 
Winsock_DataArrival( SocketHandle:Socket , Error )

{

    if ( 
Socket == g_sAcceptSocket )

    {

        new 
szData[ 64 ] , iError;

        
Winsock_RecvData( Socket , szData , charsmax( szData ) , iError );

            

        
server_print( "SERVER RECV: %s [Errors=%d/%d]" , szData , Error , iError );

    }

}



public 
Winsock_Disconnected( SocketHandle:Socket , Error )

{

    if ( 
Socket == g_sAcceptSocket )

    {

        if ( !
Error )

        {

            
server_print( "Servers accepted client was notified of remote host disconnect" );

        }

        else

        {

            
server_print( "Error at server-side client disconnect forward %d" , Error );

        }

    }

} 









Client


PHP Code:









#include <amxmodx>

#include <winsock>



new const Version[] = "0.1";



const 
ServerPort = 5934;



new 
SocketHandle:g_sConnectSocket;



public 
plugin_init() 

{

    
register_plugin( "Winsock Client" , Version , "bugsy" );

    

    
register_concmd( "client_connect" , "ConnectToServer" );

    
register_concmd( "client_close" , "CloseSocket" );

    
register_concmd( "client_send" , "SendMessage" );

}



public 
plugin_end()

{

    
CloseSocket();

}



public 
ConnectToServer()

{

    new 
iError;

    

    if ( ( ( 
g_sConnectSocket = Winsock_Connect( "192.168.1.12" , ServerPort , SOCKET_TCP , iError ) ) != Invalid_Socket ) && !iError )

    {

        
server_print( "Connection requested attempted on Port %d. [Socket=%d]" , ServerPort , g_sConnectSocket );

    }

    else

    {

        
server_print( "Connect error occurred: Socket=%d iError=%d" , g_sConnectSocket , iError );

    }

}



public 
CloseSocket()

{

    
Winsock_Close( g_sConnectSocket );

}



public 
SendMessage()

{

    new 
iError , szPacket[] = "This is a message from the client to server";

    
Winsock_SendText( g_sConnectSocket , szPacket , sizeof( szPacket ) , iError );

}



public 
Winsock_Connected( SocketHandle:Socket , Error )

{

    if ( 
Socket == g_sConnectSocket )

    {

        if ( !
Error )

        {

            
server_print( "Connection successful [Socket=%d][Error=%d]" , Socket , Error );

                

            new 
iSendError , szPacket[] = "CLIENT: Thanks for accepting my connection request";

            
Winsock_SendText( Socket , szPacket , sizeof( szPacket ) , iSendError );

        }

        else

        {

            switch ( 
Error )

            {

                case 
WSAECONNREFUSED: server_print( "Error %d: Connection refused" , Error );

                case 
WSAETIMEDOUT: server_print( "Error %d: Connection timed out" , Error );

                default: 
server_print( "Error connecting: %d" , Error );

            }

        }

    }

}



public 
Winsock_DataArrival( SocketHandle:Socket , Error )

{

    if ( 
Socket == g_sConnectSocket )

    {

        new 
szData[ 64 ] , iError;

        
Winsock_RecvData( Socket , szData , charsmax( szData ) , iError );

    

        
server_print( "CLIENT RECV: %s [Errors=%d/%d]" , szData , Error , iError );

    }

}



public 
Winsock_Disconnected( SocketHandle:Socket , Error )

{

    if ( 
Socket == g_sConnectSocket )

    {

        if ( !
Error )

        {

            
server_print( "Client was notified of remote host disconnect" );

        }

        else

        {

            
server_print( "Error at client disconnect forward %d" , Error );

        }

    }

} 
























Attached Files

















File Type: dll


winsock_amxx.dll (72.0 KB, N/A views)


File Type: zip


winsock_src.zip (43.1 KB, N/A views)


File Type: inc


winsock.inc (3.1 KB, N/A views)


File Type: sma

Get Plugin or
Get Source (winsock_server.sma - 2.4 KB)

File Type: sma

Get Plugin or
Get Source (winsock_client.sma - 2.5 KB)







Orignal From: Module: Winsock

No comments

Not a single link is allowed to submit in comment :o