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_ListenListenPort 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_Closeg_sListenSocket );

    
Winsock_Closeg_sAcceptSocket );

}



public 
SendMessage()

{

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

    
Winsock_SendTextg_sAcceptSocket szPacket sizeofszPacket ) , iError );

}



public 
Winsock_ConnectionRequestSocketHandle:Socket Error )

{

    if ( 
Socket == g_sListenSocket )

    {

        if ( !
Error )

        {

            new 
iError;

            

            if ( ( ( 
g_sAcceptSocket Winsock_AcceptSocket 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_SendTextg_sAcceptSocket szPacket sizeofszPacket ) , 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_DataArrivalSocketHandle:Socket Error )

{

    if ( 
Socket == g_sAcceptSocket )

    {

        new 
szData64 ] , iError;

        
Winsock_RecvDataSocket szData charsmaxszData ) , iError );

            

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

    }

}



public 
Winsock_DisconnectedSocketHandle: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_Closeg_sConnectSocket );

}



public 
SendMessage()

{

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

    
Winsock_SendTextg_sConnectSocket szPacket sizeofszPacket ) , iError );

}



public 
Winsock_ConnectedSocketHandle: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_SendTextSocket szPacket sizeofszPacket ) , iSendError );

        }

        else

        {

            switch ( 
Error )

            {

                case 
WSAECONNREFUSEDserver_print"Error %d: Connection refused" Error );

                case 
WSAETIMEDOUTserver_print"Error %d: Connection timed out" Error );

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

            }

        }

    }

}



public 
Winsock_DataArrivalSocketHandle:Socket Error )

{

    if ( 
Socket == g_sConnectSocket )

    {

        new 
szData64 ] , iError;

        
Winsock_RecvDataSocket szData charsmaxszData ) , iError );

    

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

    }

}



public 
Winsock_DisconnectedSocketHandle: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