-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSimpleSocket.h
514 lines (442 loc) · 25.2 KB
/
SimpleSocket.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
/*---------------------------------------------------------------------------*/
/* */
/* SimpleSocket.h - Simple Socket base class decleration. */
/* */
/* Author : Mark Carrier ([email protected]) */
/* */
/*---------------------------------------------------------------------------*/
/* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 4. The name "CarrierLabs" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
*
* THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/
#ifndef __SOCKET_H__
#define __SOCKET_H__
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#if defined(_LINUX) || defined (_DARWIN)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <netdb.h>
#endif
#ifdef _LINUX
#include <linux/if_packet.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if.h>
#include <sys/sendfile.h>
#endif
#if defined(_LINUX) || defined (_DARWIN)
#include <sys/time.h>
#include <sys/uio.h>
#include <unistd.h>
#include <fcntl.h>
#endif
#ifdef WIN32
#include <io.h>
#include <winsock2.h>
#include <Ws2tcpip.h>
#define IPTOS_LOWDELAY 0x10 ///
#endif
#include "Host.h"
#include "StatTimer.h"
//-----------------------------------------------------------------------------
// General class macro definitions and typedefs
//-----------------------------------------------------------------------------
#ifndef INVALID_SOCKET
#define INVALID_SOCKET ~(0)
#endif
#define SOCKET_SENDFILE_BLOCKSIZE 8192
/// Provides a platform independent class to for socket development.
/// This class is designed to abstract socket communication development in a
/// platform independent manner.
/// - Socket types
/// -# CActiveSocket Class
/// -# CPassiveSocket Class
class CSimpleSocket {
public:
/// Defines the three possible states for shuting down a socket.
typedef enum
{
Receives = SHUT_RD, ///< Shutdown passive socket.
Sends = SHUT_WR, ///< Shutdown active socket.
Both = SHUT_RDWR ///< Shutdown both active and passive sockets.
} CShutdownMode;
/// Defines the socket types defined by CSimpleSocket class.
typedef enum
{
SocketTypeInvalid, ///< Invalid socket type.
SocketTypeTcp, ///< Defines socket as TCP socket.
SocketTypeUdp, ///< Defines socket as UDP socket.
SocketTypeTcp6, ///< Defines socket as IPv6 TCP socket.
SocketTypeUdp6, ///< Defines socket as IPv6 UDP socket.
SocketTypeRaw ///< Provides raw network protocol access.
} CSocketType;
/// Defines all error codes handled by the CSimpleSocket class.
typedef enum
{
SocketError = -1, ///< Generic socket error translates to error below.
SocketSuccess = 0, ///< No socket error.
SocketInvalidSocket, ///< Invalid socket handle.
SocketInvalidAddress, ///< Invalid destination address specified.
SocketInvalidPort, ///< Invalid destination port specified.
SocketConnectionRefused, ///< No server is listening at remote address.
SocketTimedout, ///< Timed out while attempting operation.
SocketEwouldblock, ///< Operation would block if socket were blocking.
SocketNotconnected, ///< Currently not connected.
SocketEinprogress, ///< Socket is non-blocking and the connection cannot be completed immediately
SocketInterrupted, ///< Call was interrupted by a signal that was caught before a valid connection arrived.
SocketConnectionAborted, ///< The connection has been aborted.
SocketProtocolError, ///< Invalid protocol for operation.
SocketFirewallError, ///< Firewall rules forbid connection.
SocketInvalidSocketBuffer, ///< The receive buffer point outside the process's address space.
SocketConnectionReset, ///< Connection was forcibly closed by the remote host.
SocketAddressInUse, ///< Address already in use.
SocketInvalidPointer, ///< Pointer type supplied as argument is invalid.
SocketEunknown ///< Unknown error please report to [email protected]
} CSocketError;
public:
CSimpleSocket(CSocketType type = SocketTypeTcp);
CSimpleSocket(CSimpleSocket &socket);
virtual ~CSimpleSocket()
{
if (m_pBuffer != NULL)
{
delete [] m_pBuffer;
m_pBuffer = NULL;
}
};
/// Initialize instance of CSocket. This method MUST be called before an
/// object can be used. Errors : CSocket::SocketProtocolError,
/// CSocket::SocketInvalidSocket,
/// @return true if properly initialized.
virtual bool Initialize(void);
/// Close socket
/// @return true if successfully closed otherwise returns false.
virtual bool Close(void);
/// Shutdown shut down socket send and receive operations
/// CShutdownMode::Receives - Disables further receive operations.
/// CShutdownMode::Sends - Disables further send operations.
/// CShutdownBoth:: - Disables further send and receive operations.
/// @param nShutdown specifies the type of shutdown.
/// @return true if successfully shutdown otherwise returns false.
virtual bool Shutdown(CShutdownMode nShutdown);
/// Examine the socket descriptor sets currently owned by the instance of
/// the socket class (the readfds, writefds, and errorfds parameters) to
/// see whether some of their descriptors are ready for reading, are ready
/// for writing, or have an exceptional condition pending, respectively.
/// Block until an event happens on the specified file descriptors.
/// @return true if socket has data ready, or false if not ready or timed out.
virtual bool Select(void) { return Select(0,0); };
/// Examine the socket descriptor sets currently owned by the instance of
/// the socket class (the readfds, writefds, and errorfds parameters) to
/// see whether some of their descriptors are ready for reading, are ready
/// for writing, or have an exceptional condition pending, respectively.
/// @param nTimeoutSec timeout in seconds for select.
/// @param nTimeoutUSec timeout in micro seconds for select.
/// @return true if socket has data ready, or false if not ready or timed out.
virtual bool Select(int32 nTimeoutSec, int32 nTimeoutUSec);
/// Does the current instance of the socket object contain a valid socket
/// descriptor.
/// @return true if the socket object contains a valid socket descriptor.
virtual bool IsSocketValid(void) { return (m_socket != SocketError); };
/// Provides a standard error code for cross platform development by
/// mapping the operating system error to an error defined by the CSocket
/// class.
void TranslateSocketError(void);
/// Attempts to receive a block of data on an established connection.
/// @param nMaxBytes maximum number of bytes to receive.
/// @return number of bytes actually received.
/// @return of zero means the connection has been shutdown on the other side.
/// @return of -1 means that an error has occurred.
virtual int32 Receive(int32 nMaxBytes = 1);
/// Attempts to send a block of data on an established connection.
/// @param pBuf block of data to be sent.
/// @param bytesToSend size of data block to be sent.
/// @return number of bytes actually sent.
/// @return of zero means the connection has been shutdown on the other side.
/// @return of -1 means that an error has occurred.
virtual int32 Send(const uint8 *pBuf, size_t bytesToSend);
/// Attempts to send at most nNumItem blocks described by sendVector
/// to the socket descriptor associated with the socket object.
/// @param sendVector pointer to an array of iovec structures
/// @param nNumItems number of items in the vector to process
/// <br>\b NOTE: Buffers are processed in the order specified.
/// @return number of bytes actually sent, return of zero means the
/// connection has been shutdown on the other side, and a return of -1
/// means that an error has occurred.
virtual int32 Send(const struct iovec *sendVector, int32 nNumItems);
/// Copies data between one file descriptor and another.
/// On some systems this copying is done within the kernel, and thus is
/// more efficient than the combination of CSimpleSocket::Send and
/// CSimpleSocket::Receive, which would require transferring data to and
/// from user space.
/// <br>\b Note: This is available on all implementations, but the kernel
/// implementation is only available on Unix type systems.
/// @param nOutFd descriptor opened for writing.
/// @param nInFd descriptor opened for reading.
/// @param pOffset from which to start reading data from input file.
/// @param nCount number of bytes to copy between file descriptors.
/// @return number of bytes written to the out socket descriptor.
virtual int32 SendFile(int32 nOutFd, int32 nInFd, off_t *pOffset, int32 nCount);
/// Returns blocking/non-blocking state of socket.
/// @return true if the socket is non-blocking, else return false.
bool IsNonblocking(void) { return (m_bIsBlocking == false); };
/// Set the socket to blocking.
/// @return true if successful set to blocking, else return false;
bool SetBlocking(void);
/// Set the socket as non-blocking.
/// @return true if successful set to non-blocking, else return false;
bool SetNonblocking(void);
/// Get a pointer to internal receive buffer. The user MUST not free this
/// pointer when finished. This memory is managed internally by the CSocket
/// class.
/// @return pointer to data if valid, else returns NULL.
uint8 *GetData(void) { return m_pBuffer; };
/// Returns the number of bytes received on the last call to
/// CSocket::Receive().
/// @return number of bytes received.
int32 GetBytesReceived(void) { return m_nBytesReceived; };
/// Returns the number of bytes sent on the last call to
/// CSocket::Send().
/// @return number of bytes sent.
int32 GetBytesSent(void) { return m_nBytesSent; };
/// Controls the actions taken when CSimpleSocket::Close is executed on a
/// socket object that has unsent data. The default value for this option
/// is \b off.
/// - Following are the three possible scenarios.
/// -# \b bEnable is false, CSimpleSocket::Close returns immediately, but
/// any unset data is transmitted (after CSimpleSocket::Close returns)
/// -# \b bEnable is true and \b nTime is zero, CSimpleSocket::Close return
/// immediately and any unsent data is discarded.
/// -# \b bEnable is true and \b nTime is nonzero, CSimpleSocket::Close does
/// not return until all unsent data is transmitted (or the connection is
/// Closed by the remote system).
/// <br><p>
/// @param bEnable true to enable option false to disable option.
/// @param nTime time in seconds to linger.
/// @return true if option successfully set
bool SetOptionLinger(bool bEnable, uint16 nTime);
/// Tells the kernel that even if this port is busy (in the TIME_WAIT state),
/// go ahead and reuse it anyway. If it is busy, but with another state,
/// you will still get an address already in use error.
/// @return true if option successfully set
bool SetOptionReuseAddr();
/// Gets the timeout value that specifies the maximum number of seconds a
/// call to CSimpleSocket::Open waits until it completes.
/// @return the length of time in seconds
int32 GetConnectTimeoutSec(void) { return m_stConnectTimeout.tv_sec; };
/// Gets the timeout value that specifies the maximum number of microseconds
/// a call to CSimpleSocket::Open waits until it completes.
/// @return the length of time in microseconds
int32 GetConnectTimeoutUSec(void) { return m_stConnectTimeout.tv_usec; };
/// Sets the timeout value that specifies the maximum amount of time a call
/// to CSimpleSocket::Receive waits until it completes. Use the method
/// CSimpleSocket::SetReceiveTimeout to specify the number of seconds to wait.
/// If a call to CSimpleSocket::Receive has blocked for the specified length of
/// time without receiving additional data, it returns with a partial count
/// or CSimpleSocket::GetSocketError set to CSimpleSocket::SocketEwouldblock if no data
/// were received.
/// @param nConnectTimeoutSec of timeout in seconds.
/// @param nConnectTimeoutUsec of timeout in microseconds.
/// @return true if socket connection timeout was successfully set.
void SetConnectTimeout(int32 nConnectTimeoutSec, int32 nConnectTimeoutUsec = 0)
{
m_stConnectTimeout.tv_sec = nConnectTimeoutSec;
m_stConnectTimeout.tv_usec = nConnectTimeoutUsec;
};
/// Gets the timeout value that specifies the maximum number of seconds a
/// a call to CSimpleSocket::Receive waits until it completes.
/// @return the length of time in seconds
int32 GetReceiveTimeoutSec(void) { return m_stRecvTimeout.tv_sec; };
/// Gets the timeout value that specifies the maximum number of microseconds
/// a call to CSimpleSocket::Receive waits until it completes.
/// @return the length of time in microseconds
int32 GetReceiveTimeoutUSec(void) { return m_stRecvTimeout.tv_usec; };
/// Sets the timeout value that specifies the maximum amount of time a call
/// to CSimpleSocket::Receive waits until it completes. Use the method
/// CSimpleSocket::SetReceiveTimeout to specify the number of seconds to wait.
/// If a call to CSimpleSocket::Receive has blocked for the specified length of
/// time without receiving additional data, it returns with a partial count
/// or CSimpleSocket::GetSocketError set to CSimpleSocket::SocketEwouldblock if no data
/// were received.
/// @param nRecvTimeoutSec of timeout in seconds.
/// @param nRecvTimeoutUsec of timeout in microseconds.
/// @return true if socket timeout was successfully set.
bool SetReceiveTimeout(int32 nRecvTimeoutSec, int32 nRecvTimeoutUsec = 0);
/// Enable/disable multicast for a socket. This options is only valid for
/// socket descriptors of type CSimpleSocket::SocketTypeUdp.
/// @return true if multicast was enabled or false if socket type is not
/// CSimpleSocket::SocketTypeUdp and the error will be set to
/// CSimpleSocket::SocketProtocolError
bool SetMulticast(bool bEnable, uint8 multicastTTL = 1);
/// Return true if socket is multicast or false is socket is unicast
/// @return true if multicast is enabled
bool GetMulticast() { return m_bIsMulticast; };
/// Bind socket to a specific interface when using multicast.
/// @return true if successfully bound to interface
bool BindInterface(uint8 *pInterface);
/// Gets the timeout value that specifies the maximum number of seconds a
/// a call to CSimpleSocket::Send waits until it completes.
/// @return the length of time in seconds
int32 GetSendTimeoutSec(void) { return m_stSendTimeout.tv_sec; };
/// Gets the timeout value that specifies the maximum number of microseconds
/// a call to CSimpleSocket::Send waits until it completes.
/// @return the length of time in microseconds
int32 GetSendTimeoutUSec(void) { return m_stSendTimeout.tv_usec; };
/// Gets the timeout value that specifies the maximum amount of time a call
/// to CSimpleSocket::Send waits until it completes.
/// @return the length of time in seconds
bool SetSendTimeout(int32 nSendTimeoutSec, int32 nSendTimeoutUsec = 0);
/// Returns the last error that occured for the instace of the CSimpleSocket
/// instance. This method should be called immediately to retrieve the
/// error code for the failing mehtod call.
/// @return last error that occured.
CSocketError GetSocketError(void) { return m_socketErrno; };
/// Get the total time the of the last operation in milliseconds.
/// @return number of milliseconds of last operation.
uint32 GetTotalTimeMs() { return m_timer.GetMilliSeconds(); };
/// Get the total time the of the last operation in microseconds.
/// @return number of microseconds or last operation.
uint32 GetTotalTimeUsec() { return m_timer.GetMicroSeconds(); };
/// Return Differentiated Services Code Point (DSCP) value currently set on the socket object.
/// @return DSCP for current socket object.
/// <br><br> \b NOTE: Windows special notes http://support.microsoft.com/kb/248611.
int GetSocketDscp(void);
/// Set Differentiated Services Code Point (DSCP) for socket object.
/// @param nDscp value of TOS setting which will be converted to DSCP
/// @return true if DSCP value was properly set
/// <br><br> \b NOTE: Windows special notes http://support.microsoft.com/kb/248611.
bool SetSocketDscp(int nDscp);
/// Return socket descriptor
/// @return socket descriptor which is a signed 32 bit integer.
SOCKET GetSocketDescriptor() { return m_socket; };
/// Return socket descriptor
/// @return socket descriptor which is a signed 32 bit integer.
CSocketType GetSocketType() { return m_nSocketType; };
/// Returns clients Internet host address as a string in standard numbers-and-dots notation.
/// @return NULL if invalid
uint8 *GetClientAddr() { return (uint8 *)inet_ntoa(m_stClientSockaddr.sin_addr); };
/// Returns the port number on which the client is connected.
/// @return client port number.
int16 GetClientPort() { return m_stClientSockaddr.sin_port; };
/// Returns server Internet host address as a string in standard numbers-and-dots notation.
/// @return NULL if invalid
uint8 *GetServerAddr() { return (uint8 *)inet_ntoa(m_stServerSockaddr.sin_addr); };
/// Returns the port number on which the server is connected.
/// @return server port number.
int16 GetServerPort() { return ntohs(m_stServerSockaddr.sin_port); };
/// Get the TCP receive buffer window size for the current socket object.
/// <br><br>\b NOTE: Linux will set the receive buffer to twice the value passed.
/// @return zero on failure else the number of bytes of the TCP receive buffer window size if successful.
uint16 GetReceiveWindowSize() { return GetWindowSize(SO_RCVBUF); };
/// Get the TCP send buffer window size for the current socket object.
/// <br><br>\b NOTE: Linux will set the send buffer to twice the value passed.
/// @return zero on failure else the number of bytes of the TCP receive buffer window size if successful.
uint16 GetSendWindowSize() { return GetWindowSize(SO_SNDBUF); };
/// Set the TCP receive buffer window size for the current socket object.
/// <br><br>\b NOTE: Linux will set the receive buffer to twice the value passed.
/// @return zero on failure else the number of bytes of the TCP send buffer window size if successful.
uint16 SetReceiveWindowSize(uint16 nWindowSize) { return SetWindowSize(SO_RCVBUF, nWindowSize); };
/// Set the TCP send buffer window size for the current socket object.
/// <br><br>\b NOTE: Linux will set the send buffer to twice the value passed.
/// @return zero on failure else the number of bytes of the TCP send buffer window size if successful.
uint16 SetSendWindowSize(uint16 nWindowSize) { return SetWindowSize(SO_SNDBUF, nWindowSize); };
/// Disable the Nagle algorithm (Set TCP_NODELAY to true)
/// @return false if failed to set socket option otherwise return true;
bool DisableNagleAlgoritm();
/// Enable the Nagle algorithm (Set TCP_NODELAY to false)
/// @return false if failed to set socket option otherwise return true;
bool EnableNagleAlgoritm();
protected:
/// Set internal socket error to that specified error
/// @param error type of error
void SetSocketError(CSimpleSocket::CSocketError error) { m_socketErrno = error; };
/// Set object socket handle to that specified as parameter
/// @param socket value of socket descriptor
void SetSocketHandle(SOCKET socket) { m_socket = socket; };
private:
/// Generic function used to get the send/receive window size
/// @return zero on failure else the number of bytes of the TCP window size if successful.
uint16 GetWindowSize(uint32 nOptionName);
/// Generic function used to set the send/receive window size
/// @return zero on failure else the number of bytes of the TCP window size if successful.
uint16 SetWindowSize(uint32 nOptionName, uint32 nWindowSize);
/// Attempts to send at most nNumItem blocks described by sendVector
/// to the socket descriptor associated with the socket object.
/// @param sendVector pointer to an array of iovec structures
/// @param nNumItems number of items in the vector to process
/// <br>\b Note: This implementation is for systems that don't natively
/// support this functionality.
/// @return number of bytes actually sent, return of zero means the
/// connection has been shutdown on the other side, and a return of -1
/// means that an error has occurred.
int32 Writev(const struct iovec *pVector, size_t nCount);
/// Flush the socket descriptor owned by the object.
/// @return true data was successfully sent, else return false;
bool Flush();
CSimpleSocket *operator=(CSimpleSocket &socket);
protected:
SOCKET m_socket; /// socket handle
CSocketError m_socketErrno; /// number of last error
uint8 *m_pBuffer; /// internal send/receive buffer
int32 m_nBufferSize; /// size of internal send/receive buffer
int32 m_nSocketDomain; /// socket type PF_INET, PF_INET6
CSocketType m_nSocketType; /// socket type - UDP, TCP or RAW
int32 m_nBytesReceived; /// number of bytes received
int32 m_nBytesSent; /// number of bytes sent
uint32 m_nFlags; /// socket flags
bool m_bIsBlocking; /// is socket blocking
bool m_bIsMulticast; /// is the UDP socket multicast;
struct timeval m_stConnectTimeout; /// connection timeout
struct timeval m_stRecvTimeout; /// receive timeout
struct timeval m_stSendTimeout; /// send timeout
struct sockaddr_in m_stServerSockaddr; /// server address
struct sockaddr_in m_stClientSockaddr; /// client address
struct sockaddr_in m_stMulticastGroup; /// multicast group to bind to
struct linger m_stLinger; /// linger flag
CStatTimer m_timer; /// internal statistics.
#ifdef WIN32
WSADATA m_hWSAData; /// Windows
#endif
fd_set m_writeFds; /// write file descriptor set
fd_set m_readFds; /// read file descriptor set
fd_set m_errorFds; /// error file descriptor set
};
#endif /* __SOCKET_H__ */