GCDAsyncSocket rapid development of Socket communication based on iOS

IOS based on the rapid development of Socket communications GCDAsyncSocket Miyagi

And Socket reconstruction design: iOS Socket reconstruction design


GCDAsyncSocket is one of the third party libraries in CocoaAsyncSocket, this paper is based on this class to do the rapid development of socket communications

This is my call to the GCDAsyncSocket layer of packaging, which includes the build, disconnect, reconnection, heartbeat, custom request

GitHub – Yuzeyang/GCDAsyncSocketManager

Easy to use, please help me star, fork oh oh


First of all, introduce the use of CocoaAsyncSocket third party Library

CocoaAsyncSocket provides easy-to-use and powerful asynchronous socket libraries for Mac and iOS.

Translate into:

IOS provides an easy to use and powerful asynchronous communication library for Mac and
CocoaAsyncSocket

In the Podfile file, as long as this sentence can be used

Pod’CocoaAsyncSocket’,’7.4.1′


Simple Socket communications, including the construction of connected, disconnected, send socket service requests, re connect these four basic functions

Below, I will be in accordance with the four basic functions in terms of how to use CocoaAsyncSocket in the GCDAsyncSocket class to develop Socket Communications

First of all, Socket in the first step, you need to connect to start communication

There are four ways to initialize in GCDAsyncSocket

– (ID) init;
(ID) initWithSocketQueue: (dispatch_queue_t) sq; (ID) – initWithDelegate: (ID) aDelegate delegateQueue: (dispatch_queue_t) DQ; (ID) – initWithDelegate: (ID) aDelegate delegateQueue: (dispatch_queue_t) DQ socketQueue: (dispatch_queue_t) sq; @property (atomic, weak, readwrite) id delegate;
@property (atomic, assign, readwrite) dispatch_queue_t delegateQueue;
(void) setDelegate: (ID) delegate delegateQueue: (dispatch_queue_t) delegateQueue;

SQ is the socket thread, this is optional, if you write null, GCDAsyncSocket will help you create a socket of its own thread, if you want to own a socket thread, do not provide a concurrent thread in the frequent socket communication process, may be blocked, personal that is not to create

ADelegate is the socket proxy

DQ is the delegate thread

You need to set up the socket agent and the agent of the thread, or socket callback you do not know,

For example:

Self.socket= [[GCDAsyncSocket initWithDelegate:self delegateQueue:dispatch_get_main_queue ()) alloc] (
)

Then, after setting up the proxy, you need to try to connect to the appropriate address to determine if your socket is connected

(BOOL) connectToHost: (NSString*) host onPort: (uint16_t) port error: (NSError**) errPtr;

Host is the host address, port is the port number

If you are successful, you will receive a successful callback socket, in which you can do something you need to do something, my side, then do a heartbeat treatment

– (void) socket: (GCDAsyncSocket*) sock didConnectToHost: (NSString*) host port: (UInt16) port

If you fail to build, will receive a failure of the callback, I failed to do in the side of the re operation

(void) socketDidDisconnect: (GCDAsyncSocket*) sock withError: (NSError*) err

Even the operation is relatively simple, only need to call a construction company request, I set the rules here even is even 5 times, each time interval is 2 times more than n times, after no longer to reconnect the

– (void) socketDidDisconnect: (GCDAsyncSocket*) sock withError: (NSError* ERR) {_status= -1; if (_reconnection_time> =0 & & _reconnection_time = < kMaxReconnection_time) {[_timer invalidate]; _timer=nil int; time =pow (2, _reconnection_time); _timer= [NSTimer scheduledTimerWithTimeInterval:time target:selfselector:@selector (reconnection) userInfo:nil repeats:NO]; _reconnection_time++; NSLog (@ “socket did reconnection, after%ds try again”, time);}else{_reconnection_time=0; NSLog (@ socketDidDisconnect:%p withError:, sock, err% @ “);}}

Here I use status to mark the connection status of socket

So socket has been built, how to initiate socket communication?

You will need to agree with the backend developer for the socket protocol format, such as:

[NSString stringWithFormat:@ “version/”%d, {/ “/” reqType/ “:%d /” body/ “/”}/r/n “:”%@/, PROTOCOL_VERSION, reqType, reqBody];

Everyone should be able to see the middle, why do you need to add /r/n?

This is a /r/n socket message delimiters, is the message in order to prevent the occurrence of adhesion, without /r/n, probably due to some reason, the back-end will receive two socket requests, but the end do not know how to split the two request

Similarly, when receiving the socket request callback, will also be based on this boundary to split

So why use /r/n?

And the GCDAsyncSocket does not support custom boundaries, it provides four kinds of boundary for you to use /r/n, /r, /n, empty string

After assembling the socket request, you need to call the GCDAsyncSocket method to send the request, and then write it and you will receive the callback

[self.socket writeData:requestData withTimeout:-1 tag:0];

Timeout is a timeout, which is set according to the actual needs

This is a write back

(void) socket: (GCDAsyncSocket*) sock didWriteDataWithTag: (long) tag;

After writing, you need to call the reading method, so as to receive the data you received from the server after you request

[self.socketreadDataToData:[GCDAsyncSocket CRLFData] maxLength:50000 tag:0];
; withTimeout:10

[GCDAsyncSocket CRLFData] here is to set the boundary symbol, maxLength is set to receive the maximum content of the requested data content

In the read callback, you can perform different operations according to different operations

(void) socket: (GCDAsyncSocket*) sock didReadData: (NSData*) data withTag: (long) tag;

The last one is disconnected, this calls only

[self.socket disconnect];

OK, in this case, the simplest basic socket communications, you have been able to complete the ~!

—————————————————-

2016.4.26 update

Some people say that in the network environment and other factors, it is likely to cause the client or back-end did not receive a callback or request, then how to do?

We need to deal with the receipt of the message

When the client makes a request, the request may be put to array, until the corresponding callback backend, if the request timeout, indicating the backend does not receive our request, we will resend the request

When the client receives the request, the back-end data to the client, the client needs to increase the receipt, tell the back-end, the client receives the data, if not received back, but also to push over data, two-way protection of client and backend to solve the problem of losing

2016.8.5 update

In some cases, can not locate the back end of the problem or the client /SDK problem, you can use the command line to grab a look at the socket package (Charles can only use HTTP and HTTPS package)

Command line is as follows:

Sudo tcpdump any -X port 7070 -n

Tip:7070 port number according to the actual debug port number

The results are as follows:

GCDAsyncSocket rapid development of Socket communication based on iOS
red part is the contents of the socket package

If you have any comments or suggestions, please leave a message, knowledge is the need to communicate, I believe there will be a better and more concise way to deal with

This is my personal WeChat public number, will be published on a number of iOS development and difficult problems and I read some of the technical and non-technical books, welcome to subscribe!

GCDAsyncSocket rapid development of Socket communication based on iOS
Miyagi Dev