linux_camp /ClassMaster2014/barahon/Cultivation_9_UnixSource/minorGems/network/Socket.h

Language C/C++ Header Lines 330
MD5 Hash 839f5add26f7bf3a3a9f944a2d889aa4
Repository https://gitlab.com/garheade/linux_camp.git View Raw File
  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
/*
 * Modification History
 *
 * 2001-January-9		Jason Rohrer
 * Created.
 *
 * 2001-January-28		Jason Rohrer
 * Added a static framework init function.
 *
 * 2001-November-13		Jason Rohrer
 * Changed timeout parameter to signed, since -1 is a possible argument.
 *
 * 2002-March-29    Jason Rohrer
 * Added Fortify inclusion.
 *
 * 2002-August-2    Jason Rohrer
 * Added functon for getting remote host address.
 *
 * 2003-February-3   Jason Rohrer
 * Added a function for getting the local host address from a socket.
 *
 * 2003-August-12   Jason Rohrer
 * Added more verbose comment about receive timeout parameter.
 * Added a function for flushing socket sends.
 *
 * 2003-November-20   Jason Rohrer
 * Made flush function robust against bogus receive return values.
 *
 * 2004-December13   Jason Rohrer
 * Added a breakConnection function.
 *
 * 2005-July-5   Jason Rohrer
 * Added port number when getting address of remote host.
 *
 * 2006-May-28   Jason Rohrer
 * Changed timeout behavior slightly to support emulation of non-blocking mode.
 * Added support for non-blocking sends.
 *
 * 2008-September-30   Jason Rohrer
 * Added support for non-blocking connect.
 *
 * 2010-January-26  Jason Rohrer
 * Added support for disabling Nagle algorithm.
 */



#include "minorGems/common.h"


#ifndef SOCKET_CLASS_INCLUDED
#define SOCKET_CLASS_INCLUDED



#include "minorGems/network/HostAddress.h"
#include "minorGems/system/Time.h"



#ifdef FORTIFY
#include "minorGems/util/development/fortify/fortify.h"
#endif



/**
 * Network socket.  Does not contain an interface for listening to connections
 * (see SocketServer for these interfaces) or for establishing connections
 * (see SocketClient for these interfaces).
 *
 * Note:  Implementation for the functions defined here is provided
 *   separately for each platform (in the mac/ linux/ and win32/ 
 *   subdirectories).
 *
 * @author Jason Rohrer
 */ 
class Socket {

	public:

        

        /**
         * Constructor for a socket.
         *
         * Should not be called directly.  Use SocketClient or SocketServer
         * to obtain an outbound or inbound socket connection.
         */
        Socket();

        
		// destroying a Socket closes the connection
		~Socket();
		
		
		/**
		 * Initializes the socket framework.  Must be called
		 * once by program before sockets are used.  Note
		 * that SocketClient and SocketServer both should call
		 * init automatically when they are first used.
		 *
		 * @return 0 on success, or -1 on failure.
		 */ 
		static int initSocketFramework();
		
		
		/**
		 * Gets whether the socket framework has been initialized.
		 *
		 * @return true if the framework has been initialized.
		 */
		static char isFrameworkInitialized();

		

        /**
         * For outbound sockets that were opened in non-blocking mode:
         *
         * Get whether socket is connected yet.
         *
         * @return 1 on success, 0 on still waiting, -1 on error.
         */
        int isConnected();
        

		
		/**
		 * Sends bytes through this socket.
		 *
		 * @param inBuffer the buffer of bytes to send.
		 * @param inNumBytes the number of bytes to send.
		 * @param inAllowedToBlock set to false to prevent blocking.
         *   Defaults to true.
         * @param inAllowDelay set to false to disable Nagle algorithm,
         *   where a buffer should be sent NOW without waiting for
         *   more data accumulation.
         *   Defaults to true.
         *
		 * @return the number of bytes sent successfully,
		 *   or -1 for a socket error.
         *   Returns -2 if not allowed to block and the operation
         *   would block.
		 */
		int send( unsigned char *inBuffer, int inNumBytes,
                  char inAllowedToBlock = true,
                  char inAllowDelay = true );
		
		
		/**
		 * Receives bytes from this socket.
		 *
		 * @param inBuffer the buffer where received bytes will be put.
		 *   Must be pre-allocated memory space.
		 * @param inNumBytes the number of bytes to read from the socket.
		 * @param inTimeout the timeout for this receive operation in
         *   milliseconds.  Set to -1 for an infinite timeout.
		 *   -2 is returned from this call in the event of a timeout.
         *   If timeout is set, only available data is returned (up
         *   to, but not more than inNumBytes).  The socket does not
         *   wait for all inNumBytes to become available before returning.
         *   Thus, a timeout return value (-2) means no data was available
         *   before the timeout.  If some data is available, we never
         *   time out.  If no timeout is set (-1 for infinite), the socket
         *   waits for all inNumBytes to arrive before returning.
         *   Thus, setting a timeout of 0 effectively puts the socket
         *   into non-blocking mode.
		 *
		 * @return the number of bytes read successfully,
		 *   or -1, -2 for a socket error or timeout, respectively.
		 */
		int receive( unsigned char *inBuffer, int inNumBytes,
                     long inTimeout );


