CAsyncSocketEx is an MFC-less replacement for
CAsyncSocket which does also offer a flexible layer code. This
class was written because
CAsyncSocket is not the fastest WinSock
wrapper and it's very hard to add new functionality to
derived classes. This class supports most of the features of
CAsyncSocket and can be extended quite easily. With the layer
system, you can implement transparent layers like proxy or SSL
One benefit is, that
CAsyncSocketEx works without MFC, but if
MFC is enabled (
_AFX is defined),
offers some functions taking a
CString as argument, so that
CAsyncSocketEx is compatible with
CAsyncProxySocketLayer is a layer class for
CAsyncSocketEx. With it's help, you can connect through proxy
servers. This layer is almost transparent, so you won't have to modify much code
to use it. Other layers can be written quite easily as well, just derive new
layer classes from
Another layer class is CAsyncSslSocketLayer,
which can be used to establish SSL connections to servers.
Using the code
CAsyncSocketEx, just replace all occurrences of
CAsyncSocket in your code with
CAsyncSocketEx. If you
did not enhance
CAsyncSocket yourself in any way, you won't have to
change anything else in your code. However, problems can occur if you're using
SetSockOpt in your code,
CAsyncSocketEx and the layer classes do not recognize if you change
any options using
CAsyncSocketEx provides some useful new functions:
BOOL TriggerEvent(long lEvent);
TriggerEvent you can explicitly trigger the notification
messages handled in
TriggerEvent(FD_SEND); for example posts a message to the
internal helper window and returns. Later, if this message is processed,
OnSend will be called.
There's something special about
will only be called if there is really any data available. To trigger a call to
OnReceive regardless of data waiting or not, use
The other new functions are for the new layer system.
Using the layer system
Using the layer system is really simple. In most cases, it is sufficient to
create a new instance of a layer class and attach it to a
BOOL AddLayer(CAsyncSocketExLayer *pLayer);
This adds a new layer derived from
CAsyncSocketExLayer to the
socket. You can add more than one layer. The layer last added to the layer list,
works directly on the socket and the other layers operate on the previous one.
All calls you make to
CAsyncSocketEx are first handled by the layer
first added to the list. Example: If you want to establish an SSL connection to
a server over a proxy server, first add the SSL layer (see the CAsyncSslSocketLayer
article), then add the proxy layer.
This function detached all layers from the socket. But it does not destroy
the layer class instances, you are still responsible for destroying the layer
instances. In theory, it would be possible to add a layer previously detached
from a socket to a new socket, but this is not recommended. You should create
and attach a new instance of the layer for each established connection.
virtual int OnLayerCallback(const CAsyncSocketExLayer *pLayer,
int nType, int nParam1, int nParam2);
This function is called by the layers to notify the program about more or
less important events of the layer. The first parameter identifies the layer
which did send the notification message. The second parameter is the type of the
notification. Valid notification types are:
This notification is sent if the state of the layer has changed.
nParam1 contains the new state,
nParam2 contains the
old state. Valid states are:
- 0 - Not a valid socket
- 1 - Unconnected
- 2 - Connecting
- 3 - Listening
- 4 - Connected
- 5 - Closed
- 6 - Aborted
This notification is sent on events specific to a each layer. See the layer's
description for the meaning and the parameters of this notification message.
With this layer you can connect through proxy servers. This class supports
SOCKS4/5 as well as HTTP/1.1 (using CONNECT method) proxies. For more
information about SOCKS4/5 go to http://www.socks.nec.com/socksprot.html, for more information
about HTTP 1.1 go to http://www.rfc-editor.org/ and search for RFC2616.
You don't have to change much, in your already existing code, to use
CAsyncProxySocketLayer. To use it, create an instance of
SetProxy and attach it to
CAsyncSocketEx instance. You have to process
OnLayerCallback in your
CAsyncSocketEx instance as it
will receive all layer notifications.
The following notifications are sent (of type
- Error codes:
|Can't connect to proxy server, use |
GetLastError for more
|Request failed, can't send data |
|Authentication required |
|Authtype unknown or not supported |
|Authentication failed |
- Status messages:
|Called when a listen socket was created successfully. Unlike the normal
listen function, a socksified socket has to connect to the proxy to negotiate
the details with the server on which the listen socket will be created. The two
parameters will contain the IP and port of the listen socket on the server.
If you want to use
CAsyncProxySocketLayer to create a listen
socket, you have to use this overloaded function:
BOOL PrepareListen(unsigned long serverIp);
serverIP is the IP of the server you are already connected
through the SOCKS proxy. You can't use listen sockets over a SOCKS proxy without
a primary connection. Listen sockets are only supported by SOCKS proxies, this
won't work with HTTP proxies.
When the listen socket is created successfully, the
PROXYSTATUS_LISTENSOCKETCREATED notification is sent. The
parameters will tell you the IP and the port of the listen socket. After it, you
have to handle the
OnAccept message and accept the connection.
Be careful when calling
will NOT be filled! Instead use the instance which created the listen
socket, it will handle the data connection.
If you want to accept more than one connection, you have to create a listing
socket for each of them!
Description of important functions and their parameters:
void SetProxy(int nProxyType);
void SetProxy(int nProxyType, CString ProxyHost, int nProxyPort);
void SetProxy(int nProxyType, CString ProxyHost, int nProxyPort,
CString ProxyUser, CString ProxyPass);
Call one of this functions to set the proxy type.
nProxyType specifies the Proxy Type.
nProxyPort specify the address of
ProxyPass are only available for
Supported proxy types:
There are also some other functions:
Returns the used proxy.
const int GetLastProxyError() const;
Returns the last proxy error, see above for a list of available error
- blocking mode not supported
SetSockOpt not fully supported, use with
SOCK_DGRAM (UDP) is not supported, only
SOCK_STREAM (TCP) is supported.
- 2003-03-29 - small fixes
- 2003-03-28 - Connect now uses
WSAAsyncGetHostByName to resolve
host names, no longer blocking whole thread
- 2003-03-26 - First public release