If need in the project like QQ to do instant communication, must use socket communication, I also just learn, share, there is nothing wrong place hope everybody correct
iOS native socket is not very intuitive to use, so I use asyncsocket this third-party library, the socket is better, just as if there is no out-of-band transmission (Out-of-band) If your server needs to send out out-of-band data, you might want to do something else.
Environment
Download the Asyncsockethttps://github.com/robbiehanson/cocoaasyncsocket class library, place the Runloop folder under AsyncSocket.h, ASYNCSOCKET.M, AsyncUdpSocket.h, ASYNCUDPSOCKET.M files are copied to your own project
Add Cfnetwork.framework, in the file header using the socket
#import <sys/socket.h> #import <netinet/in.h> #import <arpa/inet.h> #import <unistd.h>
Use
1. Socket connection
Real-time communication is the most important feature is realtime, the basic sense is not delayed or dropped, so the connection to the socket must be monitored and detected, when disconnected, reconnect, if the user exits the login, to the socket manually shut down, or the server will cause a certain load.
In general, a user (for iOS, our project) can have only one socket connected, so the socket variable must be global, here you can consider using a singleton or appdelegate for data sharing, this article uses a single case. If a connected socket object is connected again, it throws an exception (no connection to the connected socket) crashes, so the connection state of the socket object is judged before connecting to the socket.
Using the socket for Instant messaging There is also a necessary operation, that is, sending a heartbeat packet to the server, sending long connection instructions to the server at intervals (instructions are not unique, specified by the server, including sending messages using the socket, sending data and formats are specified by the server), If you do not receive a return message from the server, Asyncsocket will get the message of the lost connection, and we can reconnect in the lost connection callback method.
First create a singleton, named Singleton
Singleton.h
Singleton.h#import "AsyncSocket.h" #define Define_shared_instance_using_block (BLOCK) \static dispatch_once_t Oncetoken = 0; __strong static id sharedinstance = NIL; \dispatch_once (&oncetoken, ^{sharedinstance = block ();}); \return sharedinstance; \ @interface singleton:nsobject+ (Singleton *) sharedinstance; @end
Singleton.m
+ (Singleton *) sharedinstance{static Singleton *sharedinstace = nil;static dispatch_once_t oncetoken;dispatch_once ( &oncetoken, ^{sharedinstace = [[Self alloc] init];}); return sharedinstace;}
Such a single example is created.
The life socket variable in the. h file
@property (nonatomic, strong) Asyncsocket *socket; [Email protected] (nonatomic, copy) NSString *sockethost; socket [email protected] (nonatomic, assign) UInt16 Socketport; Socket's Prot
Here is 连接
, 心跳
,,失去连接后重连
Connection (long Connection)
Declare the method in the. h file, and declare the proxy<AsyncSocketDelegate>
-(void) socketconnecthost;//socket connection
Implemented in. m, the host and port are specified by the server when connecting, and if the server is not the one you write to, communicate with the server-side developer
Socket connection-(void) socketconnecthost{self.socket = [[Asyncsocket alloc] initwithdelegate:self]; Nserror *error = nil; [Self.socket connectToHost:self.socketHost onPort:self.socketPort withtimeout:3 error:&error];}
Heartbeat
The heartbeat is realized by a timer.
Declaring a timer in the Singleton.h
@property (nonatomic, retain) Nstimer *connecttimer; Timer
Implement the connection success callback method in. m, and initialize the timer in this method to send the heartbeat when sending data to the server
#pragma mark-Connection succeeded Callback-(void) Onsocket: (Asyncsocket *) sock didconnecttohost: (NSString *) host port: (UInt16) port{NSLog (@ "Socket connection succeeded"); Every 30s like the server sends heartbeat packet Self.connecttimer = [Nstimer scheduledtimerwithtimeinterval:30 target:self selector: @selector ( Longconnecttosocket) Userinfo:nil repeats:yes];//The message sent to the server for a long connection in the Longconnecttosocket method [Self.connecttimer fire];}
2. Socket disconnected and re-connected
Disconnect Connection
There are several cases of loss of connectivity, the server is disconnected, the user active cut, but also may be like QQ other device login is dropped, regardless of that situation, we can receive the socket callback method returned to our message, if the user is logged out or the program exits the need for manual cut, We assign a value to the userdata of the socket before the cut to mark the user's exit so that we can determine what caused the drop when we receive the break information.
Declaring an enumeration type in an. h file
enum{socketofflinebyserver,//Server Drop line, the default is 0 socketofflinebyuser,//user active Cut};
Declaring a disconnect method
-(void) cutoffsocket; Disconnecting the socket connection
. m
Cut off socket-(void) cutoffsocket{self.socket.userData = socketofflinebyuser;//declaration is initiated by the user to cut [Self.connecttimer Invalida TE]; [Self.socket disconnect];}
reconnects
Implementing Proxy methods
-(void) Onsocketdiddisconnect: (asyncsocket *) Sock{ nslog (@ "sorry the connect is failure %ld ", Sock.userdata); if (sock.userData == socketofflinebyserver) { // server dropped, re-connected [self socketConnectHost]; } else if (Sock.userdata == socketofflinebyuser) { // if disconnected by the user, do not re-connect return; }}
3. Socket send and receive data
Send Data
We add a method of not completing the heartbeat connection above
Heartbeat connection-(void) longconnecttosocket{//Send fixed-format data according to server requirements, assuming the directive @ "Longconnect", but generally not as simple as instructions nsstring *longconnect = @ " Longconnect "; NSData *datastream = [Longconnect datausingencoding:nsutf8stringencoding]; [Self.socket writedata:datastream withtimeout:1 tag:1];}
Socket send data is stored in the form of a stack, all data placed in a stack, access will appear sticky packet phenomenon, so many times the server in sending and receiving data is to send the content byte length, and then send the form of content, get the data is also first to get a length, Then according to this length in the stack to read this length of the byte stream, if this is the case, send the data only need to send a length before sending the content, the sending method is the same as the sending content, assuming a length of 8
NSData *datastream = [@8 datausingencoding:nsutf8stringencoding]; [Self.socket writedata:datastream withtimeout:1 tag:1];
Receive Data
In order to receive the message of the socket at all times, we read the data in the long connection method
[Self.socket readdatawithtimeout:30 tag:0];
If the data is obtained, the callback method is called
-(void) Onsocket: (Asyncsocket *) sock didreaddata: (NSData *) data withtag: (long) tag{//To parse and convert the resulting data value [Self.socket Readdatawithtimeout:30 tag:0];}
4. Simple use instructions
We in the user login the first interface to the socket initialization connection operation, after getting the data, will need to display the data in the singleton, the variable is monitored after the corresponding operation can be extended to more complex, no real data is not too convenient to explain, Let's explore it yourself, please leave a message below
[singleton sharedinstance].sockethost = @ "192.186.100.21";// Host setting [singleton sharedinstance].socketport = 10045;// port settings // manually disconnect [singleton sharedinstance before connecting]. socket.userdata = socketofflinebyuser; [[singleton sharedinstance] cutoffsocket]; // be sure to disconnect and then crash if connecting to a socket that is in a connected state [ singleton sharedinstance].socket.userdata = socketofflinebyserver; [[ Singleton sharedinstance] socketconnecthost];
All the code here, just the integration of this article, run out as blank
iOS learning socket using a simple tutorial-asyncsocket