Module: Winsock
WinsockThis 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).
v0.1
.: 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.
- Socket - The socket handle to close.
- 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 );
}
}
}
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 );
}
}
}
Orignal From: Module: Winsock
Post a Comment