AsyncSocket.h
上传用户:kc0325
上传日期:2020-06-20
资源大小:204k
文件大小:17k
源码类别:

iPhone

开发平台:

Objective-C

  1. //
  2. //  AsyncSocket.h
  3. //  
  4. //  This class is in the public domain.
  5. //  Originally created by Dustin Voss on Wed Jan 29 2003.
  6. //  Updated and maintained by Deusty Designs and the Mac development community.
  7. //
  8. //  http://code.google.com/p/cocoaasyncsocket/
  9. //
  10. #import <Foundation/Foundation.h>
  11. @class AsyncSocket;
  12. @class AsyncReadPacket;
  13. @class AsyncWritePacket;
  14. extern NSString *const AsyncSocketException;
  15. extern NSString *const AsyncSocketErrorDomain;
  16. enum AsyncSocketError
  17. {
  18. AsyncSocketCFSocketError = kCFSocketError, // From CFSocketError enum.
  19. AsyncSocketNoError = 0, // Never used.
  20. AsyncSocketCanceledError, // onSocketWillConnect: returned NO.
  21. AsyncSocketConnectTimeoutError,
  22. AsyncSocketReadMaxedOutError,               // Reached set maxLength without completing
  23. AsyncSocketReadTimeoutError,
  24. AsyncSocketWriteTimeoutError
  25. };
  26. typedef enum AsyncSocketError AsyncSocketError;
  27. @interface NSObject (AsyncSocketDelegate)
  28. /**
  29.  * In the event of an error, the socket is closed.
  30.  * You may call "unreadData" during this call-back to get the last bit of data off the socket.
  31.  * When connecting, this delegate method may be called
  32.  * before"onSocket:didAcceptNewSocket:" or "onSocket:didConnectToHost:".
  33. **/
  34. - (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;
  35. /**
  36.  * Called when a socket disconnects with or without error.  If you want to release a socket after it disconnects,
  37.  * do so here. It is not safe to do that during "onSocket:willDisconnectWithError:".
  38. **/
  39. - (void)onSocketDidDisconnect:(AsyncSocket *)sock;
  40. /**
  41.  * Called when a socket accepts a connection.  Another socket is spawned to handle it. The new socket will have
  42.  * the same delegate and will call "onSocket:didConnectToHost:port:".
  43. **/
  44. - (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;
  45. /**
  46.  * Called when a new socket is spawned to handle a connection.  This method should return the run-loop of the
  47.  * thread on which the new socket and its delegate should operate. If omitted, [NSRunLoop currentRunLoop] is used.
  48. **/
  49. - (NSRunLoop *)onSocket:(AsyncSocket *)sock wantsRunLoopForNewSocket:(AsyncSocket *)newSocket;
  50. /**
  51.  * Called when a socket is about to connect. This method should return YES to continue, or NO to abort.
  52.  * If aborted, will result in AsyncSocketCanceledError.
  53.  * 
  54.  * If the connectToHost:onPort:error: method was called, the delegate will be able to access and configure the
  55.  * CFReadStream and CFWriteStream as desired prior to connection.
  56.  *
  57.  * If the connectToAddress:error: method was called, the delegate will be able to access and configure the
  58.  * CFSocket and CFSocketNativeHandle (BSD socket) as desired prior to connection. You will be able to access and
  59.  * configure the CFReadStream and CFWriteStream in the onSocket:didConnectToHost:port: method.
  60. **/
  61. - (BOOL)onSocketWillConnect:(AsyncSocket *)sock;
  62. /**
  63.  * Called when a socket connects and is ready for reading and writing.
  64.  * The host parameter will be an IP address, not a DNS name.
  65. **/
  66. - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port;
  67. /**
  68.  * Called when a socket has completed reading the requested data into memory.
  69.  * Not called if there is an error.
  70. **/
  71. - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;
  72. /**
  73.  * Called when a socket has read in data, but has not yet completed the read.
  74.  * This would occur if using readToData: or readToLength: methods.
  75.  * It may be used to for things such as updating progress bars.
  76. **/
  77. - (void)onSocket:(AsyncSocket *)sock didReadPartialDataOfLength:(CFIndex)partialLength tag:(long)tag;
  78. /**
  79.  * Called when a socket has completed writing the requested data. Not called if there is an error.
  80. **/
  81. - (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;
  82. /**
  83.  * Called after the socket has completed SSL/TLS negotiation.
  84.  * This method is not called unless you use the provided startTLS method.
  85. **/
  86. - (void)onSocket:(AsyncSocket *)sock didSecure:(BOOL)flag;
  87. @end
  88. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  89. #pragma mark -
  90. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  91. @interface AsyncSocket : NSObject
  92. {
  93. CFSocketRef theSocket;             // IPv4 accept or connect socket
  94. CFSocketRef theSocket6;            // IPv6 accept or connect socket
  95. CFReadStreamRef theReadStream;
  96. CFWriteStreamRef theWriteStream;
  97. CFRunLoopSourceRef theSource;      // For theSocket
  98. CFRunLoopSourceRef theSource6;     // For theSocket6
  99. CFRunLoopRef theRunLoop;
  100. CFSocketContext theContext;
  101. NSArray *theRunLoopModes;
  102. NSTimer *theConnectTimer;
  103. NSMutableArray *theReadQueue;
  104. AsyncReadPacket *theCurrentRead;
  105. NSTimer *theReadTimer;
  106. NSMutableData *partialReadBuffer;
  107. NSMutableArray *theWriteQueue;
  108. AsyncWritePacket *theCurrentWrite;
  109. NSTimer *theWriteTimer;
  110. id theDelegate;
  111. UInt16 theFlags;
  112. long theUserData;
  113. }
  114. - (id)init;
  115. - (id)initWithDelegate:(id)delegate;
  116. - (id)initWithDelegate:(id)delegate userData:(long)userData;
  117. /* String representation is long but has no "n". */
  118. - (NSString *)description;
  119. /**
  120.  * Use "canSafelySetDelegate" to see if there is any pending business (reads and writes) with the current delegate
  121.  * before changing it.  It is, of course, safe to change the delegate before connecting or accepting connections.
  122. **/
  123. - (id)delegate;
  124. - (BOOL)canSafelySetDelegate;
  125. - (void)setDelegate:(id)delegate;
  126. /* User data can be a long, or an id or void * cast to a long. */
  127. - (long)userData;
  128. - (void)setUserData:(long)userData;
  129. /* Don't use these to read or write. And don't close them, either! */
  130. - (CFSocketRef)getCFSocket;
  131. - (CFReadStreamRef)getCFReadStream;
  132. - (CFWriteStreamRef)getCFWriteStream;
  133. // Once one of the accept or connect methods are called, the AsyncSocket instance is locked in
  134. // and the other accept/connect methods can't be called without disconnecting the socket first.
  135. // If the attempt fails or times out, these methods either return NO or
  136. // call "onSocket:willDisconnectWithError:" and "onSockedDidDisconnect:".
  137. // When an incoming connection is accepted, AsyncSocket invokes several delegate methods.
  138. // These methods are (in chronological order):
  139. // 1. onSocket:didAcceptNewSocket:
  140. // 2. onSocket:wantsRunLoopForNewSocket:
  141. // 3. onSocketWillConnect:
  142. // 
  143. // Your server code will need to retain the accepted socket (if you want to accept it).
  144. // The best place to do this is probably in the onSocket:didAcceptNewSocket: method.
  145. // 
  146. // After the read and write streams have been setup for the newly accepted socket,
  147. // the onSocket:didConnectToHost:port: method will be called on the proper run loop.
  148. /**
  149.  * Tells the socket to begin listening and accepting connections on the given port.
  150.  * When a connection comes in, the AsyncSocket instance will call the various delegate methods (see above).
  151.  * The socket will listen on all available interfaces (e.g. wifi, ethernet, etc)
  152. **/
  153. - (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr;
  154. /**
  155.  * This method is the same as acceptOnPort:error: with the additional option
  156.  * of specifying which interface to listen on. So, for example, if you were writing code for a server that
  157.  * has multiple IP addresses, you could specify which address you wanted to listen on.  Or you could use it
  158.  * to specify that the socket should only accept connections over ethernet, and not other interfaces such as wifi.
  159.  * You may also use the special strings "localhost" or "loopback" to specify that
  160.  * the socket only accept connections from the local machine.
  161.  * 
  162.  * To accept connections on any interface pass nil, or simply use the acceptOnPort:error: method.
  163. **/
  164. - (BOOL)acceptOnAddress:(NSString *)hostaddr port:(UInt16)port error:(NSError **)errPtr;
  165. /**
  166.  * Connects to the given host and port.
  167.  * The host may be a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2")
  168. **/
  169. - (BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr;
  170. /**
  171.  * This method is the same as connectToHost:onPort:error: with an additional timeout option.
  172.  * To not time out use a negative time interval, or simply use the connectToHost:onPort:error: method.
  173. **/
  174. - (BOOL)connectToHost:(NSString *)hostname
  175.    onPort:(UInt16)port
  176.   withTimeout:(NSTimeInterval)timeout
  177. error:(NSError **)errPtr;
  178. /**
  179.  * Connects to the given address, specified as a sockaddr structure wrapped in a NSData object.
  180.  * For example, a NSData object returned from NSNetservice's addresses method.
  181.  * 
  182.  * If you have an existing struct sockaddr you can convert it to a NSData object like so:
  183.  * struct sockaddr sa  -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
  184.  * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];
  185. **/
  186. - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr;
  187. /**
  188.  * This method is the same as connectToAddress:error: with an additional timeout option.
  189.  * To not time out use a negative time interval, or simply use the connectToAddress:error: method.
  190. **/
  191. - (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr;
  192. /**
  193.  * Disconnects immediately. Any pending reads or writes are dropped.
  194. **/
  195. - (void)disconnect;
  196. /**
  197.  * Disconnects after all pending reads have completed.
  198.  * After calling this, the read and write methods will do nothing.
  199.  * The socket will disconnect even if there are still pending writes.
  200. **/
  201. - (void)disconnectAfterReading;
  202. /**
  203.  * Disconnects after all pending writes have completed.
  204.  * After calling this, the read and write methods will do nothing.
  205.  * The socket will disconnect even if there are still pending reads.
  206. **/
  207. - (void)disconnectAfterWriting;
  208. /**
  209.  * Disconnects after all pending reads and writes have completed.
  210.  * After calling this, the read and write methods will do nothing.
  211. **/
  212. - (void)disconnectAfterReadingAndWriting;
  213. /* Returns YES if the socket and streams are open, connected, and ready for reading and writing. */
  214. - (BOOL)isConnected;
  215. /**
  216.  * Returns the local or remote host and port to which this socket is connected, or nil and 0 if not connected.
  217.  * The host will be an IP address.
  218. **/
  219. - (NSString *)connectedHost;
  220. - (UInt16)connectedPort;
  221. - (NSString *)localHost;
  222. - (UInt16)localPort;
  223. - (BOOL)isIPv4;
  224. - (BOOL)isIPv6;
  225. // The readData and writeData methods won't block. To not time out, use a negative time interval.
  226. // If they time out, "onSocket:disconnectWithError:" is called. The tag is for your convenience.
  227. // You can use it as an array index, step number, state id, pointer, etc., just like the socket's user data.
  228. /**
  229.  * This will read a certain number of bytes into memory, and call the delegate method when those bytes have been read.
  230.  * If there is an error, partially read data is lost.
  231.  * If the length is 0, this method does nothing and the delegate is not called.
  232. **/
  233. - (void)readDataToLength:(CFIndex)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  234. /**
  235.  * This reads bytes until (and including) the passed "data" parameter, which acts as a separator.
  236.  * The bytes and the separator are returned by the delegate method.
  237.  * 
  238.  * If you pass nil or zero-length data as the "data" parameter,
  239.  * the method will do nothing, and the delegate will not be called.
  240.  * 
  241.  * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter.
  242.  * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for
  243.  * a character, the read will prematurely end.
  244. **/
  245. - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  246. /**
  247.  * Same as readDataToData:withTimeout:tag, with the additional restriction that the amount of data read
  248.  * may not surpass the given maxLength (specified in bytes).
  249.  * 
  250.  * If you pass a maxLength parameter that is less than the length of the data parameter,
  251.  * the method will do nothing, and the delegate will not be called.
  252.  * 
  253.  * If the max length is surpassed, it is treated the same as a timeout - the socket is closed.
  254.  * 
  255.  * Pass -1 as maxLength if no length restriction is desired, or simply use the readDataToData:withTimeout:tag method.
  256. **/
  257. - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(CFIndex)length tag:(long)tag;
  258. /**
  259.  * Reads the first available bytes that become available on the socket.
  260. **/
  261. - (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag;
  262. /**
  263.  * Writes data to the socket, and calls the delegate when finished.
  264.  * 
  265.  * If you pass in nil or zero-length data, this method does nothing and the delegate will not be called.
  266. **/
  267. - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  268. /**
  269.  * Returns progress of current read or write, from 0.0 to 1.0, or NaN if no read/write (use isnan() to check).
  270.  * "tag", "done" and "total" will be filled in if they aren't NULL.
  271. **/
  272. - (float)progressOfReadReturningTag:(long *)tag bytesDone:(CFIndex *)done total:(CFIndex *)total;
  273. - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(CFIndex *)done total:(CFIndex *)total;
  274. /**
  275.  * Secures the connection using SSL/TLS.
  276.  * 
  277.  * This method may be called at any time, and the TLS handshake will occur after all pending reads and writes
  278.  * are finished. This allows one the option of sending a protocol dependent StartTLS message, and queuing
  279.  * the upgrade to TLS at the same time, without having to wait for the write to finish.
  280.  * Any reads or writes scheduled after this method is called will occur over the secured connection.
  281.  * 
  282.  * The possible keys and values for the TLS settings are well documented.
  283.  * Some possible keys are:
  284.  * - kCFStreamSSLLevel
  285.  * - kCFStreamSSLAllowsExpiredCertificates
  286.  * - kCFStreamSSLAllowsExpiredRoots
  287.  * - kCFStreamSSLAllowsAnyRoot
  288.  * - kCFStreamSSLValidatesCertificateChain
  289.  * - kCFStreamSSLPeerName
  290.  * - kCFStreamSSLCertificates
  291.  * - kCFStreamSSLIsServer
  292.  * 
  293.  * Please refer to Apple's documentation for associated values, as well as other possible keys.
  294.  * 
  295.  * If you pass in nil or an empty dictionary, this method does nothing and the delegate will not be called.
  296. **/
  297. - (void)startTLS:(NSDictionary *)tlsSettings;
  298. /**
  299.  * For handling readDataToData requests, data is necessarily read from the socket in small increments.
  300.  * The performance can be much improved by allowing AsyncSocket to read larger chunks at a time and
  301.  * store any overflow in a small internal buffer.
  302.  * This is termed pre-buffering, as some data may be read for you before you ask for it.
  303.  * If you use readDataToData a lot, enabling pre-buffering will result in better performance, especially on the iPhone.
  304.  * 
  305.  * The default pre-buffering state is controlled by the DEFAULT_PREBUFFERING definition.
  306.  * It is highly recommended one leave this set to YES.
  307.  * 
  308.  * This method exists in case pre-buffering needs to be disabled by default for some reason.
  309.  * In that case, this method exists to allow one to easily enable pre-buffering when ready.
  310. **/
  311. - (void)enablePreBuffering;
  312. /**
  313.  * When you create an AsyncSocket, it is added to the runloop of the current thread.
  314.  * So for manually created sockets, it is easiest to simply create the socket on the thread you intend to use it.
  315.  * 
  316.  * If a new socket is accepted, the delegate method onSocket:wantsRunLoopForNewSocket: is called to
  317.  * allow you to place the socket on a separate thread. This works best in conjunction with a thread pool design.
  318.  * 
  319.  * If, however, you need to move the socket to a separate thread at a later time, this
  320.  * method may be used to accomplish the task.
  321.  * 
  322.  * This method must be called from the thread/runloop the socket is currently running on.
  323.  * 
  324.  * Note: After calling this method, all further method calls to this object should be done from the given runloop.
  325.  * Also, all delegate calls will be sent on the given runloop.
  326. **/
  327. - (BOOL)moveToRunLoop:(NSRunLoop *)runLoop;
  328. /**
  329.  * Allows you to configure which run loop modes the socket uses.
  330.  * The default set of run loop modes is NSDefaultRunLoopMode.
  331.  * 
  332.  * If you'd like your socket to continue operation during other modes, you may want to add modes such as
  333.  * NSModalPanelRunLoopMode or NSEventTrackingRunLoopMode. Or you may simply want to use NSRunLoopCommonModes.
  334.  * 
  335.  * Accepted sockets will automatically inherit the same run loop modes as the listening socket.
  336.  * 
  337.  * Note: NSRunLoopCommonModes is defined in 10.5. For previous versions one can use kCFRunLoopCommonModes.
  338. **/
  339. - (BOOL)setRunLoopModes:(NSArray *)runLoopModes;
  340. /**
  341.  * In the event of an error, this method may be called during onSocket:willDisconnectWithError: to read
  342.  * any data that's left on the socket.
  343. **/
  344. - (NSData *)unreadData;
  345. /* A few common line separators, for use with the readDataToData:... methods. */
  346. + (NSData *)CRLFData;   // 0x0D0A
  347. + (NSData *)CRData;     // 0x0D
  348. + (NSData *)LFData;     // 0x0A
  349. + (NSData *)ZeroData;   // 0x00
  350. @end