Raised This Month: $12 Target: $400
 3% 

Module: Winsock


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 10-23-2011 , 15:21   Module: Winsock
Reply With Quote #1

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. These sockets are asynchronous which is a type of non-blocking socket; when a socket change (connected, closed, data arrival, connection request) occurs, the library is notified by the operating system and the appropriate forwards are called, there is no looping involved to poll for changes. The errors returned by the functions/forwards 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 also made a module/include combo compatible for both Windows & Linux that provide the same type of forward notifications which uses a thinking entity to constantly check for changes (Sockets Forwards in Code Snippets\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 to receive data on.
    • Data[] - The data buffer used to retrieve 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 to send text on.
    • 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 to send binary data on.
    • 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; the error code will indicate these types of things.
  • 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. You can use both plugins on the same server to test.

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 );
        }
        
Winsock_CloseSocket );
    }

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 );
        }
        
Winsock_CloseSocket );
    }

Attached Files
File Type: dll winsock_amxx.dll (72.0 KB, 343 views)
File Type: inc winsock.inc (3.1 KB, 388 views)
File Type: zip winsock_src.zip (40.2 KB, 346 views)
File Type: sma Get Plugin or Get Source (winsock_server.sma - 970 views - 2.4 KB)
File Type: sma Get Plugin or Get Source (winsock_client.sma - 1044 views - 2.3 KB)
__________________

Last edited by Bugsy; 11-02-2011 at 22:13.
Bugsy is offline
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 10-23-2011 , 15:21   Re: Module: Winsock
Reply With Quote #2

reserved
__________________
Bugsy is offline
dark_style
Senior Member
Join Date: Jul 2009
Location: Bulgaria
Old 10-23-2011 , 15:30   Re: Module: Winsock
Reply With Quote #3

Wow! Good job, you're awesome!
dark_style is offline
wangningyu
Member
Join Date: Dec 2011
Location: China.GuangDong
Old 02-18-2012 , 03:08   Re: Module: Winsock
Reply With Quote #4

nice module !

I just used it to write a plugin ,like the CrossServer-AdminChat
__________________
One Code , One Dream !
wangningyu is offline
johnally
Member
Join Date: May 2011
Location: Mauritius
Old 12-26-2015 , 15:16   Re: Module: Winsock
Reply With Quote #5

Is there a way to communicate over HTTPS using this module?
__________________
No allowed!

johnally is offline
metal_upa
Senior Member
Join Date: Jun 2016
Old 10-12-2023 , 02:32   Re: Module: Winsock
Reply With Quote #6

@Bugsy
I don't know much about socket but i'm trying to learn it from your code.

Ok let's say i have 5 servers:
- 1 server to host winsock_server.amxx + winsock_client.amxx
- 4 server to host winsock_client.amxx

The problem is how do i resend a packet receive from winsock_server to all winsock_client?

This is the part right?
PHP Code:
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 );
    }

any idea to get 4 other 'Socket' number that used by the client?
metal_upa is offline
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 11-03-2023 , 23:00   Re: Module: Winsock
Reply With Quote #7

On data arrival on one of your client connections, loop through all other client connections to send them the data.

I would use an array sized at the number of clients you need to support. Each slot of that array will hold the socket handle of an active client connection...on disconnect set it to 0. When you need to send data to all clients, loop through this array, sending data to all non-zero cells.
__________________
Bugsy is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 01:20.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode