您的位置:首页 > 其它

支持SSL的封装类--CAsyncSocketEx

2007-09-07 15:45 531 查看

Introduction

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
CAsyncSocket
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 layers easily.

One benefit is, that
CAsyncSocketEx
works without MFC, but if MFC is enabled (
_AFX
is defined),
CAsyncSocketEx
offers some functions taking a
CString
as argument, so that
CAsyncSocketEx
is compatible with
CAsyncSocket
.

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
CAsyncSocketExLayer
.

Another layer class is CAsyncSslSocketLayer, which can be used to establish SSL connections to servers.

Using the code

To use
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
IOCtl
or
SetSockOpt
in your code,
CAsyncSocketEx
and the layer classes do not recognize if you change any options using
IOCtl
or
SetSockOpt
.

CAsyncSocketEx
provides some useful new functions:

// Triggers an event on the socket
// Any combination of FD_READ, FD_WRITE, FD_CLOSE,
//FD_ACCEPT, FD_CONNECT and FD_FORCEREAD is valid for lEvent.
BOOL TriggerEvent(long lEvent);

With
TriggerEvent
you can explicitly trigger the notification messages handled in
OnReceive
,
OnSend
, ...

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
FD_READ
:
OnRecieve
will only be called if there is really any data available. To trigger a call to
OnReceive
regardless of data waiting or not, use
FD_FORCEREAD
instead.

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
CAsyncSocketEx
instance.

//Attaches a new layer to the socket.
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.

//Resets layer chain.
void RemoveAllLayers()

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.

//Called by the layers to notify application of some events
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:

LAYERCALLBACK_STATECHANGE

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

LAYERCALLBACK_LAYERSPECIFIC

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.

CAsyncProxySocketLayer

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
CAsyncProxySocketLayer
, call
SetProxy
and attach it to a
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
LAYERCALLBACK_LAYERSPECIFIC
):

Error codes:
PROXYERROR_NOERROR 0
PROXYERROR_NOCONN 1
Can't connect to proxy server, use
GetLastError
for more information
PROXYERROR_REQUESTFAILED 2
Request failed, can't send data
PROXYERROR_AUTHREQUIRED 3
Authentication required
PROXYERROR_AUTHTYPEUNKNOWN 4
Authtype unknown or not supported
PROXYERROR_AUTHFAILED 5
Authentication failed
PROXYERROR_AUTHNOLOGON 6
PROXYERROR_CANTRESOLVEHOST 7
Status messages:
PROXYSTATUS_LISTENSOCKETCREATED 8
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
Accept
:
rConnected
socket 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.

Parameters:

nProxyType
specifies the Proxy Type.

ProxyHost
and
nProxyPort
specify the address of the proxy

ProxyUser
and
ProxyPass
are only available for SOCKS5 proxies.

Supported proxy types:

PROXYTYPE_NOPROXY


PROXYTYPE_SOCKS4


PROXYTYPE_SOCKS4A


PROXYTYPE_SOCKS5


PROXYTYPE_HTTP11


There are also some other functions:

int GetProxyType();

Returns the used proxy.

const int GetLastProxyError() const;

Returns the last proxy error, see above for a list of available error codes.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: