AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
|
10-23-2011
, 16:21
Module: Winsock
|
#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
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_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 ); } Winsock_Close( Socket ); } }
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 ); } Winsock_Close( Socket ); } }
__________________
Last edited by Bugsy; 11-02-2011 at 23:13.
|
|