        /**
         * Flushes sent data through the socket.
         * 
         * Intended to be called before deleting the socket to ensure
         * that data goes through.  The mechanism used by this function
         * does not guarantee that data goes through, but it works
         * better than simply closing the socket on many platforms.
         *
         * The method used by this call works best if the remote
         * host closes the connection.  For example, if we send the
         * remote host a "connection closing" indicator, then
         * call writeFlushBeforeClose, and the remote host closes
         * the connection upon receiving the indicator, all of our
         * sent data will be received by the remote host after
         * writeFlushBeforeClose returns (assuming that the maximum
         * time is long enough for the remote host to actually close
         * the connection).
         *
         * Good maximum times should be in the several-second range,
         * though the Apache system uses 30 seconds.  For slow connections,
         * this might be necessary.
         *
         * This call will cause any received data to be discarded.
         *
         * This call DOES NOT close the socket.  The socket must be deleted
         * as usual after this call returns.
         *
         * @param inMaxTimeInMilliseconds the maximum time to wait
         *   in milliseconds.  This call may block slightly longer than
         *   this if the remote host is still sending data.
         */
        void sendFlushBeforeClose( int inMaxTimeInMilliseconds );


        
        /**
         * Forces this socket's connection to break, causing any blocked
         * send or receive operations to fail.
         *
         * Note that this operation is inherently not thread-safe, so
         * some external mechanism must be used to ensure that the socket
         * is not destroyed by another thread before breakConnection is called.
         * The SocketManager class is one such external mechanism.
         */         
        void breakConnection();
        
        

        /**
         * Gets the host connected to the other end of this socket.
         *
         * @return the address of the remote host, or NULL if obtaining
         *   the address fails.  The port of the returned address
         *   will always be set to the port that the host is connecting from.
         *   Must be destroyed by caller if non-NULL.
         */
        HostAddress *getRemoteHostAddress();


        
        /**
         * Gets the local address attached to this socket.
         *
         * Getting the local address from a socket is more
         * accurate than non-connected methods (for example, the methods
         * used in HostAddress.h implementations.
         *
         * @return the address of the local host, or NULL if obtaining
         *   the address fails.  The port of the returned address
         *   will always be set to 0.
         *   Must be destroyed by caller if non-NULL.
         */
        HostAddress *getLocalHostAddress();


        
		/**
		 * Used by platform-specific implementations.
		 */		
		void *mNativeObjectPointer;

		
        // called by socket client to set connected status
        void setConnected( char inConnected ) {
            mConnected = inConnected;
            }
        

	private:
		
		static char sInitialized;

        char mConnected;
        
        char mIsConnectionBroken;
        

        // toggle Nagle algorithm (inValue=1 turns it off)
        void setNoDelay( int inValue );
        
        
	};			



inline Socket::Socket()
    : mConnected( true ), mIsConnectionBroken( false ) {

    }



inline char Socket::isFrameworkInitialized() {

	return sInitialized;
	}



inline void Socket::sendFlushBeforeClose( int inMaxTimeInMilliseconds ) {
    unsigned char *tempBuffer = new unsigned char[1];

    int numRead = -2;

    int timeout = 1000;
    if( timeout > inMaxTimeInMilliseconds ) {
        timeout = inMaxTimeInMilliseconds;
        }        
    
    long totalTimeout = 0;

    unsigned long startSec;
    unsigned long startMsec;

    Time::getCurrentTime( &startSec, &startMsec );
    
    // keep reading data from socket until we get an error
    // or wait too long (pass our max timeout)
    while( numRead != -1 && totalTimeout < inMaxTimeInMilliseconds ) {
        numRead =
            this->receive( tempBuffer, 1, timeout );


        // track total time whether the receive timed out or not
        totalTimeout =
            (long)( Time::getMillisecondsSince( startSec, startMsec ) );
        }

    delete [] tempBuffer;
    }


	
#endif
Back to Top