├── README.md ├── .DS_Store ├── ServerExample ├── .DS_Store ├── ServerExample.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── lc-macbook.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ ├── xcuserdata │ │ └── lc-macbook.xcuserdatad │ │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ └── project.pbxproj ├── ServerExample │ ├── ViewController.h │ ├── AppDelegate.h │ ├── main.m │ ├── Info.plist │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── AppDelegate.m │ └── ViewController.m ├── CocoaAsyncSocket │ ├── Source │ │ ├── CocoaAsyncSocket.h │ │ └── RunLoop │ │ │ ├── AsyncUdpSocket.h │ │ │ └── AsyncSocket.h │ └── README.markdown ├── ServerExampleTests │ ├── Info.plist │ └── ServerExampleTests.m └── ServerExampleUITests │ ├── Info.plist │ └── ServerExampleUITests.m └── ClientExample ├── ClientExample.xcodeproj ├── xcuserdata │ └── lc-macbook.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── lc-macbook.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── project.pbxproj ├── ClientExample ├── ViewController.h ├── AppDelegate.h ├── main.m ├── Info.plist ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── AppDelegate.m └── ViewController.m ├── CocoaAsyncSocket ├── Source │ ├── CocoaAsyncSocket.h │ └── RunLoop │ │ ├── AsyncUdpSocket.h │ │ └── AsyncSocket.h └── README.markdown ├── ClientExampleTests ├── Info.plist └── ClientExampleTests.m └── ClientExampleUITests ├── Info.plist └── ClientExampleUITests.m /README.md: -------------------------------------------------------------------------------- 1 | # cocoaAsynSocketExample -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iRemark/cocoaAsynSocketExample/HEAD/.DS_Store -------------------------------------------------------------------------------- /ServerExample/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iRemark/cocoaAsynSocketExample/HEAD/ServerExample/.DS_Store -------------------------------------------------------------------------------- /ClientExample/ClientExample.xcodeproj/xcuserdata/lc-macbook.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /ClientExample/ClientExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ServerExample/ServerExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ClientExample/ClientExample.xcodeproj/project.xcworkspace/xcuserdata/lc-macbook.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iRemark/cocoaAsynSocketExample/HEAD/ClientExample/ClientExample.xcodeproj/project.xcworkspace/xcuserdata/lc-macbook.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ServerExample/ServerExample.xcodeproj/project.xcworkspace/xcuserdata/lc-macbook.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iRemark/cocoaAsynSocketExample/HEAD/ServerExample/ServerExample.xcodeproj/project.xcworkspace/xcuserdata/lc-macbook.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ClientExample/ClientExample/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // ClientExample 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /ServerExample/ServerExample/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // ServerExample 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /ClientExample/ClientExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ClientExample 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /ServerExample/ServerExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ServerExample 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /ClientExample/ClientExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ClientExample 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ServerExample/ServerExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ServerExample 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ClientExample/ClientExample.xcodeproj/xcuserdata/lc-macbook.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ClientExample.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ServerExample/ServerExample.xcodeproj/xcuserdata/lc-macbook.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ServerExample.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ClientExample/CocoaAsyncSocket/Source/CocoaAsyncSocket.h: -------------------------------------------------------------------------------- 1 | // 2 | // CocoaAsyncSocket.h 3 | // CocoaAsyncSocket 4 | // 5 | // Created by Derek Clarkson on 10/08/2015. 6 | // Copyright © 2015 Robbie Hanson. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | //! Project version number for CocoaAsyncSocket. 12 | FOUNDATION_EXPORT double cocoaAsyncSocketVersionNumber; 13 | 14 | //! Project version string for CocoaAsyncSocket. 15 | FOUNDATION_EXPORT const unsigned char cocoaAsyncSocketVersionString[]; 16 | 17 | #import 18 | #import 19 | #import 20 | #import 21 | -------------------------------------------------------------------------------- /ServerExample/CocoaAsyncSocket/Source/CocoaAsyncSocket.h: -------------------------------------------------------------------------------- 1 | // 2 | // CocoaAsyncSocket.h 3 | // CocoaAsyncSocket 4 | // 5 | // Created by Derek Clarkson on 10/08/2015. 6 | // Copyright © 2015 Robbie Hanson. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | 11 | //! Project version number for CocoaAsyncSocket. 12 | FOUNDATION_EXPORT double cocoaAsyncSocketVersionNumber; 13 | 14 | //! Project version string for CocoaAsyncSocket. 15 | FOUNDATION_EXPORT const unsigned char cocoaAsyncSocketVersionString[]; 16 | 17 | #import 18 | #import 19 | #import 20 | #import 21 | -------------------------------------------------------------------------------- /ClientExample/ClientExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ClientExample/ClientExampleUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ServerExample/ServerExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ServerExample/ServerExampleUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ClientExample/ClientExampleTests/ClientExampleTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ClientExampleTests.m 3 | // ClientExampleTests 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ClientExampleTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ClientExampleTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /ServerExample/ServerExampleTests/ServerExampleTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ServerExampleTests.m 3 | // ServerExampleTests 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ServerExampleTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ServerExampleTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /ClientExample/ClientExampleUITests/ClientExampleUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ClientExampleUITests.m 3 | // ClientExampleUITests 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ClientExampleUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ClientExampleUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ServerExample/ServerExampleUITests/ServerExampleUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ServerExampleUITests.m 3 | // ServerExampleUITests 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ServerExampleUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ServerExampleUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ClientExample/ClientExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ServerExample/ServerExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ClientExample/ClientExample/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /ServerExample/ServerExample/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /ClientExample/ClientExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /ServerExample/ServerExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /ClientExample/ClientExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ClientExample 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /ServerExample/ServerExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ServerExample 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /ClientExample/ClientExample/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // Client 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "GCDAsyncSocket.h" 11 | 12 | @interface ViewController () 13 | @property (weak, nonatomic) IBOutlet UITextField *ipField; 14 | @property (weak, nonatomic) IBOutlet UITextField *portField; 15 | @property (weak, nonatomic) IBOutlet UITextField *sendMsgField; 16 | @property (weak, nonatomic) IBOutlet UITextView *reciveMsgTextView; 17 | 18 | 19 | //客户端socket 20 | @property (nonatomic) GCDAsyncSocket *clientSocket; 21 | 22 | @end 23 | 24 | @implementation ViewController 25 | 26 | 27 | - (void)viewDidLoad { 28 | [super viewDidLoad]; 29 | // Do any additional setup after loading the view, typically from a nib. 30 | 31 | //1、初始化 32 | self.ipField.text = @"172.16.1.6"; 33 | self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; 34 | } 35 | 36 | - (void)didReceiveMemoryWarning { 37 | [super didReceiveMemoryWarning]; 38 | // Dispose of any resources that can be recreated. 39 | } 40 | 41 | - (IBAction)linkButtonAction:(id)sender { 42 | //连接服务器 43 | [self.clientSocket connectToHost:self.ipField.text onPort:self.portField.text.integerValue withTimeout:-1 error:nil]; 44 | } 45 | - (IBAction)sendMsgButtonAction:(id)sender { 46 | NSData *data = [self.sendMsgField.text dataUsingEncoding:NSUTF8StringEncoding]; 47 | //withTimeout -1 :无穷大 48 | //tag: 消息标记 49 | [self.clientSocket writeData:data withTimeout:-1 tag:0]; 50 | } 51 | 52 | - (void)showMessageWithText:(NSString *)text { 53 | self.reciveMsgTextView.text = [self.reciveMsgTextView.text stringByAppendingFormat:@"%@\n", text]; 54 | } 55 | 56 | #pragma mark - GCDAsynSocket Delegate 57 | - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{ 58 | [self showMessageWithText:@"链接成功"]; 59 | [self showMessageWithText:[NSString stringWithFormat:@"服务器IP : %@", host]]; 60 | [self.clientSocket readDataWithTimeout:-1 tag:0]; 61 | } 62 | 63 | //收到消息 64 | - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{ 65 | NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 66 | [self showMessageWithText:text]; 67 | [self.clientSocket readDataWithTimeout:-1 tag:0]; 68 | } 69 | 70 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 71 | [self.view endEditing:YES]; 72 | } 73 | 74 | @end 75 | 76 | -------------------------------------------------------------------------------- /ServerExample/ServerExample/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // ServerExample 4 | // 5 | // Created by lc-macbook pro on 2017/10/23. 6 | // Copyright © 2017年 http://www.cnblogs.com/saytome/. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "GCDAsyncSocket.h" 11 | 12 | @interface ViewController () 13 | 14 | /** 端口号 **/ 15 | @property (weak, nonatomic) IBOutlet UITextField *portField; 16 | 17 | /** 发送消息 **/ 18 | @property (weak, nonatomic) IBOutlet UITextField *sendMsgField; 19 | 20 | /** 连接端口号按钮 **/ 21 | @property (weak, nonatomic) IBOutlet UIButton *linkPortButton; 22 | 23 | /** 发送消息按钮 **/ 24 | @property (weak, nonatomic) IBOutlet UIButton *sendMsgButton; 25 | 26 | /** 接受消息 **/ 27 | @property (weak, nonatomic) IBOutlet UITextView *reciveMsgTextView; 28 | 29 | 30 | 31 | //服务器socket(开放端口,监听客户端socket的链接) 32 | @property (nonatomic) GCDAsyncSocket *serverSocket; 33 | 34 | //保护客户端socket 35 | @property (nonatomic) GCDAsyncSocket *clientSocket; 36 | 37 | @end 38 | 39 | @implementation ViewController 40 | 41 | - (void)viewDidLoad { 42 | [super viewDidLoad]; 43 | // Do any additional setup after loading the view, typically from a nib. 44 | 45 | //初始化服务器socket 46 | self.serverSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()]; 47 | } 48 | - (void)didReceiveMemoryWarning { 49 | [super didReceiveMemoryWarning]; 50 | // Dispose of any resources that can be recreated. 51 | 52 | 53 | } 54 | 55 | /** 连接端口 **/ 56 | - (IBAction)linkPortButtonAction:(id)sender { 57 | NSError *error = nil; 58 | BOOL result = [self.serverSocket acceptOnPort:self.portField.text.integerValue error:&error]; 59 | if (result && error == nil) { 60 | //开放成功 61 | [self showMessageWithText:@"连接成功"]; 62 | } 63 | } 64 | 65 | 66 | /** 发消息 **/ 67 | - (IBAction)sendMsgButtonAction:(id)sender { 68 | NSData *data = [self.sendMsgField.text dataUsingEncoding:NSUTF8StringEncoding]; 69 | //withTimeout -1: 一直等 70 | //tag:消息标记 71 | [self.clientSocket writeData:data withTimeout:-1 tag:0]; 72 | } 73 | 74 | - (void)showMessageWithText:(NSString *)text { 75 | self.reciveMsgTextView.text = [self.reciveMsgTextView.text stringByAppendingFormat:@"%@\n",text]; 76 | } 77 | 78 | #pragma mark - 服务器socket Delegate 79 | - (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{ 80 | //保存客户端的socket 81 | self.clientSocket = newSocket; 82 | [self showMessageWithText:@"链接成功"]; 83 | 84 | [self showMessageWithText:[NSString stringWithFormat:@"服务器地址:%@ -端口: %d", newSocket.connectedHost, newSocket.connectedPort]]; 85 | [self.clientSocket readDataWithTimeout:-1 tag:0]; 86 | } 87 | 88 | //收到消息 89 | - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{ 90 | NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 91 | [self showMessageWithText:text]; 92 | [self.clientSocket readDataWithTimeout:-1 tag:0]; 93 | } 94 | 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /ClientExample/CocoaAsyncSocket/README.markdown: -------------------------------------------------------------------------------- 1 | # CocoaAsyncSocket 2 | [![Build Status](https://travis-ci.org/robbiehanson/CocoaAsyncSocket.svg?branch=master)](https://travis-ci.org/robbiehanson/CocoaAsyncSocket) [![Version Status](https://img.shields.io/cocoapods/v/CocoaAsyncSocket.svg?style=flat)](http://cocoadocs.org/docsets/CocoaAsyncSocket) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Platform](http://img.shields.io/cocoapods/p/CocoaAsyncSocket.svg?style=flat)](http://cocoapods.org/?q=CocoaAsyncSocket) [![license Public Domain](https://img.shields.io/badge/license-Public%20Domain-orange.svg?style=flat)](https://en.wikipedia.org/wiki/Public_domain) 3 | 4 | 5 | CocoaAsyncSocket provides easy-to-use and powerful asynchronous socket libraries for Mac and iOS. The classes are described below. 6 | 7 | ## Installation 8 | 9 | #### CocoaPods 10 | 11 | Install using [CocoaPods](http://cocoapods.org) by adding this line to your Podfile: 12 | 13 | ````ruby 14 | use_frameworks! # Add this if you are targeting iOS 8+ or using Swift 15 | pod 'CocoaAsyncSocket' 16 | ```` 17 | 18 | #### Carthage 19 | 20 | CocoaAsyncSocket is [Carthage](https://github.com/Carthage/Carthage) compatible. To include it, build your project with Carthage, then drag `Carthage/Build/iOS/CocoaAsyncSocket.framework` into your project. 21 | 22 | #### Manual 23 | 24 | You can also include it into your project by adding the source files directly, but you should probably be using a dependency manager to keep up to date. 25 | 26 | ### Importing 27 | 28 | Using Objective-C: 29 | 30 | ```obj-c 31 | @import CocoaAsyncSocket; // When using iOS 8+ frameworks 32 | // OR 33 | #import "CocoaAsyncSocket.h" // When not using frameworks, targeting iOS 7 or below 34 | ``` 35 | 36 | Using Swift: 37 | 38 | ```swift 39 | import CocoaAsyncSocket 40 | ``` 41 | 42 | ## TCP 43 | 44 | **GCDAsyncSocket** and **AsyncSocket** are TCP/IP socket networking libraries. Here are the key features available in both: 45 | 46 | - Native objective-c, fully self-contained in one class.
47 | _No need to muck around with sockets or streams. This class handles everything for you._ 48 | 49 | - Full delegate support
50 | _Errors, connections, read completions, write completions, progress, and disconnections all result in a call to your delegate method._ 51 | 52 | - Queued non-blocking reads and writes, with optional timeouts.
53 | _You tell it what to read or write, and it handles everything for you. Queueing, buffering, and searching for termination sequences within the stream - all handled for you automatically._ 54 | 55 | - Automatic socket acceptance.
56 | _Spin up a server socket, tell it to accept connections, and it will call you with new instances of itself for each connection._ 57 | 58 | - Support for TCP streams over IPv4 and IPv6.
59 | _Automatically connect to IPv4 or IPv6 hosts. Automatically accept incoming connections over both IPv4 and IPv6 with a single instance of this class. No more worrying about multiple sockets._ 60 | 61 | - Support for TLS / SSL
62 | _Secure your socket with ease using just a single method call. Available for both client and server sockets._ 63 | 64 | **GCDAsyncSocket** is built atop Grand Central Dispatch: 65 | 66 | - Fully GCD based and Thread-Safe
67 | _It runs entirely within its own GCD dispatch_queue, and is completely thread-safe. Further, the delegate methods are all invoked asynchronously onto a dispatch_queue of your choosing. This means parallel operation of your socket code, and your delegate/processing code._ 68 | 69 | - The Latest Technology & Performance Optimizations
70 | _Internally the library takes advantage of technologies such as [kqueue's](http://en.wikipedia.org/wiki/Kqueue) to limit [system calls](http://en.wikipedia.org/wiki/System_call) and optimize buffer allocations. In other words, peak performance._ 71 | 72 | **AsyncSocket** wraps CFSocket and CFStream: 73 | 74 | - Fully Run-loop based
75 | _Use it on the main thread or a worker thread. It plugs into the NSRunLoop with configurable modes._ 76 | 77 | ## UDP 78 | 79 | **GCDAsyncUdpSocket** and **AsyncUdpSocket** are UDP/IP socket networking libraries. Here are the key features available in both: 80 | 81 | - Native objective-c, fully self-contained in one class.
82 | _No need to muck around with low-level sockets. This class handles everything for you._ 83 | 84 | - Full delegate support.
85 | _Errors, send completions, receive completions, and disconnections all result in a call to your delegate method._ 86 | 87 | - Queued non-blocking send and receive operations, with optional timeouts.
88 | _You tell it what to send or receive, and it handles everything for you. Queueing, buffering, waiting and checking errno - all handled for you automatically._ 89 | 90 | - Support for IPv4 and IPv6.
91 | _Automatically send/recv using IPv4 and/or IPv6. No more worrying about multiple sockets._ 92 | 93 | **GCDAsyncUdpSocket** is built atop Grand Central Dispatch: 94 | 95 | - Fully GCD based and Thread-Safe
96 | _It runs entirely within its own GCD dispatch_queue, and is completely thread-safe. Further, the delegate methods are all invoked asynchronously onto a dispatch_queue of your choosing. This means parallel operation of your socket code, and your delegate/processing code._ 97 | 98 | **AsyncUdpSocket** wraps CFSocket: 99 | 100 | - Fully Run-loop based
101 | _Use it on the main thread or a worker thread. It plugs into the NSRunLoop with configurable modes._ 102 | 103 | *** 104 | 105 | Can't find the answer to your question in any of the [wiki](https://github.com/robbiehanson/CocoaAsyncSocket/wiki) articles? Try the **[mailing list](http://groups.google.com/group/cocoaasyncsocket)**. 106 |
107 |
108 | Love the project? Wanna buy me a coffee? (or a beer :D) [![donation](http://www.paypal.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2M8C699FQ8AW2) 109 | 110 | -------------------------------------------------------------------------------- /ServerExample/CocoaAsyncSocket/README.markdown: -------------------------------------------------------------------------------- 1 | # CocoaAsyncSocket 2 | [![Build Status](https://travis-ci.org/robbiehanson/CocoaAsyncSocket.svg?branch=master)](https://travis-ci.org/robbiehanson/CocoaAsyncSocket) [![Version Status](https://img.shields.io/cocoapods/v/CocoaAsyncSocket.svg?style=flat)](http://cocoadocs.org/docsets/CocoaAsyncSocket) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Platform](http://img.shields.io/cocoapods/p/CocoaAsyncSocket.svg?style=flat)](http://cocoapods.org/?q=CocoaAsyncSocket) [![license Public Domain](https://img.shields.io/badge/license-Public%20Domain-orange.svg?style=flat)](https://en.wikipedia.org/wiki/Public_domain) 3 | 4 | 5 | CocoaAsyncSocket provides easy-to-use and powerful asynchronous socket libraries for Mac and iOS. The classes are described below. 6 | 7 | ## Installation 8 | 9 | #### CocoaPods 10 | 11 | Install using [CocoaPods](http://cocoapods.org) by adding this line to your Podfile: 12 | 13 | ````ruby 14 | use_frameworks! # Add this if you are targeting iOS 8+ or using Swift 15 | pod 'CocoaAsyncSocket' 16 | ```` 17 | 18 | #### Carthage 19 | 20 | CocoaAsyncSocket is [Carthage](https://github.com/Carthage/Carthage) compatible. To include it, build your project with Carthage, then drag `Carthage/Build/iOS/CocoaAsyncSocket.framework` into your project. 21 | 22 | #### Manual 23 | 24 | You can also include it into your project by adding the source files directly, but you should probably be using a dependency manager to keep up to date. 25 | 26 | ### Importing 27 | 28 | Using Objective-C: 29 | 30 | ```obj-c 31 | @import CocoaAsyncSocket; // When using iOS 8+ frameworks 32 | // OR 33 | #import "CocoaAsyncSocket.h" // When not using frameworks, targeting iOS 7 or below 34 | ``` 35 | 36 | Using Swift: 37 | 38 | ```swift 39 | import CocoaAsyncSocket 40 | ``` 41 | 42 | ## TCP 43 | 44 | **GCDAsyncSocket** and **AsyncSocket** are TCP/IP socket networking libraries. Here are the key features available in both: 45 | 46 | - Native objective-c, fully self-contained in one class.
47 | _No need to muck around with sockets or streams. This class handles everything for you._ 48 | 49 | - Full delegate support
50 | _Errors, connections, read completions, write completions, progress, and disconnections all result in a call to your delegate method._ 51 | 52 | - Queued non-blocking reads and writes, with optional timeouts.
53 | _You tell it what to read or write, and it handles everything for you. Queueing, buffering, and searching for termination sequences within the stream - all handled for you automatically._ 54 | 55 | - Automatic socket acceptance.
56 | _Spin up a server socket, tell it to accept connections, and it will call you with new instances of itself for each connection._ 57 | 58 | - Support for TCP streams over IPv4 and IPv6.
59 | _Automatically connect to IPv4 or IPv6 hosts. Automatically accept incoming connections over both IPv4 and IPv6 with a single instance of this class. No more worrying about multiple sockets._ 60 | 61 | - Support for TLS / SSL
62 | _Secure your socket with ease using just a single method call. Available for both client and server sockets._ 63 | 64 | **GCDAsyncSocket** is built atop Grand Central Dispatch: 65 | 66 | - Fully GCD based and Thread-Safe
67 | _It runs entirely within its own GCD dispatch_queue, and is completely thread-safe. Further, the delegate methods are all invoked asynchronously onto a dispatch_queue of your choosing. This means parallel operation of your socket code, and your delegate/processing code._ 68 | 69 | - The Latest Technology & Performance Optimizations
70 | _Internally the library takes advantage of technologies such as [kqueue's](http://en.wikipedia.org/wiki/Kqueue) to limit [system calls](http://en.wikipedia.org/wiki/System_call) and optimize buffer allocations. In other words, peak performance._ 71 | 72 | **AsyncSocket** wraps CFSocket and CFStream: 73 | 74 | - Fully Run-loop based
75 | _Use it on the main thread or a worker thread. It plugs into the NSRunLoop with configurable modes._ 76 | 77 | ## UDP 78 | 79 | **GCDAsyncUdpSocket** and **AsyncUdpSocket** are UDP/IP socket networking libraries. Here are the key features available in both: 80 | 81 | - Native objective-c, fully self-contained in one class.
82 | _No need to muck around with low-level sockets. This class handles everything for you._ 83 | 84 | - Full delegate support.
85 | _Errors, send completions, receive completions, and disconnections all result in a call to your delegate method._ 86 | 87 | - Queued non-blocking send and receive operations, with optional timeouts.
88 | _You tell it what to send or receive, and it handles everything for you. Queueing, buffering, waiting and checking errno - all handled for you automatically._ 89 | 90 | - Support for IPv4 and IPv6.
91 | _Automatically send/recv using IPv4 and/or IPv6. No more worrying about multiple sockets._ 92 | 93 | **GCDAsyncUdpSocket** is built atop Grand Central Dispatch: 94 | 95 | - Fully GCD based and Thread-Safe
96 | _It runs entirely within its own GCD dispatch_queue, and is completely thread-safe. Further, the delegate methods are all invoked asynchronously onto a dispatch_queue of your choosing. This means parallel operation of your socket code, and your delegate/processing code._ 97 | 98 | **AsyncUdpSocket** wraps CFSocket: 99 | 100 | - Fully Run-loop based
101 | _Use it on the main thread or a worker thread. It plugs into the NSRunLoop with configurable modes._ 102 | 103 | *** 104 | 105 | Can't find the answer to your question in any of the [wiki](https://github.com/robbiehanson/CocoaAsyncSocket/wiki) articles? Try the **[mailing list](http://groups.google.com/group/cocoaasyncsocket)**. 106 |
107 |
108 | Love the project? Wanna buy me a coffee? (or a beer :D) [![donation](http://www.paypal.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2M8C699FQ8AW2) 109 | 110 | -------------------------------------------------------------------------------- /ServerExample/ServerExample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 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 | -------------------------------------------------------------------------------- /ClientExample/ClientExample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 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 | -------------------------------------------------------------------------------- /ClientExample/CocoaAsyncSocket/Source/RunLoop/AsyncUdpSocket.h: -------------------------------------------------------------------------------- 1 | // 2 | // AsyncUdpSocket.h 3 | // 4 | // This class is in the public domain. 5 | // Originally created by Robbie Hanson on Wed Oct 01 2008. 6 | // Updated and maintained by Deusty Designs and the Mac development community. 7 | // 8 | // http://code.google.com/p/cocoaasyncsocket/ 9 | // 10 | 11 | #import 12 | 13 | @class AsyncSendPacket; 14 | @class AsyncReceivePacket; 15 | 16 | extern NSString *const AsyncUdpSocketException; 17 | extern NSString *const AsyncUdpSocketErrorDomain; 18 | 19 | typedef NS_ENUM(NSInteger, AsyncUdpSocketError) { 20 | AsyncUdpSocketCFSocketError = kCFSocketError, // From CFSocketError enum 21 | AsyncUdpSocketNoError = 0, // Never used 22 | AsyncUdpSocketBadParameter, // Used if given a bad parameter (such as an improper address) 23 | AsyncUdpSocketIPv4Unavailable, // Used if you bind/connect using IPv6 only 24 | AsyncUdpSocketIPv6Unavailable, // Used if you bind/connect using IPv4 only (or iPhone) 25 | AsyncUdpSocketSendTimeoutError, 26 | AsyncUdpSocketReceiveTimeoutError 27 | }; 28 | 29 | @interface AsyncUdpSocket : NSObject 30 | { 31 | CFSocketRef theSocket4; // IPv4 socket 32 | CFSocketRef theSocket6; // IPv6 socket 33 | 34 | CFRunLoopSourceRef theSource4; // For theSocket4 35 | CFRunLoopSourceRef theSource6; // For theSocket6 36 | CFRunLoopRef theRunLoop; 37 | CFSocketContext theContext; 38 | NSArray *theRunLoopModes; 39 | 40 | NSMutableArray *theSendQueue; 41 | AsyncSendPacket *theCurrentSend; 42 | NSTimer *theSendTimer; 43 | 44 | NSMutableArray *theReceiveQueue; 45 | AsyncReceivePacket *theCurrentReceive; 46 | NSTimer *theReceiveTimer; 47 | 48 | id theDelegate; 49 | UInt16 theFlags; 50 | 51 | long theUserData; 52 | 53 | NSString *cachedLocalHost; 54 | UInt16 cachedLocalPort; 55 | 56 | NSString *cachedConnectedHost; 57 | UInt16 cachedConnectedPort; 58 | 59 | UInt32 maxReceiveBufferSize; 60 | } 61 | 62 | /** 63 | * Creates new instances of AsyncUdpSocket. 64 | **/ 65 | - (id)init; 66 | - (id)initWithDelegate:(id)delegate; 67 | - (id)initWithDelegate:(id)delegate userData:(long)userData; 68 | 69 | /** 70 | * Creates new instances of AsyncUdpSocket that support only IPv4 or IPv6. 71 | * The other init methods will support both, unless specifically binded or connected to one protocol. 72 | * If you know you'll only be using one protocol, these init methods may be a bit more efficient. 73 | **/ 74 | - (id)initIPv4; 75 | - (id)initIPv6; 76 | 77 | - (id)delegate; 78 | - (void)setDelegate:(id)delegate; 79 | 80 | - (long)userData; 81 | - (void)setUserData:(long)userData; 82 | 83 | /** 84 | * Returns the local address info for the socket. 85 | * 86 | * Note: Address info may not be available until after the socket has been bind'ed, 87 | * or until after data has been sent. 88 | **/ 89 | - (NSString *)localHost; 90 | - (UInt16)localPort; 91 | 92 | /** 93 | * Returns the remote address info for the socket. 94 | * 95 | * Note: Since UDP is connectionless by design, connected address info 96 | * will not be available unless the socket is explicitly connected to a remote host/port 97 | **/ 98 | - (NSString *)connectedHost; 99 | - (UInt16)connectedPort; 100 | 101 | /** 102 | * Returns whether or not this socket has been connected to a single host. 103 | * By design, UDP is a connectionless protocol, and connecting is not needed. 104 | * If connected, the socket will only be able to send/receive data to/from the connected host. 105 | **/ 106 | - (BOOL)isConnected; 107 | 108 | /** 109 | * Returns whether or not this socket has been closed. 110 | * The only way a socket can be closed is if you explicitly call one of the close methods. 111 | **/ 112 | - (BOOL)isClosed; 113 | 114 | /** 115 | * Returns whether or not this socket supports IPv4. 116 | * By default this will be true, unless the socket is specifically initialized as IPv6 only, 117 | * or is binded or connected to an IPv6 address. 118 | **/ 119 | - (BOOL)isIPv4; 120 | 121 | /** 122 | * Returns whether or not this socket supports IPv6. 123 | * By default this will be true, unless the socket is specifically initialized as IPv4 only, 124 | * or is binded or connected to an IPv4 address. 125 | * 126 | * This method will also return false on platforms that do not support IPv6. 127 | * Note: The iPhone does not currently support IPv6. 128 | **/ 129 | - (BOOL)isIPv6; 130 | 131 | /** 132 | * Returns the mtu of the socket. 133 | * If unknown, returns zero. 134 | * 135 | * Sending data larger than this may result in an error. 136 | * This is an advanced topic, and one should understand the wide range of mtu's on networks and the internet. 137 | * Therefore this method is only for reference and may be of little use in many situations. 138 | **/ 139 | - (unsigned int)maximumTransmissionUnit; 140 | 141 | /** 142 | * Binds the UDP socket to the given port and optional address. 143 | * Binding should be done for server sockets that receive data prior to sending it. 144 | * Client sockets can skip binding, 145 | * as the OS will automatically assign the socket an available port when it starts sending data. 146 | * 147 | * You cannot bind a socket after its been connected. 148 | * You can only bind a socket once. 149 | * You can still connect a socket (if desired) after binding. 150 | * 151 | * On success, returns YES. 152 | * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr. 153 | **/ 154 | - (BOOL)bindToPort:(UInt16)port error:(NSError **)errPtr; 155 | - (BOOL)bindToAddress:(NSString *)localAddr port:(UInt16)port error:(NSError **)errPtr; 156 | 157 | /** 158 | * Connects the UDP socket to the given host and port. 159 | * By design, UDP is a connectionless protocol, and connecting is not needed. 160 | * 161 | * Choosing to connect to a specific host/port has the following effect: 162 | * - You will only be able to send data to the connected host/port. 163 | * - You will only be able to receive data from the connected host/port. 164 | * - You will receive ICMP messages that come from the connected host/port, such as "connection refused". 165 | * 166 | * Connecting a UDP socket does not result in any communication on the socket. 167 | * It simply changes the internal state of the socket. 168 | * 169 | * You cannot bind a socket after its been connected. 170 | * You can only connect a socket once. 171 | * 172 | * On success, returns YES. 173 | * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr. 174 | **/ 175 | - (BOOL)connectToHost:(NSString *)host onPort:(UInt16)port error:(NSError **)errPtr; 176 | - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr; 177 | 178 | /** 179 | * Join multicast group 180 | * 181 | * Group should be an IP address (eg @"225.228.0.1") 182 | **/ 183 | - (BOOL)joinMulticastGroup:(NSString *)group error:(NSError **)errPtr; 184 | - (BOOL)joinMulticastGroup:(NSString *)group withAddress:(NSString *)interface error:(NSError **)errPtr; 185 | 186 | /** 187 | * By default, the underlying socket in the OS will not allow you to send broadcast messages. 188 | * In order to send broadcast messages, you need to enable this functionality in the socket. 189 | * 190 | * A broadcast is a UDP message to addresses like "192.168.255.255" or "255.255.255.255" that is 191 | * delivered to every host on the network. 192 | * The reason this is generally disabled by default is to prevent 193 | * accidental broadcast messages from flooding the network. 194 | **/ 195 | - (BOOL)enableBroadcast:(BOOL)flag error:(NSError **)errPtr; 196 | 197 | /** 198 | * Asynchronously sends the given data, with the given timeout and tag. 199 | * 200 | * This method may only be used with a connected socket. 201 | * 202 | * If data is nil or zero-length, this method does nothing and immediately returns NO. 203 | * If the socket is not connected, this method does nothing and immediately returns NO. 204 | **/ 205 | - (BOOL)sendData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 206 | 207 | /** 208 | * Asynchronously sends the given data, with the given timeout and tag, to the given host and port. 209 | * 210 | * This method cannot be used with a connected socket. 211 | * 212 | * If data is nil or zero-length, this method does nothing and immediately returns NO. 213 | * If the socket is connected, this method does nothing and immediately returns NO. 214 | * If unable to resolve host to a valid IPv4 or IPv6 address, this method returns NO. 215 | **/ 216 | - (BOOL)sendData:(NSData *)data toHost:(NSString *)host port:(UInt16)port withTimeout:(NSTimeInterval)timeout tag:(long)tag; 217 | 218 | /** 219 | * Asynchronously sends the given data, with the given timeout and tag, to the given address. 220 | * 221 | * This method cannot be used with a connected socket. 222 | * 223 | * If data is nil or zero-length, this method does nothing and immediately returns NO. 224 | * If the socket is connected, this method does nothing and immediately returns NO. 225 | **/ 226 | - (BOOL)sendData:(NSData *)data toAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout tag:(long)tag; 227 | 228 | /** 229 | * Asynchronously receives a single datagram packet. 230 | * 231 | * If the receive succeeds, the onUdpSocket:didReceiveData:fromHost:port:tag delegate method will be called. 232 | * Otherwise, a timeout will occur, and the onUdpSocket:didNotReceiveDataWithTag: delegate method will be called. 233 | **/ 234 | - (void)receiveWithTimeout:(NSTimeInterval)timeout tag:(long)tag; 235 | 236 | /** 237 | * Closes the socket immediately. Any pending send or receive operations are dropped. 238 | **/ 239 | - (void)close; 240 | 241 | /** 242 | * Closes after all pending send operations have completed. 243 | * After calling this, the sendData: and receive: methods will do nothing. 244 | * In other words, you won't be able to add any more send or receive operations to the queue. 245 | * The socket will close even if there are still pending receive operations. 246 | **/ 247 | - (void)closeAfterSending; 248 | 249 | /** 250 | * Closes after all pending receive operations have completed. 251 | * After calling this, the sendData: and receive: methods will do nothing. 252 | * In other words, you won't be able to add any more send or receive operations to the queue. 253 | * The socket will close even if there are still pending send operations. 254 | **/ 255 | - (void)closeAfterReceiving; 256 | 257 | /** 258 | * Closes after all pending send and receive operations have completed. 259 | * After calling this, the sendData: and receive: methods will do nothing. 260 | * In other words, you won't be able to add any more send or receive operations to the queue. 261 | **/ 262 | - (void)closeAfterSendingAndReceiving; 263 | 264 | /** 265 | * Gets/Sets the maximum size of the buffer that will be allocated for receive operations. 266 | * The default size is 9216 bytes. 267 | * 268 | * The theoretical maximum size of any IPv4 UDP packet is UINT16_MAX = 65535. 269 | * The theoretical maximum size of any IPv6 UDP packet is UINT32_MAX = 4294967295. 270 | * 271 | * In practice, however, the size of UDP packets will be much smaller. 272 | * Indeed most protocols will send and receive packets of only a few bytes, 273 | * or will set a limit on the size of packets to prevent fragmentation in the IP layer. 274 | * 275 | * If you set the buffer size too small, the sockets API in the OS will silently discard 276 | * any extra data, and you will not be notified of the error. 277 | **/ 278 | - (UInt32)maxReceiveBufferSize; 279 | - (void)setMaxReceiveBufferSize:(UInt32)max; 280 | 281 | /** 282 | * When you create an AsyncUdpSocket, it is added to the runloop of the current thread. 283 | * So it is easiest to simply create the socket on the thread you intend to use it. 284 | * 285 | * If, however, you need to move the socket to a separate thread at a later time, this 286 | * method may be used to accomplish the task. 287 | * 288 | * This method must be called from the thread/runloop the socket is currently running on. 289 | * 290 | * Note: After calling this method, all further method calls to this object should be done from the given runloop. 291 | * Also, all delegate calls will be sent on the given runloop. 292 | **/ 293 | - (BOOL)moveToRunLoop:(NSRunLoop *)runLoop; 294 | 295 | /** 296 | * Allows you to configure which run loop modes the socket uses. 297 | * The default set of run loop modes is NSDefaultRunLoopMode. 298 | * 299 | * If you'd like your socket to continue operation during other modes, you may want to add modes such as 300 | * NSModalPanelRunLoopMode or NSEventTrackingRunLoopMode. Or you may simply want to use NSRunLoopCommonModes. 301 | * 302 | * Note: NSRunLoopCommonModes is defined in 10.5. For previous versions one can use kCFRunLoopCommonModes. 303 | **/ 304 | - (BOOL)setRunLoopModes:(NSArray *)runLoopModes; 305 | 306 | /** 307 | * Returns the current run loop modes the AsyncSocket instance is operating in. 308 | * The default set of run loop modes is NSDefaultRunLoopMode. 309 | **/ 310 | - (NSArray *)runLoopModes; 311 | 312 | @end 313 | 314 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 315 | #pragma mark - 316 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 317 | 318 | @protocol AsyncUdpSocketDelegate 319 | @optional 320 | 321 | /** 322 | * Called when the datagram with the given tag has been sent. 323 | **/ 324 | - (void)onUdpSocket:(AsyncUdpSocket *)sock didSendDataWithTag:(long)tag; 325 | 326 | /** 327 | * Called if an error occurs while trying to send a datagram. 328 | * This could be due to a timeout, or something more serious such as the data being too large to fit in a sigle packet. 329 | **/ 330 | - (void)onUdpSocket:(AsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error; 331 | 332 | /** 333 | * Called when the socket has received the requested datagram. 334 | * 335 | * Due to the nature of UDP, you may occasionally receive undesired packets. 336 | * These may be rogue UDP packets from unknown hosts, 337 | * or they may be delayed packets arriving after retransmissions have already occurred. 338 | * It's important these packets are properly ignored, while not interfering with the flow of your implementation. 339 | * As an aid, this delegate method has a boolean return value. 340 | * If you ever need to ignore a received packet, simply return NO, 341 | * and AsyncUdpSocket will continue as if the packet never arrived. 342 | * That is, the original receive request will still be queued, and will still timeout as usual if a timeout was set. 343 | * For example, say you requested to receive data, and you set a timeout of 500 milliseconds, using a tag of 15. 344 | * If rogue data arrives after 250 milliseconds, this delegate method would be invoked, and you could simply return NO. 345 | * If the expected data then arrives within the next 250 milliseconds, 346 | * this delegate method will be invoked, with a tag of 15, just as if the rogue data never appeared. 347 | * 348 | * Under normal circumstances, you simply return YES from this method. 349 | **/ 350 | - (BOOL)onUdpSocket:(AsyncUdpSocket *)sock 351 | didReceiveData:(NSData *)data 352 | withTag:(long)tag 353 | fromHost:(NSString *)host 354 | port:(UInt16)port; 355 | 356 | /** 357 | * Called if an error occurs while trying to receive a requested datagram. 358 | * This is generally due to a timeout, but could potentially be something else if some kind of OS error occurred. 359 | **/ 360 | - (void)onUdpSocket:(AsyncUdpSocket *)sock didNotReceiveDataWithTag:(long)tag dueToError:(NSError *)error; 361 | 362 | /** 363 | * Called when the socket is closed. 364 | * A socket is only closed if you explicitly call one of the close methods. 365 | **/ 366 | - (void)onUdpSocketDidClose:(AsyncUdpSocket *)sock; 367 | 368 | @end 369 | -------------------------------------------------------------------------------- /ServerExample/CocoaAsyncSocket/Source/RunLoop/AsyncUdpSocket.h: -------------------------------------------------------------------------------- 1 | // 2 | // AsyncUdpSocket.h 3 | // 4 | // This class is in the public domain. 5 | // Originally created by Robbie Hanson on Wed Oct 01 2008. 6 | // Updated and maintained by Deusty Designs and the Mac development community. 7 | // 8 | // http://code.google.com/p/cocoaasyncsocket/ 9 | // 10 | 11 | #import 12 | 13 | @class AsyncSendPacket; 14 | @class AsyncReceivePacket; 15 | 16 | extern NSString *const AsyncUdpSocketException; 17 | extern NSString *const AsyncUdpSocketErrorDomain; 18 | 19 | typedef NS_ENUM(NSInteger, AsyncUdpSocketError) { 20 | AsyncUdpSocketCFSocketError = kCFSocketError, // From CFSocketError enum 21 | AsyncUdpSocketNoError = 0, // Never used 22 | AsyncUdpSocketBadParameter, // Used if given a bad parameter (such as an improper address) 23 | AsyncUdpSocketIPv4Unavailable, // Used if you bind/connect using IPv6 only 24 | AsyncUdpSocketIPv6Unavailable, // Used if you bind/connect using IPv4 only (or iPhone) 25 | AsyncUdpSocketSendTimeoutError, 26 | AsyncUdpSocketReceiveTimeoutError 27 | }; 28 | 29 | @interface AsyncUdpSocket : NSObject 30 | { 31 | CFSocketRef theSocket4; // IPv4 socket 32 | CFSocketRef theSocket6; // IPv6 socket 33 | 34 | CFRunLoopSourceRef theSource4; // For theSocket4 35 | CFRunLoopSourceRef theSource6; // For theSocket6 36 | CFRunLoopRef theRunLoop; 37 | CFSocketContext theContext; 38 | NSArray *theRunLoopModes; 39 | 40 | NSMutableArray *theSendQueue; 41 | AsyncSendPacket *theCurrentSend; 42 | NSTimer *theSendTimer; 43 | 44 | NSMutableArray *theReceiveQueue; 45 | AsyncReceivePacket *theCurrentReceive; 46 | NSTimer *theReceiveTimer; 47 | 48 | id theDelegate; 49 | UInt16 theFlags; 50 | 51 | long theUserData; 52 | 53 | NSString *cachedLocalHost; 54 | UInt16 cachedLocalPort; 55 | 56 | NSString *cachedConnectedHost; 57 | UInt16 cachedConnectedPort; 58 | 59 | UInt32 maxReceiveBufferSize; 60 | } 61 | 62 | /** 63 | * Creates new instances of AsyncUdpSocket. 64 | **/ 65 | - (id)init; 66 | - (id)initWithDelegate:(id)delegate; 67 | - (id)initWithDelegate:(id)delegate userData:(long)userData; 68 | 69 | /** 70 | * Creates new instances of AsyncUdpSocket that support only IPv4 or IPv6. 71 | * The other init methods will support both, unless specifically binded or connected to one protocol. 72 | * If you know you'll only be using one protocol, these init methods may be a bit more efficient. 73 | **/ 74 | - (id)initIPv4; 75 | - (id)initIPv6; 76 | 77 | - (id)delegate; 78 | - (void)setDelegate:(id)delegate; 79 | 80 | - (long)userData; 81 | - (void)setUserData:(long)userData; 82 | 83 | /** 84 | * Returns the local address info for the socket. 85 | * 86 | * Note: Address info may not be available until after the socket has been bind'ed, 87 | * or until after data has been sent. 88 | **/ 89 | - (NSString *)localHost; 90 | - (UInt16)localPort; 91 | 92 | /** 93 | * Returns the remote address info for the socket. 94 | * 95 | * Note: Since UDP is connectionless by design, connected address info 96 | * will not be available unless the socket is explicitly connected to a remote host/port 97 | **/ 98 | - (NSString *)connectedHost; 99 | - (UInt16)connectedPort; 100 | 101 | /** 102 | * Returns whether or not this socket has been connected to a single host. 103 | * By design, UDP is a connectionless protocol, and connecting is not needed. 104 | * If connected, the socket will only be able to send/receive data to/from the connected host. 105 | **/ 106 | - (BOOL)isConnected; 107 | 108 | /** 109 | * Returns whether or not this socket has been closed. 110 | * The only way a socket can be closed is if you explicitly call one of the close methods. 111 | **/ 112 | - (BOOL)isClosed; 113 | 114 | /** 115 | * Returns whether or not this socket supports IPv4. 116 | * By default this will be true, unless the socket is specifically initialized as IPv6 only, 117 | * or is binded or connected to an IPv6 address. 118 | **/ 119 | - (BOOL)isIPv4; 120 | 121 | /** 122 | * Returns whether or not this socket supports IPv6. 123 | * By default this will be true, unless the socket is specifically initialized as IPv4 only, 124 | * or is binded or connected to an IPv4 address. 125 | * 126 | * This method will also return false on platforms that do not support IPv6. 127 | * Note: The iPhone does not currently support IPv6. 128 | **/ 129 | - (BOOL)isIPv6; 130 | 131 | /** 132 | * Returns the mtu of the socket. 133 | * If unknown, returns zero. 134 | * 135 | * Sending data larger than this may result in an error. 136 | * This is an advanced topic, and one should understand the wide range of mtu's on networks and the internet. 137 | * Therefore this method is only for reference and may be of little use in many situations. 138 | **/ 139 | - (unsigned int)maximumTransmissionUnit; 140 | 141 | /** 142 | * Binds the UDP socket to the given port and optional address. 143 | * Binding should be done for server sockets that receive data prior to sending it. 144 | * Client sockets can skip binding, 145 | * as the OS will automatically assign the socket an available port when it starts sending data. 146 | * 147 | * You cannot bind a socket after its been connected. 148 | * You can only bind a socket once. 149 | * You can still connect a socket (if desired) after binding. 150 | * 151 | * On success, returns YES. 152 | * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr. 153 | **/ 154 | - (BOOL)bindToPort:(UInt16)port error:(NSError **)errPtr; 155 | - (BOOL)bindToAddress:(NSString *)localAddr port:(UInt16)port error:(NSError **)errPtr; 156 | 157 | /** 158 | * Connects the UDP socket to the given host and port. 159 | * By design, UDP is a connectionless protocol, and connecting is not needed. 160 | * 161 | * Choosing to connect to a specific host/port has the following effect: 162 | * - You will only be able to send data to the connected host/port. 163 | * - You will only be able to receive data from the connected host/port. 164 | * - You will receive ICMP messages that come from the connected host/port, such as "connection refused". 165 | * 166 | * Connecting a UDP socket does not result in any communication on the socket. 167 | * It simply changes the internal state of the socket. 168 | * 169 | * You cannot bind a socket after its been connected. 170 | * You can only connect a socket once. 171 | * 172 | * On success, returns YES. 173 | * Otherwise returns NO, and sets errPtr. If you don't care about the error, you can pass nil for errPtr. 174 | **/ 175 | - (BOOL)connectToHost:(NSString *)host onPort:(UInt16)port error:(NSError **)errPtr; 176 | - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr; 177 | 178 | /** 179 | * Join multicast group 180 | * 181 | * Group should be an IP address (eg @"225.228.0.1") 182 | **/ 183 | - (BOOL)joinMulticastGroup:(NSString *)group error:(NSError **)errPtr; 184 | - (BOOL)joinMulticastGroup:(NSString *)group withAddress:(NSString *)interface error:(NSError **)errPtr; 185 | 186 | /** 187 | * By default, the underlying socket in the OS will not allow you to send broadcast messages. 188 | * In order to send broadcast messages, you need to enable this functionality in the socket. 189 | * 190 | * A broadcast is a UDP message to addresses like "192.168.255.255" or "255.255.255.255" that is 191 | * delivered to every host on the network. 192 | * The reason this is generally disabled by default is to prevent 193 | * accidental broadcast messages from flooding the network. 194 | **/ 195 | - (BOOL)enableBroadcast:(BOOL)flag error:(NSError **)errPtr; 196 | 197 | /** 198 | * Asynchronously sends the given data, with the given timeout and tag. 199 | * 200 | * This method may only be used with a connected socket. 201 | * 202 | * If data is nil or zero-length, this method does nothing and immediately returns NO. 203 | * If the socket is not connected, this method does nothing and immediately returns NO. 204 | **/ 205 | - (BOOL)sendData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 206 | 207 | /** 208 | * Asynchronously sends the given data, with the given timeout and tag, to the given host and port. 209 | * 210 | * This method cannot be used with a connected socket. 211 | * 212 | * If data is nil or zero-length, this method does nothing and immediately returns NO. 213 | * If the socket is connected, this method does nothing and immediately returns NO. 214 | * If unable to resolve host to a valid IPv4 or IPv6 address, this method returns NO. 215 | **/ 216 | - (BOOL)sendData:(NSData *)data toHost:(NSString *)host port:(UInt16)port withTimeout:(NSTimeInterval)timeout tag:(long)tag; 217 | 218 | /** 219 | * Asynchronously sends the given data, with the given timeout and tag, to the given address. 220 | * 221 | * This method cannot be used with a connected socket. 222 | * 223 | * If data is nil or zero-length, this method does nothing and immediately returns NO. 224 | * If the socket is connected, this method does nothing and immediately returns NO. 225 | **/ 226 | - (BOOL)sendData:(NSData *)data toAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout tag:(long)tag; 227 | 228 | /** 229 | * Asynchronously receives a single datagram packet. 230 | * 231 | * If the receive succeeds, the onUdpSocket:didReceiveData:fromHost:port:tag delegate method will be called. 232 | * Otherwise, a timeout will occur, and the onUdpSocket:didNotReceiveDataWithTag: delegate method will be called. 233 | **/ 234 | - (void)receiveWithTimeout:(NSTimeInterval)timeout tag:(long)tag; 235 | 236 | /** 237 | * Closes the socket immediately. Any pending send or receive operations are dropped. 238 | **/ 239 | - (void)close; 240 | 241 | /** 242 | * Closes after all pending send operations have completed. 243 | * After calling this, the sendData: and receive: methods will do nothing. 244 | * In other words, you won't be able to add any more send or receive operations to the queue. 245 | * The socket will close even if there are still pending receive operations. 246 | **/ 247 | - (void)closeAfterSending; 248 | 249 | /** 250 | * Closes after all pending receive operations have completed. 251 | * After calling this, the sendData: and receive: methods will do nothing. 252 | * In other words, you won't be able to add any more send or receive operations to the queue. 253 | * The socket will close even if there are still pending send operations. 254 | **/ 255 | - (void)closeAfterReceiving; 256 | 257 | /** 258 | * Closes after all pending send and receive operations have completed. 259 | * After calling this, the sendData: and receive: methods will do nothing. 260 | * In other words, you won't be able to add any more send or receive operations to the queue. 261 | **/ 262 | - (void)closeAfterSendingAndReceiving; 263 | 264 | /** 265 | * Gets/Sets the maximum size of the buffer that will be allocated for receive operations. 266 | * The default size is 9216 bytes. 267 | * 268 | * The theoretical maximum size of any IPv4 UDP packet is UINT16_MAX = 65535. 269 | * The theoretical maximum size of any IPv6 UDP packet is UINT32_MAX = 4294967295. 270 | * 271 | * In practice, however, the size of UDP packets will be much smaller. 272 | * Indeed most protocols will send and receive packets of only a few bytes, 273 | * or will set a limit on the size of packets to prevent fragmentation in the IP layer. 274 | * 275 | * If you set the buffer size too small, the sockets API in the OS will silently discard 276 | * any extra data, and you will not be notified of the error. 277 | **/ 278 | - (UInt32)maxReceiveBufferSize; 279 | - (void)setMaxReceiveBufferSize:(UInt32)max; 280 | 281 | /** 282 | * When you create an AsyncUdpSocket, it is added to the runloop of the current thread. 283 | * So it is easiest to simply create the socket on the thread you intend to use it. 284 | * 285 | * If, however, you need to move the socket to a separate thread at a later time, this 286 | * method may be used to accomplish the task. 287 | * 288 | * This method must be called from the thread/runloop the socket is currently running on. 289 | * 290 | * Note: After calling this method, all further method calls to this object should be done from the given runloop. 291 | * Also, all delegate calls will be sent on the given runloop. 292 | **/ 293 | - (BOOL)moveToRunLoop:(NSRunLoop *)runLoop; 294 | 295 | /** 296 | * Allows you to configure which run loop modes the socket uses. 297 | * The default set of run loop modes is NSDefaultRunLoopMode. 298 | * 299 | * If you'd like your socket to continue operation during other modes, you may want to add modes such as 300 | * NSModalPanelRunLoopMode or NSEventTrackingRunLoopMode. Or you may simply want to use NSRunLoopCommonModes. 301 | * 302 | * Note: NSRunLoopCommonModes is defined in 10.5. For previous versions one can use kCFRunLoopCommonModes. 303 | **/ 304 | - (BOOL)setRunLoopModes:(NSArray *)runLoopModes; 305 | 306 | /** 307 | * Returns the current run loop modes the AsyncSocket instance is operating in. 308 | * The default set of run loop modes is NSDefaultRunLoopMode. 309 | **/ 310 | - (NSArray *)runLoopModes; 311 | 312 | @end 313 | 314 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 315 | #pragma mark - 316 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 317 | 318 | @protocol AsyncUdpSocketDelegate 319 | @optional 320 | 321 | /** 322 | * Called when the datagram with the given tag has been sent. 323 | **/ 324 | - (void)onUdpSocket:(AsyncUdpSocket *)sock didSendDataWithTag:(long)tag; 325 | 326 | /** 327 | * Called if an error occurs while trying to send a datagram. 328 | * This could be due to a timeout, or something more serious such as the data being too large to fit in a sigle packet. 329 | **/ 330 | - (void)onUdpSocket:(AsyncUdpSocket *)sock didNotSendDataWithTag:(long)tag dueToError:(NSError *)error; 331 | 332 | /** 333 | * Called when the socket has received the requested datagram. 334 | * 335 | * Due to the nature of UDP, you may occasionally receive undesired packets. 336 | * These may be rogue UDP packets from unknown hosts, 337 | * or they may be delayed packets arriving after retransmissions have already occurred. 338 | * It's important these packets are properly ignored, while not interfering with the flow of your implementation. 339 | * As an aid, this delegate method has a boolean return value. 340 | * If you ever need to ignore a received packet, simply return NO, 341 | * and AsyncUdpSocket will continue as if the packet never arrived. 342 | * That is, the original receive request will still be queued, and will still timeout as usual if a timeout was set. 343 | * For example, say you requested to receive data, and you set a timeout of 500 milliseconds, using a tag of 15. 344 | * If rogue data arrives after 250 milliseconds, this delegate method would be invoked, and you could simply return NO. 345 | * If the expected data then arrives within the next 250 milliseconds, 346 | * this delegate method will be invoked, with a tag of 15, just as if the rogue data never appeared. 347 | * 348 | * Under normal circumstances, you simply return YES from this method. 349 | **/ 350 | - (BOOL)onUdpSocket:(AsyncUdpSocket *)sock 351 | didReceiveData:(NSData *)data 352 | withTag:(long)tag 353 | fromHost:(NSString *)host 354 | port:(UInt16)port; 355 | 356 | /** 357 | * Called if an error occurs while trying to receive a requested datagram. 358 | * This is generally due to a timeout, but could potentially be something else if some kind of OS error occurred. 359 | **/ 360 | - (void)onUdpSocket:(AsyncUdpSocket *)sock didNotReceiveDataWithTag:(long)tag dueToError:(NSError *)error; 361 | 362 | /** 363 | * Called when the socket is closed. 364 | * A socket is only closed if you explicitly call one of the close methods. 365 | **/ 366 | - (void)onUdpSocketDidClose:(AsyncUdpSocket *)sock; 367 | 368 | @end 369 | -------------------------------------------------------------------------------- /ClientExample/ClientExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4AA9F7BD1F9D849E00DFA163 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F7BC1F9D849E00DFA163 /* AppDelegate.m */; }; 11 | 4AA9F7C01F9D849E00DFA163 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F7BF1F9D849E00DFA163 /* ViewController.m */; }; 12 | 4AA9F7C31F9D849E00DFA163 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4AA9F7C11F9D849E00DFA163 /* Main.storyboard */; }; 13 | 4AA9F7C51F9D849E00DFA163 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4AA9F7C41F9D849E00DFA163 /* Assets.xcassets */; }; 14 | 4AA9F7C81F9D849E00DFA163 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4AA9F7C61F9D849E00DFA163 /* LaunchScreen.storyboard */; }; 15 | 4AA9F7CB1F9D849E00DFA163 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F7CA1F9D849E00DFA163 /* main.m */; }; 16 | 4AA9F7D51F9D849F00DFA163 /* ClientExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F7D41F9D849F00DFA163 /* ClientExampleTests.m */; }; 17 | 4AA9F7E01F9D849F00DFA163 /* ClientExampleUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F7DF1F9D849F00DFA163 /* ClientExampleUITests.m */; }; 18 | 4AA9F7FB1F9D84A900DFA163 /* README.markdown in Resources */ = {isa = PBXBuildFile; fileRef = 4AA9F7EE1F9D84A900DFA163 /* README.markdown */; }; 19 | 4AA9F7FC1F9D84A900DFA163 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F7F31F9D84A900DFA163 /* GCDAsyncSocket.m */; }; 20 | 4AA9F7FD1F9D84A900DFA163 /* GCDAsyncUdpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F7F51F9D84A900DFA163 /* GCDAsyncUdpSocket.m */; }; 21 | 4AA9F7FE1F9D84A900DFA163 /* AsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F7F81F9D84A900DFA163 /* AsyncSocket.m */; }; 22 | 4AA9F7FF1F9D84A900DFA163 /* AsyncUdpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F7FA1F9D84A900DFA163 /* AsyncUdpSocket.m */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXContainerItemProxy section */ 26 | 4AA9F7D11F9D849F00DFA163 /* PBXContainerItemProxy */ = { 27 | isa = PBXContainerItemProxy; 28 | containerPortal = 4AA9F7B01F9D849E00DFA163 /* Project object */; 29 | proxyType = 1; 30 | remoteGlobalIDString = 4AA9F7B71F9D849E00DFA163; 31 | remoteInfo = ClientExample; 32 | }; 33 | 4AA9F7DC1F9D849F00DFA163 /* PBXContainerItemProxy */ = { 34 | isa = PBXContainerItemProxy; 35 | containerPortal = 4AA9F7B01F9D849E00DFA163 /* Project object */; 36 | proxyType = 1; 37 | remoteGlobalIDString = 4AA9F7B71F9D849E00DFA163; 38 | remoteInfo = ClientExample; 39 | }; 40 | /* End PBXContainerItemProxy section */ 41 | 42 | /* Begin PBXFileReference section */ 43 | 4AA9F7B81F9D849E00DFA163 /* ClientExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ClientExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 4AA9F7BB1F9D849E00DFA163 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 45 | 4AA9F7BC1F9D849E00DFA163 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 46 | 4AA9F7BE1F9D849E00DFA163 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 47 | 4AA9F7BF1F9D849E00DFA163 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 48 | 4AA9F7C21F9D849E00DFA163 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 49 | 4AA9F7C41F9D849E00DFA163 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 50 | 4AA9F7C71F9D849E00DFA163 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 51 | 4AA9F7C91F9D849E00DFA163 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | 4AA9F7CA1F9D849E00DFA163 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 53 | 4AA9F7D01F9D849F00DFA163 /* ClientExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ClientExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 4AA9F7D41F9D849F00DFA163 /* ClientExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ClientExampleTests.m; sourceTree = ""; }; 55 | 4AA9F7D61F9D849F00DFA163 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 4AA9F7DB1F9D849F00DFA163 /* ClientExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ClientExampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 4AA9F7DF1F9D849F00DFA163 /* ClientExampleUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ClientExampleUITests.m; sourceTree = ""; }; 58 | 4AA9F7E11F9D849F00DFA163 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 59 | 4AA9F7EE1F9D84A900DFA163 /* README.markdown */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.markdown; sourceTree = ""; }; 60 | 4AA9F7F01F9D84A900DFA163 /* CocoaAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CocoaAsyncSocket.h; sourceTree = ""; }; 61 | 4AA9F7F21F9D84A900DFA163 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncSocket.h; sourceTree = ""; }; 62 | 4AA9F7F31F9D84A900DFA163 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncSocket.m; sourceTree = ""; }; 63 | 4AA9F7F41F9D84A900DFA163 /* GCDAsyncUdpSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncUdpSocket.h; sourceTree = ""; }; 64 | 4AA9F7F51F9D84A900DFA163 /* GCDAsyncUdpSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncUdpSocket.m; sourceTree = ""; }; 65 | 4AA9F7F71F9D84A900DFA163 /* AsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncSocket.h; sourceTree = ""; }; 66 | 4AA9F7F81F9D84A900DFA163 /* AsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AsyncSocket.m; sourceTree = ""; }; 67 | 4AA9F7F91F9D84A900DFA163 /* AsyncUdpSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncUdpSocket.h; sourceTree = ""; }; 68 | 4AA9F7FA1F9D84A900DFA163 /* AsyncUdpSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AsyncUdpSocket.m; sourceTree = ""; }; 69 | /* End PBXFileReference section */ 70 | 71 | /* Begin PBXFrameworksBuildPhase section */ 72 | 4AA9F7B51F9D849E00DFA163 /* Frameworks */ = { 73 | isa = PBXFrameworksBuildPhase; 74 | buildActionMask = 2147483647; 75 | files = ( 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | 4AA9F7CD1F9D849F00DFA163 /* Frameworks */ = { 80 | isa = PBXFrameworksBuildPhase; 81 | buildActionMask = 2147483647; 82 | files = ( 83 | ); 84 | runOnlyForDeploymentPostprocessing = 0; 85 | }; 86 | 4AA9F7D81F9D849F00DFA163 /* Frameworks */ = { 87 | isa = PBXFrameworksBuildPhase; 88 | buildActionMask = 2147483647; 89 | files = ( 90 | ); 91 | runOnlyForDeploymentPostprocessing = 0; 92 | }; 93 | /* End PBXFrameworksBuildPhase section */ 94 | 95 | /* Begin PBXGroup section */ 96 | 4AA9F7AF1F9D849E00DFA163 = { 97 | isa = PBXGroup; 98 | children = ( 99 | 4AA9F7ED1F9D84A900DFA163 /* CocoaAsyncSocket */, 100 | 4AA9F7BA1F9D849E00DFA163 /* ClientExample */, 101 | 4AA9F7D31F9D849F00DFA163 /* ClientExampleTests */, 102 | 4AA9F7DE1F9D849F00DFA163 /* ClientExampleUITests */, 103 | 4AA9F7B91F9D849E00DFA163 /* Products */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | 4AA9F7B91F9D849E00DFA163 /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 4AA9F7B81F9D849E00DFA163 /* ClientExample.app */, 111 | 4AA9F7D01F9D849F00DFA163 /* ClientExampleTests.xctest */, 112 | 4AA9F7DB1F9D849F00DFA163 /* ClientExampleUITests.xctest */, 113 | ); 114 | name = Products; 115 | sourceTree = ""; 116 | }; 117 | 4AA9F7BA1F9D849E00DFA163 /* ClientExample */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 4AA9F7BB1F9D849E00DFA163 /* AppDelegate.h */, 121 | 4AA9F7BC1F9D849E00DFA163 /* AppDelegate.m */, 122 | 4AA9F7BE1F9D849E00DFA163 /* ViewController.h */, 123 | 4AA9F7BF1F9D849E00DFA163 /* ViewController.m */, 124 | 4AA9F7C11F9D849E00DFA163 /* Main.storyboard */, 125 | 4AA9F7C41F9D849E00DFA163 /* Assets.xcassets */, 126 | 4AA9F7C61F9D849E00DFA163 /* LaunchScreen.storyboard */, 127 | 4AA9F7C91F9D849E00DFA163 /* Info.plist */, 128 | 4AA9F7CA1F9D849E00DFA163 /* main.m */, 129 | ); 130 | path = ClientExample; 131 | sourceTree = ""; 132 | }; 133 | 4AA9F7D31F9D849F00DFA163 /* ClientExampleTests */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 4AA9F7D41F9D849F00DFA163 /* ClientExampleTests.m */, 137 | 4AA9F7D61F9D849F00DFA163 /* Info.plist */, 138 | ); 139 | path = ClientExampleTests; 140 | sourceTree = ""; 141 | }; 142 | 4AA9F7DE1F9D849F00DFA163 /* ClientExampleUITests */ = { 143 | isa = PBXGroup; 144 | children = ( 145 | 4AA9F7DF1F9D849F00DFA163 /* ClientExampleUITests.m */, 146 | 4AA9F7E11F9D849F00DFA163 /* Info.plist */, 147 | ); 148 | path = ClientExampleUITests; 149 | sourceTree = ""; 150 | }; 151 | 4AA9F7ED1F9D84A900DFA163 /* CocoaAsyncSocket */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | 4AA9F7EE1F9D84A900DFA163 /* README.markdown */, 155 | 4AA9F7EF1F9D84A900DFA163 /* Source */, 156 | ); 157 | path = CocoaAsyncSocket; 158 | sourceTree = ""; 159 | }; 160 | 4AA9F7EF1F9D84A900DFA163 /* Source */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | 4AA9F7F01F9D84A900DFA163 /* CocoaAsyncSocket.h */, 164 | 4AA9F7F11F9D84A900DFA163 /* GCD */, 165 | 4AA9F7F61F9D84A900DFA163 /* RunLoop */, 166 | ); 167 | path = Source; 168 | sourceTree = ""; 169 | }; 170 | 4AA9F7F11F9D84A900DFA163 /* GCD */ = { 171 | isa = PBXGroup; 172 | children = ( 173 | 4AA9F7F21F9D84A900DFA163 /* GCDAsyncSocket.h */, 174 | 4AA9F7F31F9D84A900DFA163 /* GCDAsyncSocket.m */, 175 | 4AA9F7F41F9D84A900DFA163 /* GCDAsyncUdpSocket.h */, 176 | 4AA9F7F51F9D84A900DFA163 /* GCDAsyncUdpSocket.m */, 177 | ); 178 | path = GCD; 179 | sourceTree = ""; 180 | }; 181 | 4AA9F7F61F9D84A900DFA163 /* RunLoop */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 4AA9F7F71F9D84A900DFA163 /* AsyncSocket.h */, 185 | 4AA9F7F81F9D84A900DFA163 /* AsyncSocket.m */, 186 | 4AA9F7F91F9D84A900DFA163 /* AsyncUdpSocket.h */, 187 | 4AA9F7FA1F9D84A900DFA163 /* AsyncUdpSocket.m */, 188 | ); 189 | path = RunLoop; 190 | sourceTree = ""; 191 | }; 192 | /* End PBXGroup section */ 193 | 194 | /* Begin PBXNativeTarget section */ 195 | 4AA9F7B71F9D849E00DFA163 /* ClientExample */ = { 196 | isa = PBXNativeTarget; 197 | buildConfigurationList = 4AA9F7E41F9D849F00DFA163 /* Build configuration list for PBXNativeTarget "ClientExample" */; 198 | buildPhases = ( 199 | 4AA9F7B41F9D849E00DFA163 /* Sources */, 200 | 4AA9F7B51F9D849E00DFA163 /* Frameworks */, 201 | 4AA9F7B61F9D849E00DFA163 /* Resources */, 202 | ); 203 | buildRules = ( 204 | ); 205 | dependencies = ( 206 | ); 207 | name = ClientExample; 208 | productName = ClientExample; 209 | productReference = 4AA9F7B81F9D849E00DFA163 /* ClientExample.app */; 210 | productType = "com.apple.product-type.application"; 211 | }; 212 | 4AA9F7CF1F9D849F00DFA163 /* ClientExampleTests */ = { 213 | isa = PBXNativeTarget; 214 | buildConfigurationList = 4AA9F7E71F9D849F00DFA163 /* Build configuration list for PBXNativeTarget "ClientExampleTests" */; 215 | buildPhases = ( 216 | 4AA9F7CC1F9D849F00DFA163 /* Sources */, 217 | 4AA9F7CD1F9D849F00DFA163 /* Frameworks */, 218 | 4AA9F7CE1F9D849F00DFA163 /* Resources */, 219 | ); 220 | buildRules = ( 221 | ); 222 | dependencies = ( 223 | 4AA9F7D21F9D849F00DFA163 /* PBXTargetDependency */, 224 | ); 225 | name = ClientExampleTests; 226 | productName = ClientExampleTests; 227 | productReference = 4AA9F7D01F9D849F00DFA163 /* ClientExampleTests.xctest */; 228 | productType = "com.apple.product-type.bundle.unit-test"; 229 | }; 230 | 4AA9F7DA1F9D849F00DFA163 /* ClientExampleUITests */ = { 231 | isa = PBXNativeTarget; 232 | buildConfigurationList = 4AA9F7EA1F9D849F00DFA163 /* Build configuration list for PBXNativeTarget "ClientExampleUITests" */; 233 | buildPhases = ( 234 | 4AA9F7D71F9D849F00DFA163 /* Sources */, 235 | 4AA9F7D81F9D849F00DFA163 /* Frameworks */, 236 | 4AA9F7D91F9D849F00DFA163 /* Resources */, 237 | ); 238 | buildRules = ( 239 | ); 240 | dependencies = ( 241 | 4AA9F7DD1F9D849F00DFA163 /* PBXTargetDependency */, 242 | ); 243 | name = ClientExampleUITests; 244 | productName = ClientExampleUITests; 245 | productReference = 4AA9F7DB1F9D849F00DFA163 /* ClientExampleUITests.xctest */; 246 | productType = "com.apple.product-type.bundle.ui-testing"; 247 | }; 248 | /* End PBXNativeTarget section */ 249 | 250 | /* Begin PBXProject section */ 251 | 4AA9F7B01F9D849E00DFA163 /* Project object */ = { 252 | isa = PBXProject; 253 | attributes = { 254 | LastUpgradeCheck = 0900; 255 | ORGANIZATIONNAME = "http://www.cnblogs.com/saytome/"; 256 | TargetAttributes = { 257 | 4AA9F7B71F9D849E00DFA163 = { 258 | CreatedOnToolsVersion = 9.0; 259 | ProvisioningStyle = Automatic; 260 | }; 261 | 4AA9F7CF1F9D849F00DFA163 = { 262 | CreatedOnToolsVersion = 9.0; 263 | ProvisioningStyle = Automatic; 264 | TestTargetID = 4AA9F7B71F9D849E00DFA163; 265 | }; 266 | 4AA9F7DA1F9D849F00DFA163 = { 267 | CreatedOnToolsVersion = 9.0; 268 | ProvisioningStyle = Automatic; 269 | TestTargetID = 4AA9F7B71F9D849E00DFA163; 270 | }; 271 | }; 272 | }; 273 | buildConfigurationList = 4AA9F7B31F9D849E00DFA163 /* Build configuration list for PBXProject "ClientExample" */; 274 | compatibilityVersion = "Xcode 8.0"; 275 | developmentRegion = en; 276 | hasScannedForEncodings = 0; 277 | knownRegions = ( 278 | en, 279 | Base, 280 | ); 281 | mainGroup = 4AA9F7AF1F9D849E00DFA163; 282 | productRefGroup = 4AA9F7B91F9D849E00DFA163 /* Products */; 283 | projectDirPath = ""; 284 | projectRoot = ""; 285 | targets = ( 286 | 4AA9F7B71F9D849E00DFA163 /* ClientExample */, 287 | 4AA9F7CF1F9D849F00DFA163 /* ClientExampleTests */, 288 | 4AA9F7DA1F9D849F00DFA163 /* ClientExampleUITests */, 289 | ); 290 | }; 291 | /* End PBXProject section */ 292 | 293 | /* Begin PBXResourcesBuildPhase section */ 294 | 4AA9F7B61F9D849E00DFA163 /* Resources */ = { 295 | isa = PBXResourcesBuildPhase; 296 | buildActionMask = 2147483647; 297 | files = ( 298 | 4AA9F7C81F9D849E00DFA163 /* LaunchScreen.storyboard in Resources */, 299 | 4AA9F7C51F9D849E00DFA163 /* Assets.xcassets in Resources */, 300 | 4AA9F7FB1F9D84A900DFA163 /* README.markdown in Resources */, 301 | 4AA9F7C31F9D849E00DFA163 /* Main.storyboard in Resources */, 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | }; 305 | 4AA9F7CE1F9D849F00DFA163 /* Resources */ = { 306 | isa = PBXResourcesBuildPhase; 307 | buildActionMask = 2147483647; 308 | files = ( 309 | ); 310 | runOnlyForDeploymentPostprocessing = 0; 311 | }; 312 | 4AA9F7D91F9D849F00DFA163 /* Resources */ = { 313 | isa = PBXResourcesBuildPhase; 314 | buildActionMask = 2147483647; 315 | files = ( 316 | ); 317 | runOnlyForDeploymentPostprocessing = 0; 318 | }; 319 | /* End PBXResourcesBuildPhase section */ 320 | 321 | /* Begin PBXSourcesBuildPhase section */ 322 | 4AA9F7B41F9D849E00DFA163 /* Sources */ = { 323 | isa = PBXSourcesBuildPhase; 324 | buildActionMask = 2147483647; 325 | files = ( 326 | 4AA9F7FC1F9D84A900DFA163 /* GCDAsyncSocket.m in Sources */, 327 | 4AA9F7FD1F9D84A900DFA163 /* GCDAsyncUdpSocket.m in Sources */, 328 | 4AA9F7C01F9D849E00DFA163 /* ViewController.m in Sources */, 329 | 4AA9F7FE1F9D84A900DFA163 /* AsyncSocket.m in Sources */, 330 | 4AA9F7CB1F9D849E00DFA163 /* main.m in Sources */, 331 | 4AA9F7BD1F9D849E00DFA163 /* AppDelegate.m in Sources */, 332 | 4AA9F7FF1F9D84A900DFA163 /* AsyncUdpSocket.m in Sources */, 333 | ); 334 | runOnlyForDeploymentPostprocessing = 0; 335 | }; 336 | 4AA9F7CC1F9D849F00DFA163 /* Sources */ = { 337 | isa = PBXSourcesBuildPhase; 338 | buildActionMask = 2147483647; 339 | files = ( 340 | 4AA9F7D51F9D849F00DFA163 /* ClientExampleTests.m in Sources */, 341 | ); 342 | runOnlyForDeploymentPostprocessing = 0; 343 | }; 344 | 4AA9F7D71F9D849F00DFA163 /* Sources */ = { 345 | isa = PBXSourcesBuildPhase; 346 | buildActionMask = 2147483647; 347 | files = ( 348 | 4AA9F7E01F9D849F00DFA163 /* ClientExampleUITests.m in Sources */, 349 | ); 350 | runOnlyForDeploymentPostprocessing = 0; 351 | }; 352 | /* End PBXSourcesBuildPhase section */ 353 | 354 | /* Begin PBXTargetDependency section */ 355 | 4AA9F7D21F9D849F00DFA163 /* PBXTargetDependency */ = { 356 | isa = PBXTargetDependency; 357 | target = 4AA9F7B71F9D849E00DFA163 /* ClientExample */; 358 | targetProxy = 4AA9F7D11F9D849F00DFA163 /* PBXContainerItemProxy */; 359 | }; 360 | 4AA9F7DD1F9D849F00DFA163 /* PBXTargetDependency */ = { 361 | isa = PBXTargetDependency; 362 | target = 4AA9F7B71F9D849E00DFA163 /* ClientExample */; 363 | targetProxy = 4AA9F7DC1F9D849F00DFA163 /* PBXContainerItemProxy */; 364 | }; 365 | /* End PBXTargetDependency section */ 366 | 367 | /* Begin PBXVariantGroup section */ 368 | 4AA9F7C11F9D849E00DFA163 /* Main.storyboard */ = { 369 | isa = PBXVariantGroup; 370 | children = ( 371 | 4AA9F7C21F9D849E00DFA163 /* Base */, 372 | ); 373 | name = Main.storyboard; 374 | sourceTree = ""; 375 | }; 376 | 4AA9F7C61F9D849E00DFA163 /* LaunchScreen.storyboard */ = { 377 | isa = PBXVariantGroup; 378 | children = ( 379 | 4AA9F7C71F9D849E00DFA163 /* Base */, 380 | ); 381 | name = LaunchScreen.storyboard; 382 | sourceTree = ""; 383 | }; 384 | /* End PBXVariantGroup section */ 385 | 386 | /* Begin XCBuildConfiguration section */ 387 | 4AA9F7E21F9D849F00DFA163 /* Debug */ = { 388 | isa = XCBuildConfiguration; 389 | buildSettings = { 390 | ALWAYS_SEARCH_USER_PATHS = NO; 391 | CLANG_ANALYZER_NONNULL = YES; 392 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 393 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 394 | CLANG_CXX_LIBRARY = "libc++"; 395 | CLANG_ENABLE_MODULES = YES; 396 | CLANG_ENABLE_OBJC_ARC = YES; 397 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 398 | CLANG_WARN_BOOL_CONVERSION = YES; 399 | CLANG_WARN_COMMA = YES; 400 | CLANG_WARN_CONSTANT_CONVERSION = YES; 401 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 402 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 403 | CLANG_WARN_EMPTY_BODY = YES; 404 | CLANG_WARN_ENUM_CONVERSION = YES; 405 | CLANG_WARN_INFINITE_RECURSION = YES; 406 | CLANG_WARN_INT_CONVERSION = YES; 407 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 408 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 409 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 410 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 411 | CLANG_WARN_STRICT_PROTOTYPES = YES; 412 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 413 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 414 | CLANG_WARN_UNREACHABLE_CODE = YES; 415 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 416 | CODE_SIGN_IDENTITY = "iPhone Developer"; 417 | COPY_PHASE_STRIP = NO; 418 | DEBUG_INFORMATION_FORMAT = dwarf; 419 | ENABLE_STRICT_OBJC_MSGSEND = YES; 420 | ENABLE_TESTABILITY = YES; 421 | GCC_C_LANGUAGE_STANDARD = gnu11; 422 | GCC_DYNAMIC_NO_PIC = NO; 423 | GCC_NO_COMMON_BLOCKS = YES; 424 | GCC_OPTIMIZATION_LEVEL = 0; 425 | GCC_PREPROCESSOR_DEFINITIONS = ( 426 | "DEBUG=1", 427 | "$(inherited)", 428 | ); 429 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 430 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 431 | GCC_WARN_UNDECLARED_SELECTOR = YES; 432 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 433 | GCC_WARN_UNUSED_FUNCTION = YES; 434 | GCC_WARN_UNUSED_VARIABLE = YES; 435 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 436 | MTL_ENABLE_DEBUG_INFO = YES; 437 | ONLY_ACTIVE_ARCH = YES; 438 | SDKROOT = iphoneos; 439 | }; 440 | name = Debug; 441 | }; 442 | 4AA9F7E31F9D849F00DFA163 /* Release */ = { 443 | isa = XCBuildConfiguration; 444 | buildSettings = { 445 | ALWAYS_SEARCH_USER_PATHS = NO; 446 | CLANG_ANALYZER_NONNULL = YES; 447 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 448 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 449 | CLANG_CXX_LIBRARY = "libc++"; 450 | CLANG_ENABLE_MODULES = YES; 451 | CLANG_ENABLE_OBJC_ARC = YES; 452 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 453 | CLANG_WARN_BOOL_CONVERSION = YES; 454 | CLANG_WARN_COMMA = YES; 455 | CLANG_WARN_CONSTANT_CONVERSION = YES; 456 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 457 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 458 | CLANG_WARN_EMPTY_BODY = YES; 459 | CLANG_WARN_ENUM_CONVERSION = YES; 460 | CLANG_WARN_INFINITE_RECURSION = YES; 461 | CLANG_WARN_INT_CONVERSION = YES; 462 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 463 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 464 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 465 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 466 | CLANG_WARN_STRICT_PROTOTYPES = YES; 467 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 468 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 469 | CLANG_WARN_UNREACHABLE_CODE = YES; 470 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 471 | CODE_SIGN_IDENTITY = "iPhone Developer"; 472 | COPY_PHASE_STRIP = NO; 473 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 474 | ENABLE_NS_ASSERTIONS = NO; 475 | ENABLE_STRICT_OBJC_MSGSEND = YES; 476 | GCC_C_LANGUAGE_STANDARD = gnu11; 477 | GCC_NO_COMMON_BLOCKS = YES; 478 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 479 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 480 | GCC_WARN_UNDECLARED_SELECTOR = YES; 481 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 482 | GCC_WARN_UNUSED_FUNCTION = YES; 483 | GCC_WARN_UNUSED_VARIABLE = YES; 484 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 485 | MTL_ENABLE_DEBUG_INFO = NO; 486 | SDKROOT = iphoneos; 487 | VALIDATE_PRODUCT = YES; 488 | }; 489 | name = Release; 490 | }; 491 | 4AA9F7E51F9D849F00DFA163 /* Debug */ = { 492 | isa = XCBuildConfiguration; 493 | buildSettings = { 494 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 495 | CODE_SIGN_STYLE = Automatic; 496 | INFOPLIST_FILE = ClientExample/Info.plist; 497 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 498 | PRODUCT_BUNDLE_IDENTIFIER = com.lc.ClientExample; 499 | PRODUCT_NAME = "$(TARGET_NAME)"; 500 | TARGETED_DEVICE_FAMILY = "1,2"; 501 | }; 502 | name = Debug; 503 | }; 504 | 4AA9F7E61F9D849F00DFA163 /* Release */ = { 505 | isa = XCBuildConfiguration; 506 | buildSettings = { 507 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 508 | CODE_SIGN_STYLE = Automatic; 509 | INFOPLIST_FILE = ClientExample/Info.plist; 510 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 511 | PRODUCT_BUNDLE_IDENTIFIER = com.lc.ClientExample; 512 | PRODUCT_NAME = "$(TARGET_NAME)"; 513 | TARGETED_DEVICE_FAMILY = "1,2"; 514 | }; 515 | name = Release; 516 | }; 517 | 4AA9F7E81F9D849F00DFA163 /* Debug */ = { 518 | isa = XCBuildConfiguration; 519 | buildSettings = { 520 | BUNDLE_LOADER = "$(TEST_HOST)"; 521 | CODE_SIGN_STYLE = Automatic; 522 | INFOPLIST_FILE = ClientExampleTests/Info.plist; 523 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 524 | PRODUCT_BUNDLE_IDENTIFIER = com.lc.ClientExampleTests; 525 | PRODUCT_NAME = "$(TARGET_NAME)"; 526 | TARGETED_DEVICE_FAMILY = "1,2"; 527 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ClientExample.app/ClientExample"; 528 | }; 529 | name = Debug; 530 | }; 531 | 4AA9F7E91F9D849F00DFA163 /* Release */ = { 532 | isa = XCBuildConfiguration; 533 | buildSettings = { 534 | BUNDLE_LOADER = "$(TEST_HOST)"; 535 | CODE_SIGN_STYLE = Automatic; 536 | INFOPLIST_FILE = ClientExampleTests/Info.plist; 537 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 538 | PRODUCT_BUNDLE_IDENTIFIER = com.lc.ClientExampleTests; 539 | PRODUCT_NAME = "$(TARGET_NAME)"; 540 | TARGETED_DEVICE_FAMILY = "1,2"; 541 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ClientExample.app/ClientExample"; 542 | }; 543 | name = Release; 544 | }; 545 | 4AA9F7EB1F9D849F00DFA163 /* Debug */ = { 546 | isa = XCBuildConfiguration; 547 | buildSettings = { 548 | CODE_SIGN_STYLE = Automatic; 549 | INFOPLIST_FILE = ClientExampleUITests/Info.plist; 550 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 551 | PRODUCT_BUNDLE_IDENTIFIER = com.lc.ClientExampleUITests; 552 | PRODUCT_NAME = "$(TARGET_NAME)"; 553 | TARGETED_DEVICE_FAMILY = "1,2"; 554 | TEST_TARGET_NAME = ClientExample; 555 | }; 556 | name = Debug; 557 | }; 558 | 4AA9F7EC1F9D849F00DFA163 /* Release */ = { 559 | isa = XCBuildConfiguration; 560 | buildSettings = { 561 | CODE_SIGN_STYLE = Automatic; 562 | INFOPLIST_FILE = ClientExampleUITests/Info.plist; 563 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 564 | PRODUCT_BUNDLE_IDENTIFIER = com.lc.ClientExampleUITests; 565 | PRODUCT_NAME = "$(TARGET_NAME)"; 566 | TARGETED_DEVICE_FAMILY = "1,2"; 567 | TEST_TARGET_NAME = ClientExample; 568 | }; 569 | name = Release; 570 | }; 571 | /* End XCBuildConfiguration section */ 572 | 573 | /* Begin XCConfigurationList section */ 574 | 4AA9F7B31F9D849E00DFA163 /* Build configuration list for PBXProject "ClientExample" */ = { 575 | isa = XCConfigurationList; 576 | buildConfigurations = ( 577 | 4AA9F7E21F9D849F00DFA163 /* Debug */, 578 | 4AA9F7E31F9D849F00DFA163 /* Release */, 579 | ); 580 | defaultConfigurationIsVisible = 0; 581 | defaultConfigurationName = Release; 582 | }; 583 | 4AA9F7E41F9D849F00DFA163 /* Build configuration list for PBXNativeTarget "ClientExample" */ = { 584 | isa = XCConfigurationList; 585 | buildConfigurations = ( 586 | 4AA9F7E51F9D849F00DFA163 /* Debug */, 587 | 4AA9F7E61F9D849F00DFA163 /* Release */, 588 | ); 589 | defaultConfigurationIsVisible = 0; 590 | defaultConfigurationName = Release; 591 | }; 592 | 4AA9F7E71F9D849F00DFA163 /* Build configuration list for PBXNativeTarget "ClientExampleTests" */ = { 593 | isa = XCConfigurationList; 594 | buildConfigurations = ( 595 | 4AA9F7E81F9D849F00DFA163 /* Debug */, 596 | 4AA9F7E91F9D849F00DFA163 /* Release */, 597 | ); 598 | defaultConfigurationIsVisible = 0; 599 | defaultConfigurationName = Release; 600 | }; 601 | 4AA9F7EA1F9D849F00DFA163 /* Build configuration list for PBXNativeTarget "ClientExampleUITests" */ = { 602 | isa = XCConfigurationList; 603 | buildConfigurations = ( 604 | 4AA9F7EB1F9D849F00DFA163 /* Debug */, 605 | 4AA9F7EC1F9D849F00DFA163 /* Release */, 606 | ); 607 | defaultConfigurationIsVisible = 0; 608 | defaultConfigurationName = Release; 609 | }; 610 | /* End XCConfigurationList section */ 611 | }; 612 | rootObject = 4AA9F7B01F9D849E00DFA163 /* Project object */; 613 | } 614 | -------------------------------------------------------------------------------- /ServerExample/ServerExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4AA9F69C1F9D7CD200DFA163 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F69B1F9D7CD200DFA163 /* AppDelegate.m */; }; 11 | 4AA9F69F1F9D7CD200DFA163 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F69E1F9D7CD200DFA163 /* ViewController.m */; }; 12 | 4AA9F6A21F9D7CD200DFA163 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4AA9F6A01F9D7CD200DFA163 /* Main.storyboard */; }; 13 | 4AA9F6A41F9D7CD200DFA163 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4AA9F6A31F9D7CD200DFA163 /* Assets.xcassets */; }; 14 | 4AA9F6A71F9D7CD200DFA163 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4AA9F6A51F9D7CD200DFA163 /* LaunchScreen.storyboard */; }; 15 | 4AA9F6AA1F9D7CD200DFA163 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F6A91F9D7CD200DFA163 /* main.m */; }; 16 | 4AA9F6B41F9D7CD200DFA163 /* ServerExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F6B31F9D7CD200DFA163 /* ServerExampleTests.m */; }; 17 | 4AA9F6BF1F9D7CD200DFA163 /* ServerExampleUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F6BE1F9D7CD200DFA163 /* ServerExampleUITests.m */; }; 18 | 4AA9F7AA1F9D845D00DFA163 /* README.markdown in Resources */ = {isa = PBXBuildFile; fileRef = 4AA9F79D1F9D845D00DFA163 /* README.markdown */; }; 19 | 4AA9F7AB1F9D845D00DFA163 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F7A21F9D845D00DFA163 /* GCDAsyncSocket.m */; }; 20 | 4AA9F7AC1F9D845D00DFA163 /* GCDAsyncUdpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F7A41F9D845D00DFA163 /* GCDAsyncUdpSocket.m */; }; 21 | 4AA9F7AD1F9D845D00DFA163 /* AsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F7A71F9D845D00DFA163 /* AsyncSocket.m */; }; 22 | 4AA9F7AE1F9D845D00DFA163 /* AsyncUdpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AA9F7A91F9D845D00DFA163 /* AsyncUdpSocket.m */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXContainerItemProxy section */ 26 | 4AA9F6B01F9D7CD200DFA163 /* PBXContainerItemProxy */ = { 27 | isa = PBXContainerItemProxy; 28 | containerPortal = 4AA9F68F1F9D7CD200DFA163 /* Project object */; 29 | proxyType = 1; 30 | remoteGlobalIDString = 4AA9F6961F9D7CD200DFA163; 31 | remoteInfo = ServerExample; 32 | }; 33 | 4AA9F6BB1F9D7CD200DFA163 /* PBXContainerItemProxy */ = { 34 | isa = PBXContainerItemProxy; 35 | containerPortal = 4AA9F68F1F9D7CD200DFA163 /* Project object */; 36 | proxyType = 1; 37 | remoteGlobalIDString = 4AA9F6961F9D7CD200DFA163; 38 | remoteInfo = ServerExample; 39 | }; 40 | /* End PBXContainerItemProxy section */ 41 | 42 | /* Begin PBXFileReference section */ 43 | 4AA9F6971F9D7CD200DFA163 /* ServerExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ServerExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 4AA9F69A1F9D7CD200DFA163 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 45 | 4AA9F69B1F9D7CD200DFA163 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 46 | 4AA9F69D1F9D7CD200DFA163 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 47 | 4AA9F69E1F9D7CD200DFA163 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 48 | 4AA9F6A11F9D7CD200DFA163 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 49 | 4AA9F6A31F9D7CD200DFA163 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 50 | 4AA9F6A61F9D7CD200DFA163 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 51 | 4AA9F6A81F9D7CD200DFA163 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | 4AA9F6A91F9D7CD200DFA163 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 53 | 4AA9F6AF1F9D7CD200DFA163 /* ServerExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ServerExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 4AA9F6B31F9D7CD200DFA163 /* ServerExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ServerExampleTests.m; sourceTree = ""; }; 55 | 4AA9F6B51F9D7CD200DFA163 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 4AA9F6BA1F9D7CD200DFA163 /* ServerExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ServerExampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 4AA9F6BE1F9D7CD200DFA163 /* ServerExampleUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ServerExampleUITests.m; sourceTree = ""; }; 58 | 4AA9F6C01F9D7CD200DFA163 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 59 | 4AA9F79D1F9D845D00DFA163 /* README.markdown */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.markdown; sourceTree = ""; }; 60 | 4AA9F79F1F9D845D00DFA163 /* CocoaAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CocoaAsyncSocket.h; sourceTree = ""; }; 61 | 4AA9F7A11F9D845D00DFA163 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncSocket.h; sourceTree = ""; }; 62 | 4AA9F7A21F9D845D00DFA163 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncSocket.m; sourceTree = ""; }; 63 | 4AA9F7A31F9D845D00DFA163 /* GCDAsyncUdpSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncUdpSocket.h; sourceTree = ""; }; 64 | 4AA9F7A41F9D845D00DFA163 /* GCDAsyncUdpSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncUdpSocket.m; sourceTree = ""; }; 65 | 4AA9F7A61F9D845D00DFA163 /* AsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncSocket.h; sourceTree = ""; }; 66 | 4AA9F7A71F9D845D00DFA163 /* AsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AsyncSocket.m; sourceTree = ""; }; 67 | 4AA9F7A81F9D845D00DFA163 /* AsyncUdpSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncUdpSocket.h; sourceTree = ""; }; 68 | 4AA9F7A91F9D845D00DFA163 /* AsyncUdpSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AsyncUdpSocket.m; sourceTree = ""; }; 69 | /* End PBXFileReference section */ 70 | 71 | /* Begin PBXFrameworksBuildPhase section */ 72 | 4AA9F6941F9D7CD200DFA163 /* Frameworks */ = { 73 | isa = PBXFrameworksBuildPhase; 74 | buildActionMask = 2147483647; 75 | files = ( 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | 4AA9F6AC1F9D7CD200DFA163 /* Frameworks */ = { 80 | isa = PBXFrameworksBuildPhase; 81 | buildActionMask = 2147483647; 82 | files = ( 83 | ); 84 | runOnlyForDeploymentPostprocessing = 0; 85 | }; 86 | 4AA9F6B71F9D7CD200DFA163 /* Frameworks */ = { 87 | isa = PBXFrameworksBuildPhase; 88 | buildActionMask = 2147483647; 89 | files = ( 90 | ); 91 | runOnlyForDeploymentPostprocessing = 0; 92 | }; 93 | /* End PBXFrameworksBuildPhase section */ 94 | 95 | /* Begin PBXGroup section */ 96 | 4AA9F68E1F9D7CD200DFA163 = { 97 | isa = PBXGroup; 98 | children = ( 99 | 4AA9F79C1F9D845D00DFA163 /* CocoaAsyncSocket */, 100 | 4AA9F6991F9D7CD200DFA163 /* ServerExample */, 101 | 4AA9F6B21F9D7CD200DFA163 /* ServerExampleTests */, 102 | 4AA9F6BD1F9D7CD200DFA163 /* ServerExampleUITests */, 103 | 4AA9F6981F9D7CD200DFA163 /* Products */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | 4AA9F6981F9D7CD200DFA163 /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 4AA9F6971F9D7CD200DFA163 /* ServerExample.app */, 111 | 4AA9F6AF1F9D7CD200DFA163 /* ServerExampleTests.xctest */, 112 | 4AA9F6BA1F9D7CD200DFA163 /* ServerExampleUITests.xctest */, 113 | ); 114 | name = Products; 115 | sourceTree = ""; 116 | }; 117 | 4AA9F6991F9D7CD200DFA163 /* ServerExample */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 4AA9F69A1F9D7CD200DFA163 /* AppDelegate.h */, 121 | 4AA9F69B1F9D7CD200DFA163 /* AppDelegate.m */, 122 | 4AA9F69D1F9D7CD200DFA163 /* ViewController.h */, 123 | 4AA9F69E1F9D7CD200DFA163 /* ViewController.m */, 124 | 4AA9F6A01F9D7CD200DFA163 /* Main.storyboard */, 125 | 4AA9F6A31F9D7CD200DFA163 /* Assets.xcassets */, 126 | 4AA9F6A51F9D7CD200DFA163 /* LaunchScreen.storyboard */, 127 | 4AA9F6A81F9D7CD200DFA163 /* Info.plist */, 128 | 4AA9F6A91F9D7CD200DFA163 /* main.m */, 129 | ); 130 | path = ServerExample; 131 | sourceTree = ""; 132 | }; 133 | 4AA9F6B21F9D7CD200DFA163 /* ServerExampleTests */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 4AA9F6B31F9D7CD200DFA163 /* ServerExampleTests.m */, 137 | 4AA9F6B51F9D7CD200DFA163 /* Info.plist */, 138 | ); 139 | path = ServerExampleTests; 140 | sourceTree = ""; 141 | }; 142 | 4AA9F6BD1F9D7CD200DFA163 /* ServerExampleUITests */ = { 143 | isa = PBXGroup; 144 | children = ( 145 | 4AA9F6BE1F9D7CD200DFA163 /* ServerExampleUITests.m */, 146 | 4AA9F6C01F9D7CD200DFA163 /* Info.plist */, 147 | ); 148 | path = ServerExampleUITests; 149 | sourceTree = ""; 150 | }; 151 | 4AA9F79C1F9D845D00DFA163 /* CocoaAsyncSocket */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | 4AA9F79D1F9D845D00DFA163 /* README.markdown */, 155 | 4AA9F79E1F9D845D00DFA163 /* Source */, 156 | ); 157 | path = CocoaAsyncSocket; 158 | sourceTree = ""; 159 | }; 160 | 4AA9F79E1F9D845D00DFA163 /* Source */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | 4AA9F79F1F9D845D00DFA163 /* CocoaAsyncSocket.h */, 164 | 4AA9F7A01F9D845D00DFA163 /* GCD */, 165 | 4AA9F7A51F9D845D00DFA163 /* RunLoop */, 166 | ); 167 | path = Source; 168 | sourceTree = ""; 169 | }; 170 | 4AA9F7A01F9D845D00DFA163 /* GCD */ = { 171 | isa = PBXGroup; 172 | children = ( 173 | 4AA9F7A11F9D845D00DFA163 /* GCDAsyncSocket.h */, 174 | 4AA9F7A21F9D845D00DFA163 /* GCDAsyncSocket.m */, 175 | 4AA9F7A31F9D845D00DFA163 /* GCDAsyncUdpSocket.h */, 176 | 4AA9F7A41F9D845D00DFA163 /* GCDAsyncUdpSocket.m */, 177 | ); 178 | path = GCD; 179 | sourceTree = ""; 180 | }; 181 | 4AA9F7A51F9D845D00DFA163 /* RunLoop */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 4AA9F7A61F9D845D00DFA163 /* AsyncSocket.h */, 185 | 4AA9F7A71F9D845D00DFA163 /* AsyncSocket.m */, 186 | 4AA9F7A81F9D845D00DFA163 /* AsyncUdpSocket.h */, 187 | 4AA9F7A91F9D845D00DFA163 /* AsyncUdpSocket.m */, 188 | ); 189 | path = RunLoop; 190 | sourceTree = ""; 191 | }; 192 | /* End PBXGroup section */ 193 | 194 | /* Begin PBXNativeTarget section */ 195 | 4AA9F6961F9D7CD200DFA163 /* ServerExample */ = { 196 | isa = PBXNativeTarget; 197 | buildConfigurationList = 4AA9F6C31F9D7CD200DFA163 /* Build configuration list for PBXNativeTarget "ServerExample" */; 198 | buildPhases = ( 199 | 4AA9F6931F9D7CD200DFA163 /* Sources */, 200 | 4AA9F6941F9D7CD200DFA163 /* Frameworks */, 201 | 4AA9F6951F9D7CD200DFA163 /* Resources */, 202 | ); 203 | buildRules = ( 204 | ); 205 | dependencies = ( 206 | ); 207 | name = ServerExample; 208 | productName = ServerExample; 209 | productReference = 4AA9F6971F9D7CD200DFA163 /* ServerExample.app */; 210 | productType = "com.apple.product-type.application"; 211 | }; 212 | 4AA9F6AE1F9D7CD200DFA163 /* ServerExampleTests */ = { 213 | isa = PBXNativeTarget; 214 | buildConfigurationList = 4AA9F6C61F9D7CD200DFA163 /* Build configuration list for PBXNativeTarget "ServerExampleTests" */; 215 | buildPhases = ( 216 | 4AA9F6AB1F9D7CD200DFA163 /* Sources */, 217 | 4AA9F6AC1F9D7CD200DFA163 /* Frameworks */, 218 | 4AA9F6AD1F9D7CD200DFA163 /* Resources */, 219 | ); 220 | buildRules = ( 221 | ); 222 | dependencies = ( 223 | 4AA9F6B11F9D7CD200DFA163 /* PBXTargetDependency */, 224 | ); 225 | name = ServerExampleTests; 226 | productName = ServerExampleTests; 227 | productReference = 4AA9F6AF1F9D7CD200DFA163 /* ServerExampleTests.xctest */; 228 | productType = "com.apple.product-type.bundle.unit-test"; 229 | }; 230 | 4AA9F6B91F9D7CD200DFA163 /* ServerExampleUITests */ = { 231 | isa = PBXNativeTarget; 232 | buildConfigurationList = 4AA9F6C91F9D7CD200DFA163 /* Build configuration list for PBXNativeTarget "ServerExampleUITests" */; 233 | buildPhases = ( 234 | 4AA9F6B61F9D7CD200DFA163 /* Sources */, 235 | 4AA9F6B71F9D7CD200DFA163 /* Frameworks */, 236 | 4AA9F6B81F9D7CD200DFA163 /* Resources */, 237 | ); 238 | buildRules = ( 239 | ); 240 | dependencies = ( 241 | 4AA9F6BC1F9D7CD200DFA163 /* PBXTargetDependency */, 242 | ); 243 | name = ServerExampleUITests; 244 | productName = ServerExampleUITests; 245 | productReference = 4AA9F6BA1F9D7CD200DFA163 /* ServerExampleUITests.xctest */; 246 | productType = "com.apple.product-type.bundle.ui-testing"; 247 | }; 248 | /* End PBXNativeTarget section */ 249 | 250 | /* Begin PBXProject section */ 251 | 4AA9F68F1F9D7CD200DFA163 /* Project object */ = { 252 | isa = PBXProject; 253 | attributes = { 254 | LastUpgradeCheck = 0900; 255 | ORGANIZATIONNAME = "http://www.cnblogs.com/saytome/"; 256 | TargetAttributes = { 257 | 4AA9F6961F9D7CD200DFA163 = { 258 | CreatedOnToolsVersion = 9.0; 259 | ProvisioningStyle = Automatic; 260 | }; 261 | 4AA9F6AE1F9D7CD200DFA163 = { 262 | CreatedOnToolsVersion = 9.0; 263 | ProvisioningStyle = Automatic; 264 | TestTargetID = 4AA9F6961F9D7CD200DFA163; 265 | }; 266 | 4AA9F6B91F9D7CD200DFA163 = { 267 | CreatedOnToolsVersion = 9.0; 268 | ProvisioningStyle = Automatic; 269 | TestTargetID = 4AA9F6961F9D7CD200DFA163; 270 | }; 271 | }; 272 | }; 273 | buildConfigurationList = 4AA9F6921F9D7CD200DFA163 /* Build configuration list for PBXProject "ServerExample" */; 274 | compatibilityVersion = "Xcode 8.0"; 275 | developmentRegion = en; 276 | hasScannedForEncodings = 0; 277 | knownRegions = ( 278 | en, 279 | Base, 280 | ); 281 | mainGroup = 4AA9F68E1F9D7CD200DFA163; 282 | productRefGroup = 4AA9F6981F9D7CD200DFA163 /* Products */; 283 | projectDirPath = ""; 284 | projectRoot = ""; 285 | targets = ( 286 | 4AA9F6961F9D7CD200DFA163 /* ServerExample */, 287 | 4AA9F6AE1F9D7CD200DFA163 /* ServerExampleTests */, 288 | 4AA9F6B91F9D7CD200DFA163 /* ServerExampleUITests */, 289 | ); 290 | }; 291 | /* End PBXProject section */ 292 | 293 | /* Begin PBXResourcesBuildPhase section */ 294 | 4AA9F6951F9D7CD200DFA163 /* Resources */ = { 295 | isa = PBXResourcesBuildPhase; 296 | buildActionMask = 2147483647; 297 | files = ( 298 | 4AA9F6A71F9D7CD200DFA163 /* LaunchScreen.storyboard in Resources */, 299 | 4AA9F6A41F9D7CD200DFA163 /* Assets.xcassets in Resources */, 300 | 4AA9F7AA1F9D845D00DFA163 /* README.markdown in Resources */, 301 | 4AA9F6A21F9D7CD200DFA163 /* Main.storyboard in Resources */, 302 | ); 303 | runOnlyForDeploymentPostprocessing = 0; 304 | }; 305 | 4AA9F6AD1F9D7CD200DFA163 /* Resources */ = { 306 | isa = PBXResourcesBuildPhase; 307 | buildActionMask = 2147483647; 308 | files = ( 309 | ); 310 | runOnlyForDeploymentPostprocessing = 0; 311 | }; 312 | 4AA9F6B81F9D7CD200DFA163 /* Resources */ = { 313 | isa = PBXResourcesBuildPhase; 314 | buildActionMask = 2147483647; 315 | files = ( 316 | ); 317 | runOnlyForDeploymentPostprocessing = 0; 318 | }; 319 | /* End PBXResourcesBuildPhase section */ 320 | 321 | /* Begin PBXSourcesBuildPhase section */ 322 | 4AA9F6931F9D7CD200DFA163 /* Sources */ = { 323 | isa = PBXSourcesBuildPhase; 324 | buildActionMask = 2147483647; 325 | files = ( 326 | 4AA9F7AB1F9D845D00DFA163 /* GCDAsyncSocket.m in Sources */, 327 | 4AA9F7AC1F9D845D00DFA163 /* GCDAsyncUdpSocket.m in Sources */, 328 | 4AA9F69F1F9D7CD200DFA163 /* ViewController.m in Sources */, 329 | 4AA9F7AD1F9D845D00DFA163 /* AsyncSocket.m in Sources */, 330 | 4AA9F6AA1F9D7CD200DFA163 /* main.m in Sources */, 331 | 4AA9F69C1F9D7CD200DFA163 /* AppDelegate.m in Sources */, 332 | 4AA9F7AE1F9D845D00DFA163 /* AsyncUdpSocket.m in Sources */, 333 | ); 334 | runOnlyForDeploymentPostprocessing = 0; 335 | }; 336 | 4AA9F6AB1F9D7CD200DFA163 /* Sources */ = { 337 | isa = PBXSourcesBuildPhase; 338 | buildActionMask = 2147483647; 339 | files = ( 340 | 4AA9F6B41F9D7CD200DFA163 /* ServerExampleTests.m in Sources */, 341 | ); 342 | runOnlyForDeploymentPostprocessing = 0; 343 | }; 344 | 4AA9F6B61F9D7CD200DFA163 /* Sources */ = { 345 | isa = PBXSourcesBuildPhase; 346 | buildActionMask = 2147483647; 347 | files = ( 348 | 4AA9F6BF1F9D7CD200DFA163 /* ServerExampleUITests.m in Sources */, 349 | ); 350 | runOnlyForDeploymentPostprocessing = 0; 351 | }; 352 | /* End PBXSourcesBuildPhase section */ 353 | 354 | /* Begin PBXTargetDependency section */ 355 | 4AA9F6B11F9D7CD200DFA163 /* PBXTargetDependency */ = { 356 | isa = PBXTargetDependency; 357 | target = 4AA9F6961F9D7CD200DFA163 /* ServerExample */; 358 | targetProxy = 4AA9F6B01F9D7CD200DFA163 /* PBXContainerItemProxy */; 359 | }; 360 | 4AA9F6BC1F9D7CD200DFA163 /* PBXTargetDependency */ = { 361 | isa = PBXTargetDependency; 362 | target = 4AA9F6961F9D7CD200DFA163 /* ServerExample */; 363 | targetProxy = 4AA9F6BB1F9D7CD200DFA163 /* PBXContainerItemProxy */; 364 | }; 365 | /* End PBXTargetDependency section */ 366 | 367 | /* Begin PBXVariantGroup section */ 368 | 4AA9F6A01F9D7CD200DFA163 /* Main.storyboard */ = { 369 | isa = PBXVariantGroup; 370 | children = ( 371 | 4AA9F6A11F9D7CD200DFA163 /* Base */, 372 | ); 373 | name = Main.storyboard; 374 | sourceTree = ""; 375 | }; 376 | 4AA9F6A51F9D7CD200DFA163 /* LaunchScreen.storyboard */ = { 377 | isa = PBXVariantGroup; 378 | children = ( 379 | 4AA9F6A61F9D7CD200DFA163 /* Base */, 380 | ); 381 | name = LaunchScreen.storyboard; 382 | sourceTree = ""; 383 | }; 384 | /* End PBXVariantGroup section */ 385 | 386 | /* Begin XCBuildConfiguration section */ 387 | 4AA9F6C11F9D7CD200DFA163 /* Debug */ = { 388 | isa = XCBuildConfiguration; 389 | buildSettings = { 390 | ALWAYS_SEARCH_USER_PATHS = NO; 391 | CLANG_ANALYZER_NONNULL = YES; 392 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 393 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 394 | CLANG_CXX_LIBRARY = "libc++"; 395 | CLANG_ENABLE_MODULES = YES; 396 | CLANG_ENABLE_OBJC_ARC = YES; 397 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 398 | CLANG_WARN_BOOL_CONVERSION = YES; 399 | CLANG_WARN_COMMA = YES; 400 | CLANG_WARN_CONSTANT_CONVERSION = YES; 401 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 402 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 403 | CLANG_WARN_EMPTY_BODY = YES; 404 | CLANG_WARN_ENUM_CONVERSION = YES; 405 | CLANG_WARN_INFINITE_RECURSION = YES; 406 | CLANG_WARN_INT_CONVERSION = YES; 407 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 408 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 409 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 410 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 411 | CLANG_WARN_STRICT_PROTOTYPES = YES; 412 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 413 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 414 | CLANG_WARN_UNREACHABLE_CODE = YES; 415 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 416 | CODE_SIGN_IDENTITY = "iPhone Developer"; 417 | COPY_PHASE_STRIP = NO; 418 | DEBUG_INFORMATION_FORMAT = dwarf; 419 | ENABLE_STRICT_OBJC_MSGSEND = YES; 420 | ENABLE_TESTABILITY = YES; 421 | GCC_C_LANGUAGE_STANDARD = gnu11; 422 | GCC_DYNAMIC_NO_PIC = NO; 423 | GCC_NO_COMMON_BLOCKS = YES; 424 | GCC_OPTIMIZATION_LEVEL = 0; 425 | GCC_PREPROCESSOR_DEFINITIONS = ( 426 | "DEBUG=1", 427 | "$(inherited)", 428 | ); 429 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 430 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 431 | GCC_WARN_UNDECLARED_SELECTOR = YES; 432 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 433 | GCC_WARN_UNUSED_FUNCTION = YES; 434 | GCC_WARN_UNUSED_VARIABLE = YES; 435 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 436 | MTL_ENABLE_DEBUG_INFO = YES; 437 | ONLY_ACTIVE_ARCH = YES; 438 | SDKROOT = iphoneos; 439 | }; 440 | name = Debug; 441 | }; 442 | 4AA9F6C21F9D7CD200DFA163 /* Release */ = { 443 | isa = XCBuildConfiguration; 444 | buildSettings = { 445 | ALWAYS_SEARCH_USER_PATHS = NO; 446 | CLANG_ANALYZER_NONNULL = YES; 447 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 448 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 449 | CLANG_CXX_LIBRARY = "libc++"; 450 | CLANG_ENABLE_MODULES = YES; 451 | CLANG_ENABLE_OBJC_ARC = YES; 452 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 453 | CLANG_WARN_BOOL_CONVERSION = YES; 454 | CLANG_WARN_COMMA = YES; 455 | CLANG_WARN_CONSTANT_CONVERSION = YES; 456 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 457 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 458 | CLANG_WARN_EMPTY_BODY = YES; 459 | CLANG_WARN_ENUM_CONVERSION = YES; 460 | CLANG_WARN_INFINITE_RECURSION = YES; 461 | CLANG_WARN_INT_CONVERSION = YES; 462 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 463 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 464 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 465 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 466 | CLANG_WARN_STRICT_PROTOTYPES = YES; 467 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 468 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 469 | CLANG_WARN_UNREACHABLE_CODE = YES; 470 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 471 | CODE_SIGN_IDENTITY = "iPhone Developer"; 472 | COPY_PHASE_STRIP = NO; 473 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 474 | ENABLE_NS_ASSERTIONS = NO; 475 | ENABLE_STRICT_OBJC_MSGSEND = YES; 476 | GCC_C_LANGUAGE_STANDARD = gnu11; 477 | GCC_NO_COMMON_BLOCKS = YES; 478 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 479 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 480 | GCC_WARN_UNDECLARED_SELECTOR = YES; 481 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 482 | GCC_WARN_UNUSED_FUNCTION = YES; 483 | GCC_WARN_UNUSED_VARIABLE = YES; 484 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 485 | MTL_ENABLE_DEBUG_INFO = NO; 486 | SDKROOT = iphoneos; 487 | VALIDATE_PRODUCT = YES; 488 | }; 489 | name = Release; 490 | }; 491 | 4AA9F6C41F9D7CD200DFA163 /* Debug */ = { 492 | isa = XCBuildConfiguration; 493 | buildSettings = { 494 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 495 | CODE_SIGN_STYLE = Automatic; 496 | DEVELOPMENT_TEAM = VK9XVA25GP; 497 | INFOPLIST_FILE = ServerExample/Info.plist; 498 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 499 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 500 | PRODUCT_BUNDLE_IDENTIFIER = com.lc.ServerExample; 501 | PRODUCT_NAME = "$(TARGET_NAME)"; 502 | TARGETED_DEVICE_FAMILY = "1,2"; 503 | }; 504 | name = Debug; 505 | }; 506 | 4AA9F6C51F9D7CD200DFA163 /* Release */ = { 507 | isa = XCBuildConfiguration; 508 | buildSettings = { 509 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 510 | CODE_SIGN_STYLE = Automatic; 511 | DEVELOPMENT_TEAM = VK9XVA25GP; 512 | INFOPLIST_FILE = ServerExample/Info.plist; 513 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 514 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 515 | PRODUCT_BUNDLE_IDENTIFIER = com.lc.ServerExample; 516 | PRODUCT_NAME = "$(TARGET_NAME)"; 517 | TARGETED_DEVICE_FAMILY = "1,2"; 518 | }; 519 | name = Release; 520 | }; 521 | 4AA9F6C71F9D7CD200DFA163 /* Debug */ = { 522 | isa = XCBuildConfiguration; 523 | buildSettings = { 524 | BUNDLE_LOADER = "$(TEST_HOST)"; 525 | CODE_SIGN_STYLE = Automatic; 526 | INFOPLIST_FILE = ServerExampleTests/Info.plist; 527 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 528 | PRODUCT_BUNDLE_IDENTIFIER = com.lc.ServerExampleTests; 529 | PRODUCT_NAME = "$(TARGET_NAME)"; 530 | TARGETED_DEVICE_FAMILY = "1,2"; 531 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ServerExample.app/ServerExample"; 532 | }; 533 | name = Debug; 534 | }; 535 | 4AA9F6C81F9D7CD200DFA163 /* Release */ = { 536 | isa = XCBuildConfiguration; 537 | buildSettings = { 538 | BUNDLE_LOADER = "$(TEST_HOST)"; 539 | CODE_SIGN_STYLE = Automatic; 540 | INFOPLIST_FILE = ServerExampleTests/Info.plist; 541 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 542 | PRODUCT_BUNDLE_IDENTIFIER = com.lc.ServerExampleTests; 543 | PRODUCT_NAME = "$(TARGET_NAME)"; 544 | TARGETED_DEVICE_FAMILY = "1,2"; 545 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ServerExample.app/ServerExample"; 546 | }; 547 | name = Release; 548 | }; 549 | 4AA9F6CA1F9D7CD200DFA163 /* Debug */ = { 550 | isa = XCBuildConfiguration; 551 | buildSettings = { 552 | CODE_SIGN_STYLE = Automatic; 553 | INFOPLIST_FILE = ServerExampleUITests/Info.plist; 554 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 555 | PRODUCT_BUNDLE_IDENTIFIER = com.lc.ServerExampleUITests; 556 | PRODUCT_NAME = "$(TARGET_NAME)"; 557 | TARGETED_DEVICE_FAMILY = "1,2"; 558 | TEST_TARGET_NAME = ServerExample; 559 | }; 560 | name = Debug; 561 | }; 562 | 4AA9F6CB1F9D7CD200DFA163 /* Release */ = { 563 | isa = XCBuildConfiguration; 564 | buildSettings = { 565 | CODE_SIGN_STYLE = Automatic; 566 | INFOPLIST_FILE = ServerExampleUITests/Info.plist; 567 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 568 | PRODUCT_BUNDLE_IDENTIFIER = com.lc.ServerExampleUITests; 569 | PRODUCT_NAME = "$(TARGET_NAME)"; 570 | TARGETED_DEVICE_FAMILY = "1,2"; 571 | TEST_TARGET_NAME = ServerExample; 572 | }; 573 | name = Release; 574 | }; 575 | /* End XCBuildConfiguration section */ 576 | 577 | /* Begin XCConfigurationList section */ 578 | 4AA9F6921F9D7CD200DFA163 /* Build configuration list for PBXProject "ServerExample" */ = { 579 | isa = XCConfigurationList; 580 | buildConfigurations = ( 581 | 4AA9F6C11F9D7CD200DFA163 /* Debug */, 582 | 4AA9F6C21F9D7CD200DFA163 /* Release */, 583 | ); 584 | defaultConfigurationIsVisible = 0; 585 | defaultConfigurationName = Release; 586 | }; 587 | 4AA9F6C31F9D7CD200DFA163 /* Build configuration list for PBXNativeTarget "ServerExample" */ = { 588 | isa = XCConfigurationList; 589 | buildConfigurations = ( 590 | 4AA9F6C41F9D7CD200DFA163 /* Debug */, 591 | 4AA9F6C51F9D7CD200DFA163 /* Release */, 592 | ); 593 | defaultConfigurationIsVisible = 0; 594 | defaultConfigurationName = Release; 595 | }; 596 | 4AA9F6C61F9D7CD200DFA163 /* Build configuration list for PBXNativeTarget "ServerExampleTests" */ = { 597 | isa = XCConfigurationList; 598 | buildConfigurations = ( 599 | 4AA9F6C71F9D7CD200DFA163 /* Debug */, 600 | 4AA9F6C81F9D7CD200DFA163 /* Release */, 601 | ); 602 | defaultConfigurationIsVisible = 0; 603 | defaultConfigurationName = Release; 604 | }; 605 | 4AA9F6C91F9D7CD200DFA163 /* Build configuration list for PBXNativeTarget "ServerExampleUITests" */ = { 606 | isa = XCConfigurationList; 607 | buildConfigurations = ( 608 | 4AA9F6CA1F9D7CD200DFA163 /* Debug */, 609 | 4AA9F6CB1F9D7CD200DFA163 /* Release */, 610 | ); 611 | defaultConfigurationIsVisible = 0; 612 | defaultConfigurationName = Release; 613 | }; 614 | /* End XCConfigurationList section */ 615 | }; 616 | rootObject = 4AA9F68F1F9D7CD200DFA163 /* Project object */; 617 | } 618 | -------------------------------------------------------------------------------- /ClientExample/CocoaAsyncSocket/Source/RunLoop/AsyncSocket.h: -------------------------------------------------------------------------------- 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 | 11 | #import 12 | 13 | @class AsyncSocket; 14 | @class AsyncReadPacket; 15 | @class AsyncWritePacket; 16 | 17 | extern NSString *const AsyncSocketException; 18 | extern NSString *const AsyncSocketErrorDomain; 19 | 20 | typedef NS_ENUM(NSInteger, AsyncSocketError) { 21 | AsyncSocketCFSocketError = kCFSocketError, // From CFSocketError enum. 22 | AsyncSocketNoError = 0, // Never used. 23 | AsyncSocketCanceledError, // onSocketWillConnect: returned NO. 24 | AsyncSocketConnectTimeoutError, 25 | AsyncSocketReadMaxedOutError, // Reached set maxLength without completing 26 | AsyncSocketReadTimeoutError, 27 | AsyncSocketWriteTimeoutError 28 | }; 29 | 30 | @protocol AsyncSocketDelegate 31 | @optional 32 | 33 | /** 34 | * In the event of an error, the socket is closed. 35 | * You may call "unreadData" during this call-back to get the last bit of data off the socket. 36 | * When connecting, this delegate method may be called 37 | * before"onSocket:didAcceptNewSocket:" or "onSocket:didConnectToHost:". 38 | **/ 39 | - (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err; 40 | 41 | /** 42 | * Called when a socket disconnects with or without error. If you want to release a socket after it disconnects, 43 | * do so here. It is not safe to do that during "onSocket:willDisconnectWithError:". 44 | * 45 | * If you call the disconnect method, and the socket wasn't already disconnected, 46 | * this delegate method will be called before the disconnect method returns. 47 | **/ 48 | - (void)onSocketDidDisconnect:(AsyncSocket *)sock; 49 | 50 | /** 51 | * Called when a socket accepts a connection. Another socket is spawned to handle it. The new socket will have 52 | * the same delegate and will call "onSocket:didConnectToHost:port:". 53 | **/ 54 | - (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket; 55 | 56 | /** 57 | * Called when a new socket is spawned to handle a connection. This method should return the run-loop of the 58 | * thread on which the new socket and its delegate should operate. If omitted, [NSRunLoop currentRunLoop] is used. 59 | **/ 60 | - (NSRunLoop *)onSocket:(AsyncSocket *)sock wantsRunLoopForNewSocket:(AsyncSocket *)newSocket; 61 | 62 | /** 63 | * Called when a socket is about to connect. This method should return YES to continue, or NO to abort. 64 | * If aborted, will result in AsyncSocketCanceledError. 65 | * 66 | * If the connectToHost:onPort:error: method was called, the delegate will be able to access and configure the 67 | * CFReadStream and CFWriteStream as desired prior to connection. 68 | * 69 | * If the connectToAddress:error: method was called, the delegate will be able to access and configure the 70 | * CFSocket and CFSocketNativeHandle (BSD socket) as desired prior to connection. You will be able to access and 71 | * configure the CFReadStream and CFWriteStream in the onSocket:didConnectToHost:port: method. 72 | **/ 73 | - (BOOL)onSocketWillConnect:(AsyncSocket *)sock; 74 | 75 | /** 76 | * Called when a socket connects and is ready for reading and writing. 77 | * The host parameter will be an IP address, not a DNS name. 78 | **/ 79 | - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port; 80 | 81 | /** 82 | * Called when a socket has completed reading the requested data into memory. 83 | * Not called if there is an error. 84 | **/ 85 | - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag; 86 | 87 | /** 88 | * Called when a socket has read in data, but has not yet completed the read. 89 | * This would occur if using readToData: or readToLength: methods. 90 | * It may be used to for things such as updating progress bars. 91 | **/ 92 | - (void)onSocket:(AsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; 93 | 94 | /** 95 | * Called when a socket has completed writing the requested data. Not called if there is an error. 96 | **/ 97 | - (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag; 98 | 99 | /** 100 | * Called when a socket has written some data, but has not yet completed the entire write. 101 | * It may be used to for things such as updating progress bars. 102 | **/ 103 | - (void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; 104 | 105 | /** 106 | * Called if a read operation has reached its timeout without completing. 107 | * This method allows you to optionally extend the timeout. 108 | * If you return a positive time interval (> 0) the read's timeout will be extended by the given amount. 109 | * If you don't implement this method, or return a non-positive time interval (<= 0) the read will timeout as usual. 110 | * 111 | * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method. 112 | * The length parameter is the number of bytes that have been read so far for the read operation. 113 | * 114 | * Note that this method may be called multiple times for a single read if you return positive numbers. 115 | **/ 116 | - (NSTimeInterval)onSocket:(AsyncSocket *)sock 117 | shouldTimeoutReadWithTag:(long)tag 118 | elapsed:(NSTimeInterval)elapsed 119 | bytesDone:(NSUInteger)length; 120 | 121 | /** 122 | * Called if a write operation has reached its timeout without completing. 123 | * This method allows you to optionally extend the timeout. 124 | * If you return a positive time interval (> 0) the write's timeout will be extended by the given amount. 125 | * If you don't implement this method, or return a non-positive time interval (<= 0) the write will timeout as usual. 126 | * 127 | * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method. 128 | * The length parameter is the number of bytes that have been written so far for the write operation. 129 | * 130 | * Note that this method may be called multiple times for a single write if you return positive numbers. 131 | **/ 132 | - (NSTimeInterval)onSocket:(AsyncSocket *)sock 133 | shouldTimeoutWriteWithTag:(long)tag 134 | elapsed:(NSTimeInterval)elapsed 135 | bytesDone:(NSUInteger)length; 136 | 137 | /** 138 | * Called after the socket has successfully completed SSL/TLS negotiation. 139 | * This method is not called unless you use the provided startTLS method. 140 | * 141 | * If a SSL/TLS negotiation fails (invalid certificate, etc) then the socket will immediately close, 142 | * and the onSocket:willDisconnectWithError: delegate method will be called with the specific SSL error code. 143 | **/ 144 | - (void)onSocketDidSecure:(AsyncSocket *)sock; 145 | 146 | @end 147 | 148 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 149 | #pragma mark - 150 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 151 | 152 | @interface AsyncSocket : NSObject 153 | { 154 | CFSocketNativeHandle theNativeSocket4; 155 | CFSocketNativeHandle theNativeSocket6; 156 | 157 | CFSocketRef theSocket4; // IPv4 accept or connect socket 158 | CFSocketRef theSocket6; // IPv6 accept or connect socket 159 | 160 | CFReadStreamRef theReadStream; 161 | CFWriteStreamRef theWriteStream; 162 | 163 | CFRunLoopSourceRef theSource4; // For theSocket4 164 | CFRunLoopSourceRef theSource6; // For theSocket6 165 | CFRunLoopRef theRunLoop; 166 | CFSocketContext theContext; 167 | NSArray *theRunLoopModes; 168 | 169 | NSTimer *theConnectTimer; 170 | 171 | NSMutableArray *theReadQueue; 172 | AsyncReadPacket *theCurrentRead; 173 | NSTimer *theReadTimer; 174 | NSMutableData *partialReadBuffer; 175 | 176 | NSMutableArray *theWriteQueue; 177 | AsyncWritePacket *theCurrentWrite; 178 | NSTimer *theWriteTimer; 179 | 180 | id theDelegate; 181 | UInt16 theFlags; 182 | 183 | long theUserData; 184 | } 185 | 186 | - (id)init; 187 | - (id)initWithDelegate:(id)delegate; 188 | - (id)initWithDelegate:(id)delegate userData:(long)userData; 189 | 190 | /* String representation is long but has no "\n". */ 191 | - (NSString *)description; 192 | 193 | /** 194 | * Use "canSafelySetDelegate" to see if there is any pending business (reads and writes) with the current delegate 195 | * before changing it. It is, of course, safe to change the delegate before connecting or accepting connections. 196 | **/ 197 | - (id)delegate; 198 | - (BOOL)canSafelySetDelegate; 199 | - (void)setDelegate:(id)delegate; 200 | 201 | /* User data can be a long, or an id or void * cast to a long. */ 202 | - (long)userData; 203 | - (void)setUserData:(long)userData; 204 | 205 | /* Don't use these to read or write. And don't close them either! */ 206 | - (CFSocketRef)getCFSocket; 207 | - (CFReadStreamRef)getCFReadStream; 208 | - (CFWriteStreamRef)getCFWriteStream; 209 | 210 | // Once one of the accept or connect methods are called, the AsyncSocket instance is locked in 211 | // and the other accept/connect methods can't be called without disconnecting the socket first. 212 | // If the attempt fails or times out, these methods either return NO or 213 | // call "onSocket:willDisconnectWithError:" and "onSockedDidDisconnect:". 214 | 215 | // When an incoming connection is accepted, AsyncSocket invokes several delegate methods. 216 | // These methods are (in chronological order): 217 | // 1. onSocket:didAcceptNewSocket: 218 | // 2. onSocket:wantsRunLoopForNewSocket: 219 | // 3. onSocketWillConnect: 220 | // 221 | // Your server code will need to retain the accepted socket (if you want to accept it). 222 | // The best place to do this is probably in the onSocket:didAcceptNewSocket: method. 223 | // 224 | // After the read and write streams have been setup for the newly accepted socket, 225 | // the onSocket:didConnectToHost:port: method will be called on the proper run loop. 226 | // 227 | // Multithreading Note: If you're going to be moving the newly accepted socket to another run 228 | // loop by implementing onSocket:wantsRunLoopForNewSocket:, then you should wait until the 229 | // onSocket:didConnectToHost:port: method before calling read, write, or startTLS methods. 230 | // Otherwise read/write events are scheduled on the incorrect runloop, and chaos may ensue. 231 | 232 | /** 233 | * Tells the socket to begin listening and accepting connections on the given port. 234 | * When a connection comes in, the AsyncSocket instance will call the various delegate methods (see above). 235 | * The socket will listen on all available interfaces (e.g. wifi, ethernet, etc) 236 | **/ 237 | - (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr; 238 | 239 | /** 240 | * This method is the same as acceptOnPort:error: with the additional option 241 | * of specifying which interface to listen on. So, for example, if you were writing code for a server that 242 | * has multiple IP addresses, you could specify which address you wanted to listen on. Or you could use it 243 | * to specify that the socket should only accept connections over ethernet, and not other interfaces such as wifi. 244 | * You may also use the special strings "localhost" or "loopback" to specify that 245 | * the socket only accept connections from the local machine. 246 | * 247 | * To accept connections on any interface pass nil, or simply use the acceptOnPort:error: method. 248 | **/ 249 | - (BOOL)acceptOnInterface:(NSString *)interface port:(UInt16)port error:(NSError **)errPtr; 250 | 251 | /** 252 | * Connects to the given host and port. 253 | * The host may be a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2") 254 | **/ 255 | - (BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr; 256 | 257 | /** 258 | * This method is the same as connectToHost:onPort:error: with an additional timeout option. 259 | * To not time out use a negative time interval, or simply use the connectToHost:onPort:error: method. 260 | **/ 261 | - (BOOL)connectToHost:(NSString *)hostname 262 | onPort:(UInt16)port 263 | withTimeout:(NSTimeInterval)timeout 264 | error:(NSError **)errPtr; 265 | 266 | /** 267 | * Connects to the given address, specified as a sockaddr structure wrapped in a NSData object. 268 | * For example, a NSData object returned from NSNetService's addresses method. 269 | * 270 | * If you have an existing struct sockaddr you can convert it to a NSData object like so: 271 | * struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len]; 272 | * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len]; 273 | **/ 274 | - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr; 275 | 276 | /** 277 | * This method is the same as connectToAddress:error: with an additional timeout option. 278 | * To not time out use a negative time interval, or simply use the connectToAddress:error: method. 279 | **/ 280 | - (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr; 281 | 282 | - (BOOL)connectToAddress:(NSData *)remoteAddr 283 | viaInterfaceAddress:(NSData *)interfaceAddr 284 | withTimeout:(NSTimeInterval)timeout 285 | error:(NSError **)errPtr; 286 | 287 | /** 288 | * Disconnects immediately. Any pending reads or writes are dropped. 289 | * If the socket is not already disconnected, the onSocketDidDisconnect delegate method 290 | * will be called immediately, before this method returns. 291 | * 292 | * Please note the recommended way of releasing an AsyncSocket instance (e.g. in a dealloc method) 293 | * [asyncSocket setDelegate:nil]; 294 | * [asyncSocket disconnect]; 295 | * [asyncSocket release]; 296 | **/ 297 | - (void)disconnect; 298 | 299 | /** 300 | * Disconnects after all pending reads have completed. 301 | * After calling this, the read and write methods will do nothing. 302 | * The socket will disconnect even if there are still pending writes. 303 | **/ 304 | - (void)disconnectAfterReading; 305 | 306 | /** 307 | * Disconnects after all pending writes have completed. 308 | * After calling this, the read and write methods will do nothing. 309 | * The socket will disconnect even if there are still pending reads. 310 | **/ 311 | - (void)disconnectAfterWriting; 312 | 313 | /** 314 | * Disconnects after all pending reads and writes have completed. 315 | * After calling this, the read and write methods will do nothing. 316 | **/ 317 | - (void)disconnectAfterReadingAndWriting; 318 | 319 | /* Returns YES if the socket and streams are open, connected, and ready for reading and writing. */ 320 | - (BOOL)isConnected; 321 | 322 | /** 323 | * Returns the local or remote host and port to which this socket is connected, or nil and 0 if not connected. 324 | * The host will be an IP address. 325 | **/ 326 | - (NSString *)connectedHost; 327 | - (UInt16)connectedPort; 328 | 329 | - (NSString *)localHost; 330 | - (UInt16)localPort; 331 | 332 | /** 333 | * Returns the local or remote address to which this socket is connected, 334 | * specified as a sockaddr structure wrapped in a NSData object. 335 | * 336 | * See also the connectedHost, connectedPort, localHost and localPort methods. 337 | **/ 338 | - (NSData *)connectedAddress; 339 | - (NSData *)localAddress; 340 | 341 | /** 342 | * Returns whether the socket is IPv4 or IPv6. 343 | * An accepting socket may be both. 344 | **/ 345 | - (BOOL)isIPv4; 346 | - (BOOL)isIPv6; 347 | 348 | // The readData and writeData methods won't block (they are asynchronous). 349 | // 350 | // When a read is complete the onSocket:didReadData:withTag: delegate method is called. 351 | // When a write is complete the onSocket:didWriteDataWithTag: delegate method is called. 352 | // 353 | // You may optionally set a timeout for any read/write operation. (To not timeout, use a negative time interval.) 354 | // If a read/write opertion times out, the corresponding "onSocket:shouldTimeout..." delegate method 355 | // is called to optionally allow you to extend the timeout. 356 | // Upon a timeout, the "onSocket:willDisconnectWithError:" method is called, followed by "onSocketDidDisconnect". 357 | // 358 | // The tag is for your convenience. 359 | // You can use it as an array index, step number, state id, pointer, etc. 360 | 361 | /** 362 | * Reads the first available bytes that become available on the socket. 363 | * 364 | * If the timeout value is negative, the read operation will not use a timeout. 365 | **/ 366 | - (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag; 367 | 368 | /** 369 | * Reads the first available bytes that become available on the socket. 370 | * The bytes will be appended to the given byte buffer starting at the given offset. 371 | * The given buffer will automatically be increased in size if needed. 372 | * 373 | * If the timeout value is negative, the read operation will not use a timeout. 374 | * If the buffer if nil, the socket will create a buffer for you. 375 | * 376 | * If the bufferOffset is greater than the length of the given buffer, 377 | * the method will do nothing, and the delegate will not be called. 378 | * 379 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 380 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 381 | * That is, it will reference the bytes that were appended to the given buffer. 382 | **/ 383 | - (void)readDataWithTimeout:(NSTimeInterval)timeout 384 | buffer:(NSMutableData *)buffer 385 | bufferOffset:(NSUInteger)offset 386 | tag:(long)tag; 387 | 388 | /** 389 | * Reads the first available bytes that become available on the socket. 390 | * The bytes will be appended to the given byte buffer starting at the given offset. 391 | * The given buffer will automatically be increased in size if needed. 392 | * A maximum of length bytes will be read. 393 | * 394 | * If the timeout value is negative, the read operation will not use a timeout. 395 | * If the buffer if nil, a buffer will automatically be created for you. 396 | * If maxLength is zero, no length restriction is enforced. 397 | * 398 | * If the bufferOffset is greater than the length of the given buffer, 399 | * the method will do nothing, and the delegate will not be called. 400 | * 401 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 402 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 403 | * That is, it will reference the bytes that were appended to the given buffer. 404 | **/ 405 | - (void)readDataWithTimeout:(NSTimeInterval)timeout 406 | buffer:(NSMutableData *)buffer 407 | bufferOffset:(NSUInteger)offset 408 | maxLength:(NSUInteger)length 409 | tag:(long)tag; 410 | 411 | /** 412 | * Reads the given number of bytes. 413 | * 414 | * If the timeout value is negative, the read operation will not use a timeout. 415 | * 416 | * If the length is 0, this method does nothing and the delegate is not called. 417 | **/ 418 | - (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag; 419 | 420 | /** 421 | * Reads the given number of bytes. 422 | * The bytes will be appended to the given byte buffer starting at the given offset. 423 | * The given buffer will automatically be increased in size if needed. 424 | * 425 | * If the timeout value is negative, the read operation will not use a timeout. 426 | * If the buffer if nil, a buffer will automatically be created for you. 427 | * 428 | * If the length is 0, this method does nothing and the delegate is not called. 429 | * If the bufferOffset is greater than the length of the given buffer, 430 | * the method will do nothing, and the delegate will not be called. 431 | * 432 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 433 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 434 | * That is, it will reference the bytes that were appended to the given buffer. 435 | **/ 436 | - (void)readDataToLength:(NSUInteger)length 437 | withTimeout:(NSTimeInterval)timeout 438 | buffer:(NSMutableData *)buffer 439 | bufferOffset:(NSUInteger)offset 440 | tag:(long)tag; 441 | 442 | /** 443 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 444 | * 445 | * If the timeout value is negative, the read operation will not use a timeout. 446 | * 447 | * If you pass nil or zero-length data as the "data" parameter, 448 | * the method will do nothing, and the delegate will not be called. 449 | * 450 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 451 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 452 | * a character, the read will prematurely end. 453 | **/ 454 | - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 455 | 456 | /** 457 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 458 | * The bytes will be appended to the given byte buffer starting at the given offset. 459 | * The given buffer will automatically be increased in size if needed. 460 | * 461 | * If the timeout value is negative, the read operation will not use a timeout. 462 | * If the buffer if nil, a buffer will automatically be created for you. 463 | * 464 | * If the bufferOffset is greater than the length of the given buffer, 465 | * the method will do nothing, and the delegate will not be called. 466 | * 467 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 468 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 469 | * That is, it will reference the bytes that were appended to the given buffer. 470 | * 471 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 472 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 473 | * a character, the read will prematurely end. 474 | **/ 475 | - (void)readDataToData:(NSData *)data 476 | withTimeout:(NSTimeInterval)timeout 477 | buffer:(NSMutableData *)buffer 478 | bufferOffset:(NSUInteger)offset 479 | tag:(long)tag; 480 | 481 | /** 482 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 483 | * 484 | * If the timeout value is negative, the read operation will not use a timeout. 485 | * 486 | * If maxLength is zero, no length restriction is enforced. 487 | * Otherwise if maxLength bytes are read without completing the read, 488 | * it is treated similarly to a timeout - the socket is closed with a AsyncSocketReadMaxedOutError. 489 | * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end. 490 | * 491 | * If you pass nil or zero-length data as the "data" parameter, 492 | * the method will do nothing, and the delegate will not be called. 493 | * If you pass a maxLength parameter that is less than the length of the data parameter, 494 | * the method will do nothing, and the delegate will not be called. 495 | * 496 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 497 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 498 | * a character, the read will prematurely end. 499 | **/ 500 | - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag; 501 | 502 | /** 503 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 504 | * The bytes will be appended to the given byte buffer starting at the given offset. 505 | * The given buffer will automatically be increased in size if needed. 506 | * A maximum of length bytes will be read. 507 | * 508 | * If the timeout value is negative, the read operation will not use a timeout. 509 | * If the buffer if nil, a buffer will automatically be created for you. 510 | * 511 | * If maxLength is zero, no length restriction is enforced. 512 | * Otherwise if maxLength bytes are read without completing the read, 513 | * it is treated similarly to a timeout - the socket is closed with a AsyncSocketReadMaxedOutError. 514 | * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end. 515 | * 516 | * If you pass a maxLength parameter that is less than the length of the data parameter, 517 | * the method will do nothing, and the delegate will not be called. 518 | * If the bufferOffset is greater than the length of the given buffer, 519 | * the method will do nothing, and the delegate will not be called. 520 | * 521 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 522 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 523 | * That is, it will reference the bytes that were appended to the given buffer. 524 | * 525 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 526 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 527 | * a character, the read will prematurely end. 528 | **/ 529 | - (void)readDataToData:(NSData *)data 530 | withTimeout:(NSTimeInterval)timeout 531 | buffer:(NSMutableData *)buffer 532 | bufferOffset:(NSUInteger)offset 533 | maxLength:(NSUInteger)length 534 | tag:(long)tag; 535 | 536 | /** 537 | * Writes data to the socket, and calls the delegate when finished. 538 | * 539 | * If you pass in nil or zero-length data, this method does nothing and the delegate will not be called. 540 | * If the timeout value is negative, the write operation will not use a timeout. 541 | **/ 542 | - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 543 | 544 | /** 545 | * Returns progress of current read or write, from 0.0 to 1.0, or NaN if no read/write (use isnan() to check). 546 | * "tag", "done" and "total" will be filled in if they aren't NULL. 547 | **/ 548 | - (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total; 549 | - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total; 550 | 551 | /** 552 | * Secures the connection using SSL/TLS. 553 | * 554 | * This method may be called at any time, and the TLS handshake will occur after all pending reads and writes 555 | * are finished. This allows one the option of sending a protocol dependent StartTLS message, and queuing 556 | * the upgrade to TLS at the same time, without having to wait for the write to finish. 557 | * Any reads or writes scheduled after this method is called will occur over the secured connection. 558 | * 559 | * The possible keys and values for the TLS settings are well documented. 560 | * Some possible keys are: 561 | * - kCFStreamSSLLevel 562 | * - kCFStreamSSLAllowsExpiredCertificates 563 | * - kCFStreamSSLAllowsExpiredRoots 564 | * - kCFStreamSSLAllowsAnyRoot 565 | * - kCFStreamSSLValidatesCertificateChain 566 | * - kCFStreamSSLPeerName 567 | * - kCFStreamSSLCertificates 568 | * - kCFStreamSSLIsServer 569 | * 570 | * Please refer to Apple's documentation for associated values, as well as other possible keys. 571 | * 572 | * If you pass in nil or an empty dictionary, the default settings will be used. 573 | * 574 | * The default settings will check to make sure the remote party's certificate is signed by a 575 | * trusted 3rd party certificate agency (e.g. verisign) and that the certificate is not expired. 576 | * However it will not verify the name on the certificate unless you 577 | * give it a name to verify against via the kCFStreamSSLPeerName key. 578 | * The security implications of this are important to understand. 579 | * Imagine you are attempting to create a secure connection to MySecureServer.com, 580 | * but your socket gets directed to MaliciousServer.com because of a hacked DNS server. 581 | * If you simply use the default settings, and MaliciousServer.com has a valid certificate, 582 | * the default settings will not detect any problems since the certificate is valid. 583 | * To properly secure your connection in this particular scenario you 584 | * should set the kCFStreamSSLPeerName property to "MySecureServer.com". 585 | * If you do not know the peer name of the remote host in advance (for example, you're not sure 586 | * if it will be "domain.com" or "www.domain.com"), then you can use the default settings to validate the 587 | * certificate, and then use the X509Certificate class to verify the issuer after the socket has been secured. 588 | * The X509Certificate class is part of the CocoaAsyncSocket open source project. 589 | **/ 590 | - (void)startTLS:(NSDictionary *)tlsSettings; 591 | 592 | /** 593 | * For handling readDataToData requests, data is necessarily read from the socket in small increments. 594 | * The performance can be much improved by allowing AsyncSocket to read larger chunks at a time and 595 | * store any overflow in a small internal buffer. 596 | * This is termed pre-buffering, as some data may be read for you before you ask for it. 597 | * If you use readDataToData a lot, enabling pre-buffering will result in better performance, especially on the iPhone. 598 | * 599 | * The default pre-buffering state is controlled by the DEFAULT_PREBUFFERING definition. 600 | * It is highly recommended one leave this set to YES. 601 | * 602 | * This method exists in case pre-buffering needs to be disabled by default for some unforeseen reason. 603 | * In that case, this method exists to allow one to easily enable pre-buffering when ready. 604 | **/ 605 | - (void)enablePreBuffering; 606 | 607 | /** 608 | * When you create an AsyncSocket, it is added to the runloop of the current thread. 609 | * So for manually created sockets, it is easiest to simply create the socket on the thread you intend to use it. 610 | * 611 | * If a new socket is accepted, the delegate method onSocket:wantsRunLoopForNewSocket: is called to 612 | * allow you to place the socket on a separate thread. This works best in conjunction with a thread pool design. 613 | * 614 | * If, however, you need to move the socket to a separate thread at a later time, this 615 | * method may be used to accomplish the task. 616 | * 617 | * This method must be called from the thread/runloop the socket is currently running on. 618 | * 619 | * Note: After calling this method, all further method calls to this object should be done from the given runloop. 620 | * Also, all delegate calls will be sent on the given runloop. 621 | **/ 622 | - (BOOL)moveToRunLoop:(NSRunLoop *)runLoop; 623 | 624 | /** 625 | * Allows you to configure which run loop modes the socket uses. 626 | * The default set of run loop modes is NSDefaultRunLoopMode. 627 | * 628 | * If you'd like your socket to continue operation during other modes, you may want to add modes such as 629 | * NSModalPanelRunLoopMode or NSEventTrackingRunLoopMode. Or you may simply want to use NSRunLoopCommonModes. 630 | * 631 | * Accepted sockets will automatically inherit the same run loop modes as the listening socket. 632 | * 633 | * Note: NSRunLoopCommonModes is defined in 10.5. For previous versions one can use kCFRunLoopCommonModes. 634 | **/ 635 | - (BOOL)setRunLoopModes:(NSArray *)runLoopModes; 636 | - (BOOL)addRunLoopMode:(NSString *)runLoopMode; 637 | - (BOOL)removeRunLoopMode:(NSString *)runLoopMode; 638 | 639 | /** 640 | * Returns the current run loop modes the AsyncSocket instance is operating in. 641 | * The default set of run loop modes is NSDefaultRunLoopMode. 642 | **/ 643 | - (NSArray *)runLoopModes; 644 | 645 | /** 646 | * In the event of an error, this method may be called during onSocket:willDisconnectWithError: to read 647 | * any data that's left on the socket. 648 | **/ 649 | - (NSData *)unreadData; 650 | 651 | /* A few common line separators, for use with the readDataToData:... methods. */ 652 | + (NSData *)CRLFData; // 0x0D0A 653 | + (NSData *)CRData; // 0x0D 654 | + (NSData *)LFData; // 0x0A 655 | + (NSData *)ZeroData; // 0x00 656 | 657 | @end 658 | -------------------------------------------------------------------------------- /ServerExample/CocoaAsyncSocket/Source/RunLoop/AsyncSocket.h: -------------------------------------------------------------------------------- 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 | 11 | #import 12 | 13 | @class AsyncSocket; 14 | @class AsyncReadPacket; 15 | @class AsyncWritePacket; 16 | 17 | extern NSString *const AsyncSocketException; 18 | extern NSString *const AsyncSocketErrorDomain; 19 | 20 | typedef NS_ENUM(NSInteger, AsyncSocketError) { 21 | AsyncSocketCFSocketError = kCFSocketError, // From CFSocketError enum. 22 | AsyncSocketNoError = 0, // Never used. 23 | AsyncSocketCanceledError, // onSocketWillConnect: returned NO. 24 | AsyncSocketConnectTimeoutError, 25 | AsyncSocketReadMaxedOutError, // Reached set maxLength without completing 26 | AsyncSocketReadTimeoutError, 27 | AsyncSocketWriteTimeoutError 28 | }; 29 | 30 | @protocol AsyncSocketDelegate 31 | @optional 32 | 33 | /** 34 | * In the event of an error, the socket is closed. 35 | * You may call "unreadData" during this call-back to get the last bit of data off the socket. 36 | * When connecting, this delegate method may be called 37 | * before"onSocket:didAcceptNewSocket:" or "onSocket:didConnectToHost:". 38 | **/ 39 | - (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err; 40 | 41 | /** 42 | * Called when a socket disconnects with or without error. If you want to release a socket after it disconnects, 43 | * do so here. It is not safe to do that during "onSocket:willDisconnectWithError:". 44 | * 45 | * If you call the disconnect method, and the socket wasn't already disconnected, 46 | * this delegate method will be called before the disconnect method returns. 47 | **/ 48 | - (void)onSocketDidDisconnect:(AsyncSocket *)sock; 49 | 50 | /** 51 | * Called when a socket accepts a connection. Another socket is spawned to handle it. The new socket will have 52 | * the same delegate and will call "onSocket:didConnectToHost:port:". 53 | **/ 54 | - (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket; 55 | 56 | /** 57 | * Called when a new socket is spawned to handle a connection. This method should return the run-loop of the 58 | * thread on which the new socket and its delegate should operate. If omitted, [NSRunLoop currentRunLoop] is used. 59 | **/ 60 | - (NSRunLoop *)onSocket:(AsyncSocket *)sock wantsRunLoopForNewSocket:(AsyncSocket *)newSocket; 61 | 62 | /** 63 | * Called when a socket is about to connect. This method should return YES to continue, or NO to abort. 64 | * If aborted, will result in AsyncSocketCanceledError. 65 | * 66 | * If the connectToHost:onPort:error: method was called, the delegate will be able to access and configure the 67 | * CFReadStream and CFWriteStream as desired prior to connection. 68 | * 69 | * If the connectToAddress:error: method was called, the delegate will be able to access and configure the 70 | * CFSocket and CFSocketNativeHandle (BSD socket) as desired prior to connection. You will be able to access and 71 | * configure the CFReadStream and CFWriteStream in the onSocket:didConnectToHost:port: method. 72 | **/ 73 | - (BOOL)onSocketWillConnect:(AsyncSocket *)sock; 74 | 75 | /** 76 | * Called when a socket connects and is ready for reading and writing. 77 | * The host parameter will be an IP address, not a DNS name. 78 | **/ 79 | - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port; 80 | 81 | /** 82 | * Called when a socket has completed reading the requested data into memory. 83 | * Not called if there is an error. 84 | **/ 85 | - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag; 86 | 87 | /** 88 | * Called when a socket has read in data, but has not yet completed the read. 89 | * This would occur if using readToData: or readToLength: methods. 90 | * It may be used to for things such as updating progress bars. 91 | **/ 92 | - (void)onSocket:(AsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; 93 | 94 | /** 95 | * Called when a socket has completed writing the requested data. Not called if there is an error. 96 | **/ 97 | - (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag; 98 | 99 | /** 100 | * Called when a socket has written some data, but has not yet completed the entire write. 101 | * It may be used to for things such as updating progress bars. 102 | **/ 103 | - (void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; 104 | 105 | /** 106 | * Called if a read operation has reached its timeout without completing. 107 | * This method allows you to optionally extend the timeout. 108 | * If you return a positive time interval (> 0) the read's timeout will be extended by the given amount. 109 | * If you don't implement this method, or return a non-positive time interval (<= 0) the read will timeout as usual. 110 | * 111 | * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method. 112 | * The length parameter is the number of bytes that have been read so far for the read operation. 113 | * 114 | * Note that this method may be called multiple times for a single read if you return positive numbers. 115 | **/ 116 | - (NSTimeInterval)onSocket:(AsyncSocket *)sock 117 | shouldTimeoutReadWithTag:(long)tag 118 | elapsed:(NSTimeInterval)elapsed 119 | bytesDone:(NSUInteger)length; 120 | 121 | /** 122 | * Called if a write operation has reached its timeout without completing. 123 | * This method allows you to optionally extend the timeout. 124 | * If you return a positive time interval (> 0) the write's timeout will be extended by the given amount. 125 | * If you don't implement this method, or return a non-positive time interval (<= 0) the write will timeout as usual. 126 | * 127 | * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method. 128 | * The length parameter is the number of bytes that have been written so far for the write operation. 129 | * 130 | * Note that this method may be called multiple times for a single write if you return positive numbers. 131 | **/ 132 | - (NSTimeInterval)onSocket:(AsyncSocket *)sock 133 | shouldTimeoutWriteWithTag:(long)tag 134 | elapsed:(NSTimeInterval)elapsed 135 | bytesDone:(NSUInteger)length; 136 | 137 | /** 138 | * Called after the socket has successfully completed SSL/TLS negotiation. 139 | * This method is not called unless you use the provided startTLS method. 140 | * 141 | * If a SSL/TLS negotiation fails (invalid certificate, etc) then the socket will immediately close, 142 | * and the onSocket:willDisconnectWithError: delegate method will be called with the specific SSL error code. 143 | **/ 144 | - (void)onSocketDidSecure:(AsyncSocket *)sock; 145 | 146 | @end 147 | 148 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 149 | #pragma mark - 150 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 151 | 152 | @interface AsyncSocket : NSObject 153 | { 154 | CFSocketNativeHandle theNativeSocket4; 155 | CFSocketNativeHandle theNativeSocket6; 156 | 157 | CFSocketRef theSocket4; // IPv4 accept or connect socket 158 | CFSocketRef theSocket6; // IPv6 accept or connect socket 159 | 160 | CFReadStreamRef theReadStream; 161 | CFWriteStreamRef theWriteStream; 162 | 163 | CFRunLoopSourceRef theSource4; // For theSocket4 164 | CFRunLoopSourceRef theSource6; // For theSocket6 165 | CFRunLoopRef theRunLoop; 166 | CFSocketContext theContext; 167 | NSArray *theRunLoopModes; 168 | 169 | NSTimer *theConnectTimer; 170 | 171 | NSMutableArray *theReadQueue; 172 | AsyncReadPacket *theCurrentRead; 173 | NSTimer *theReadTimer; 174 | NSMutableData *partialReadBuffer; 175 | 176 | NSMutableArray *theWriteQueue; 177 | AsyncWritePacket *theCurrentWrite; 178 | NSTimer *theWriteTimer; 179 | 180 | id theDelegate; 181 | UInt16 theFlags; 182 | 183 | long theUserData; 184 | } 185 | 186 | - (id)init; 187 | - (id)initWithDelegate:(id)delegate; 188 | - (id)initWithDelegate:(id)delegate userData:(long)userData; 189 | 190 | /* String representation is long but has no "\n". */ 191 | - (NSString *)description; 192 | 193 | /** 194 | * Use "canSafelySetDelegate" to see if there is any pending business (reads and writes) with the current delegate 195 | * before changing it. It is, of course, safe to change the delegate before connecting or accepting connections. 196 | **/ 197 | - (id)delegate; 198 | - (BOOL)canSafelySetDelegate; 199 | - (void)setDelegate:(id)delegate; 200 | 201 | /* User data can be a long, or an id or void * cast to a long. */ 202 | - (long)userData; 203 | - (void)setUserData:(long)userData; 204 | 205 | /* Don't use these to read or write. And don't close them either! */ 206 | - (CFSocketRef)getCFSocket; 207 | - (CFReadStreamRef)getCFReadStream; 208 | - (CFWriteStreamRef)getCFWriteStream; 209 | 210 | // Once one of the accept or connect methods are called, the AsyncSocket instance is locked in 211 | // and the other accept/connect methods can't be called without disconnecting the socket first. 212 | // If the attempt fails or times out, these methods either return NO or 213 | // call "onSocket:willDisconnectWithError:" and "onSockedDidDisconnect:". 214 | 215 | // When an incoming connection is accepted, AsyncSocket invokes several delegate methods. 216 | // These methods are (in chronological order): 217 | // 1. onSocket:didAcceptNewSocket: 218 | // 2. onSocket:wantsRunLoopForNewSocket: 219 | // 3. onSocketWillConnect: 220 | // 221 | // Your server code will need to retain the accepted socket (if you want to accept it). 222 | // The best place to do this is probably in the onSocket:didAcceptNewSocket: method. 223 | // 224 | // After the read and write streams have been setup for the newly accepted socket, 225 | // the onSocket:didConnectToHost:port: method will be called on the proper run loop. 226 | // 227 | // Multithreading Note: If you're going to be moving the newly accepted socket to another run 228 | // loop by implementing onSocket:wantsRunLoopForNewSocket:, then you should wait until the 229 | // onSocket:didConnectToHost:port: method before calling read, write, or startTLS methods. 230 | // Otherwise read/write events are scheduled on the incorrect runloop, and chaos may ensue. 231 | 232 | /** 233 | * Tells the socket to begin listening and accepting connections on the given port. 234 | * When a connection comes in, the AsyncSocket instance will call the various delegate methods (see above). 235 | * The socket will listen on all available interfaces (e.g. wifi, ethernet, etc) 236 | **/ 237 | - (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr; 238 | 239 | /** 240 | * This method is the same as acceptOnPort:error: with the additional option 241 | * of specifying which interface to listen on. So, for example, if you were writing code for a server that 242 | * has multiple IP addresses, you could specify which address you wanted to listen on. Or you could use it 243 | * to specify that the socket should only accept connections over ethernet, and not other interfaces such as wifi. 244 | * You may also use the special strings "localhost" or "loopback" to specify that 245 | * the socket only accept connections from the local machine. 246 | * 247 | * To accept connections on any interface pass nil, or simply use the acceptOnPort:error: method. 248 | **/ 249 | - (BOOL)acceptOnInterface:(NSString *)interface port:(UInt16)port error:(NSError **)errPtr; 250 | 251 | /** 252 | * Connects to the given host and port. 253 | * The host may be a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2") 254 | **/ 255 | - (BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr; 256 | 257 | /** 258 | * This method is the same as connectToHost:onPort:error: with an additional timeout option. 259 | * To not time out use a negative time interval, or simply use the connectToHost:onPort:error: method. 260 | **/ 261 | - (BOOL)connectToHost:(NSString *)hostname 262 | onPort:(UInt16)port 263 | withTimeout:(NSTimeInterval)timeout 264 | error:(NSError **)errPtr; 265 | 266 | /** 267 | * Connects to the given address, specified as a sockaddr structure wrapped in a NSData object. 268 | * For example, a NSData object returned from NSNetService's addresses method. 269 | * 270 | * If you have an existing struct sockaddr you can convert it to a NSData object like so: 271 | * struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len]; 272 | * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len]; 273 | **/ 274 | - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr; 275 | 276 | /** 277 | * This method is the same as connectToAddress:error: with an additional timeout option. 278 | * To not time out use a negative time interval, or simply use the connectToAddress:error: method. 279 | **/ 280 | - (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr; 281 | 282 | - (BOOL)connectToAddress:(NSData *)remoteAddr 283 | viaInterfaceAddress:(NSData *)interfaceAddr 284 | withTimeout:(NSTimeInterval)timeout 285 | error:(NSError **)errPtr; 286 | 287 | /** 288 | * Disconnects immediately. Any pending reads or writes are dropped. 289 | * If the socket is not already disconnected, the onSocketDidDisconnect delegate method 290 | * will be called immediately, before this method returns. 291 | * 292 | * Please note the recommended way of releasing an AsyncSocket instance (e.g. in a dealloc method) 293 | * [asyncSocket setDelegate:nil]; 294 | * [asyncSocket disconnect]; 295 | * [asyncSocket release]; 296 | **/ 297 | - (void)disconnect; 298 | 299 | /** 300 | * Disconnects after all pending reads have completed. 301 | * After calling this, the read and write methods will do nothing. 302 | * The socket will disconnect even if there are still pending writes. 303 | **/ 304 | - (void)disconnectAfterReading; 305 | 306 | /** 307 | * Disconnects after all pending writes have completed. 308 | * After calling this, the read and write methods will do nothing. 309 | * The socket will disconnect even if there are still pending reads. 310 | **/ 311 | - (void)disconnectAfterWriting; 312 | 313 | /** 314 | * Disconnects after all pending reads and writes have completed. 315 | * After calling this, the read and write methods will do nothing. 316 | **/ 317 | - (void)disconnectAfterReadingAndWriting; 318 | 319 | /* Returns YES if the socket and streams are open, connected, and ready for reading and writing. */ 320 | - (BOOL)isConnected; 321 | 322 | /** 323 | * Returns the local or remote host and port to which this socket is connected, or nil and 0 if not connected. 324 | * The host will be an IP address. 325 | **/ 326 | - (NSString *)connectedHost; 327 | - (UInt16)connectedPort; 328 | 329 | - (NSString *)localHost; 330 | - (UInt16)localPort; 331 | 332 | /** 333 | * Returns the local or remote address to which this socket is connected, 334 | * specified as a sockaddr structure wrapped in a NSData object. 335 | * 336 | * See also the connectedHost, connectedPort, localHost and localPort methods. 337 | **/ 338 | - (NSData *)connectedAddress; 339 | - (NSData *)localAddress; 340 | 341 | /** 342 | * Returns whether the socket is IPv4 or IPv6. 343 | * An accepting socket may be both. 344 | **/ 345 | - (BOOL)isIPv4; 346 | - (BOOL)isIPv6; 347 | 348 | // The readData and writeData methods won't block (they are asynchronous). 349 | // 350 | // When a read is complete the onSocket:didReadData:withTag: delegate method is called. 351 | // When a write is complete the onSocket:didWriteDataWithTag: delegate method is called. 352 | // 353 | // You may optionally set a timeout for any read/write operation. (To not timeout, use a negative time interval.) 354 | // If a read/write opertion times out, the corresponding "onSocket:shouldTimeout..." delegate method 355 | // is called to optionally allow you to extend the timeout. 356 | // Upon a timeout, the "onSocket:willDisconnectWithError:" method is called, followed by "onSocketDidDisconnect". 357 | // 358 | // The tag is for your convenience. 359 | // You can use it as an array index, step number, state id, pointer, etc. 360 | 361 | /** 362 | * Reads the first available bytes that become available on the socket. 363 | * 364 | * If the timeout value is negative, the read operation will not use a timeout. 365 | **/ 366 | - (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag; 367 | 368 | /** 369 | * Reads the first available bytes that become available on the socket. 370 | * The bytes will be appended to the given byte buffer starting at the given offset. 371 | * The given buffer will automatically be increased in size if needed. 372 | * 373 | * If the timeout value is negative, the read operation will not use a timeout. 374 | * If the buffer if nil, the socket will create a buffer for you. 375 | * 376 | * If the bufferOffset is greater than the length of the given buffer, 377 | * the method will do nothing, and the delegate will not be called. 378 | * 379 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 380 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 381 | * That is, it will reference the bytes that were appended to the given buffer. 382 | **/ 383 | - (void)readDataWithTimeout:(NSTimeInterval)timeout 384 | buffer:(NSMutableData *)buffer 385 | bufferOffset:(NSUInteger)offset 386 | tag:(long)tag; 387 | 388 | /** 389 | * Reads the first available bytes that become available on the socket. 390 | * The bytes will be appended to the given byte buffer starting at the given offset. 391 | * The given buffer will automatically be increased in size if needed. 392 | * A maximum of length bytes will be read. 393 | * 394 | * If the timeout value is negative, the read operation will not use a timeout. 395 | * If the buffer if nil, a buffer will automatically be created for you. 396 | * If maxLength is zero, no length restriction is enforced. 397 | * 398 | * If the bufferOffset is greater than the length of the given buffer, 399 | * the method will do nothing, and the delegate will not be called. 400 | * 401 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 402 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 403 | * That is, it will reference the bytes that were appended to the given buffer. 404 | **/ 405 | - (void)readDataWithTimeout:(NSTimeInterval)timeout 406 | buffer:(NSMutableData *)buffer 407 | bufferOffset:(NSUInteger)offset 408 | maxLength:(NSUInteger)length 409 | tag:(long)tag; 410 | 411 | /** 412 | * Reads the given number of bytes. 413 | * 414 | * If the timeout value is negative, the read operation will not use a timeout. 415 | * 416 | * If the length is 0, this method does nothing and the delegate is not called. 417 | **/ 418 | - (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag; 419 | 420 | /** 421 | * Reads the given number of bytes. 422 | * The bytes will be appended to the given byte buffer starting at the given offset. 423 | * The given buffer will automatically be increased in size if needed. 424 | * 425 | * If the timeout value is negative, the read operation will not use a timeout. 426 | * If the buffer if nil, a buffer will automatically be created for you. 427 | * 428 | * If the length is 0, this method does nothing and the delegate is not called. 429 | * If the bufferOffset is greater than the length of the given buffer, 430 | * the method will do nothing, and the delegate will not be called. 431 | * 432 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 433 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 434 | * That is, it will reference the bytes that were appended to the given buffer. 435 | **/ 436 | - (void)readDataToLength:(NSUInteger)length 437 | withTimeout:(NSTimeInterval)timeout 438 | buffer:(NSMutableData *)buffer 439 | bufferOffset:(NSUInteger)offset 440 | tag:(long)tag; 441 | 442 | /** 443 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 444 | * 445 | * If the timeout value is negative, the read operation will not use a timeout. 446 | * 447 | * If you pass nil or zero-length data as the "data" parameter, 448 | * the method will do nothing, and the delegate will not be called. 449 | * 450 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 451 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 452 | * a character, the read will prematurely end. 453 | **/ 454 | - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 455 | 456 | /** 457 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 458 | * The bytes will be appended to the given byte buffer starting at the given offset. 459 | * The given buffer will automatically be increased in size if needed. 460 | * 461 | * If the timeout value is negative, the read operation will not use a timeout. 462 | * If the buffer if nil, a buffer will automatically be created for you. 463 | * 464 | * If the bufferOffset is greater than the length of the given buffer, 465 | * the method will do nothing, and the delegate will not be called. 466 | * 467 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 468 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 469 | * That is, it will reference the bytes that were appended to the given buffer. 470 | * 471 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 472 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 473 | * a character, the read will prematurely end. 474 | **/ 475 | - (void)readDataToData:(NSData *)data 476 | withTimeout:(NSTimeInterval)timeout 477 | buffer:(NSMutableData *)buffer 478 | bufferOffset:(NSUInteger)offset 479 | tag:(long)tag; 480 | 481 | /** 482 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 483 | * 484 | * If the timeout value is negative, the read operation will not use a timeout. 485 | * 486 | * If maxLength is zero, no length restriction is enforced. 487 | * Otherwise if maxLength bytes are read without completing the read, 488 | * it is treated similarly to a timeout - the socket is closed with a AsyncSocketReadMaxedOutError. 489 | * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end. 490 | * 491 | * If you pass nil or zero-length data as the "data" parameter, 492 | * the method will do nothing, and the delegate will not be called. 493 | * If you pass a maxLength parameter that is less than the length of the data parameter, 494 | * the method will do nothing, and the delegate will not be called. 495 | * 496 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 497 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 498 | * a character, the read will prematurely end. 499 | **/ 500 | - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag; 501 | 502 | /** 503 | * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. 504 | * The bytes will be appended to the given byte buffer starting at the given offset. 505 | * The given buffer will automatically be increased in size if needed. 506 | * A maximum of length bytes will be read. 507 | * 508 | * If the timeout value is negative, the read operation will not use a timeout. 509 | * If the buffer if nil, a buffer will automatically be created for you. 510 | * 511 | * If maxLength is zero, no length restriction is enforced. 512 | * Otherwise if maxLength bytes are read without completing the read, 513 | * it is treated similarly to a timeout - the socket is closed with a AsyncSocketReadMaxedOutError. 514 | * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end. 515 | * 516 | * If you pass a maxLength parameter that is less than the length of the data parameter, 517 | * the method will do nothing, and the delegate will not be called. 518 | * If the bufferOffset is greater than the length of the given buffer, 519 | * the method will do nothing, and the delegate will not be called. 520 | * 521 | * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. 522 | * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. 523 | * That is, it will reference the bytes that were appended to the given buffer. 524 | * 525 | * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. 526 | * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for 527 | * a character, the read will prematurely end. 528 | **/ 529 | - (void)readDataToData:(NSData *)data 530 | withTimeout:(NSTimeInterval)timeout 531 | buffer:(NSMutableData *)buffer 532 | bufferOffset:(NSUInteger)offset 533 | maxLength:(NSUInteger)length 534 | tag:(long)tag; 535 | 536 | /** 537 | * Writes data to the socket, and calls the delegate when finished. 538 | * 539 | * If you pass in nil or zero-length data, this method does nothing and the delegate will not be called. 540 | * If the timeout value is negative, the write operation will not use a timeout. 541 | **/ 542 | - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 543 | 544 | /** 545 | * Returns progress of current read or write, from 0.0 to 1.0, or NaN if no read/write (use isnan() to check). 546 | * "tag", "done" and "total" will be filled in if they aren't NULL. 547 | **/ 548 | - (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total; 549 | - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total; 550 | 551 | /** 552 | * Secures the connection using SSL/TLS. 553 | * 554 | * This method may be called at any time, and the TLS handshake will occur after all pending reads and writes 555 | * are finished. This allows one the option of sending a protocol dependent StartTLS message, and queuing 556 | * the upgrade to TLS at the same time, without having to wait for the write to finish. 557 | * Any reads or writes scheduled after this method is called will occur over the secured connection. 558 | * 559 | * The possible keys and values for the TLS settings are well documented. 560 | * Some possible keys are: 561 | * - kCFStreamSSLLevel 562 | * - kCFStreamSSLAllowsExpiredCertificates 563 | * - kCFStreamSSLAllowsExpiredRoots 564 | * - kCFStreamSSLAllowsAnyRoot 565 | * - kCFStreamSSLValidatesCertificateChain 566 | * - kCFStreamSSLPeerName 567 | * - kCFStreamSSLCertificates 568 | * - kCFStreamSSLIsServer 569 | * 570 | * Please refer to Apple's documentation for associated values, as well as other possible keys. 571 | * 572 | * If you pass in nil or an empty dictionary, the default settings will be used. 573 | * 574 | * The default settings will check to make sure the remote party's certificate is signed by a 575 | * trusted 3rd party certificate agency (e.g. verisign) and that the certificate is not expired. 576 | * However it will not verify the name on the certificate unless you 577 | * give it a name to verify against via the kCFStreamSSLPeerName key. 578 | * The security implications of this are important to understand. 579 | * Imagine you are attempting to create a secure connection to MySecureServer.com, 580 | * but your socket gets directed to MaliciousServer.com because of a hacked DNS server. 581 | * If you simply use the default settings, and MaliciousServer.com has a valid certificate, 582 | * the default settings will not detect any problems since the certificate is valid. 583 | * To properly secure your connection in this particular scenario you 584 | * should set the kCFStreamSSLPeerName property to "MySecureServer.com". 585 | * If you do not know the peer name of the remote host in advance (for example, you're not sure 586 | * if it will be "domain.com" or "www.domain.com"), then you can use the default settings to validate the 587 | * certificate, and then use the X509Certificate class to verify the issuer after the socket has been secured. 588 | * The X509Certificate class is part of the CocoaAsyncSocket open source project. 589 | **/ 590 | - (void)startTLS:(NSDictionary *)tlsSettings; 591 | 592 | /** 593 | * For handling readDataToData requests, data is necessarily read from the socket in small increments. 594 | * The performance can be much improved by allowing AsyncSocket to read larger chunks at a time and 595 | * store any overflow in a small internal buffer. 596 | * This is termed pre-buffering, as some data may be read for you before you ask for it. 597 | * If you use readDataToData a lot, enabling pre-buffering will result in better performance, especially on the iPhone. 598 | * 599 | * The default pre-buffering state is controlled by the DEFAULT_PREBUFFERING definition. 600 | * It is highly recommended one leave this set to YES. 601 | * 602 | * This method exists in case pre-buffering needs to be disabled by default for some unforeseen reason. 603 | * In that case, this method exists to allow one to easily enable pre-buffering when ready. 604 | **/ 605 | - (void)enablePreBuffering; 606 | 607 | /** 608 | * When you create an AsyncSocket, it is added to the runloop of the current thread. 609 | * So for manually created sockets, it is easiest to simply create the socket on the thread you intend to use it. 610 | * 611 | * If a new socket is accepted, the delegate method onSocket:wantsRunLoopForNewSocket: is called to 612 | * allow you to place the socket on a separate thread. This works best in conjunction with a thread pool design. 613 | * 614 | * If, however, you need to move the socket to a separate thread at a later time, this 615 | * method may be used to accomplish the task. 616 | * 617 | * This method must be called from the thread/runloop the socket is currently running on. 618 | * 619 | * Note: After calling this method, all further method calls to this object should be done from the given runloop. 620 | * Also, all delegate calls will be sent on the given runloop. 621 | **/ 622 | - (BOOL)moveToRunLoop:(NSRunLoop *)runLoop; 623 | 624 | /** 625 | * Allows you to configure which run loop modes the socket uses. 626 | * The default set of run loop modes is NSDefaultRunLoopMode. 627 | * 628 | * If you'd like your socket to continue operation during other modes, you may want to add modes such as 629 | * NSModalPanelRunLoopMode or NSEventTrackingRunLoopMode. Or you may simply want to use NSRunLoopCommonModes. 630 | * 631 | * Accepted sockets will automatically inherit the same run loop modes as the listening socket. 632 | * 633 | * Note: NSRunLoopCommonModes is defined in 10.5. For previous versions one can use kCFRunLoopCommonModes. 634 | **/ 635 | - (BOOL)setRunLoopModes:(NSArray *)runLoopModes; 636 | - (BOOL)addRunLoopMode:(NSString *)runLoopMode; 637 | - (BOOL)removeRunLoopMode:(NSString *)runLoopMode; 638 | 639 | /** 640 | * Returns the current run loop modes the AsyncSocket instance is operating in. 641 | * The default set of run loop modes is NSDefaultRunLoopMode. 642 | **/ 643 | - (NSArray *)runLoopModes; 644 | 645 | /** 646 | * In the event of an error, this method may be called during onSocket:willDisconnectWithError: to read 647 | * any data that's left on the socket. 648 | **/ 649 | - (NSData *)unreadData; 650 | 651 | /* A few common line separators, for use with the readDataToData:... methods. */ 652 | + (NSData *)CRLFData; // 0x0D0A 653 | + (NSData *)CRData; // 0x0D 654 | + (NSData *)LFData; // 0x0A 655 | + (NSData *)ZeroData; // 0x00 656 | 657 | @end 658 | --------------------------------------------------------------------------------