A socket is a special kind of file. It is a file connected to two users, any one user to write data to the socket, another user can see, no matter how far apart the two users in the world is located in a corner, it feels like sitting together to pass the note.
So the socket should be easier to understand? This abstraction is very important, because it shields the bottom of things, I want to write a program to send the next data, why the relationship between the physical layer, right?
So with the concept of a socket, we can send a message between two clients:
Specify the address of the other party
Open a socket connected to each other
The socket as a normal file, write data in the
If you find data in the socket, read it, it must be sent by the other side.
In this case, is the network programming very simple?
So let's get started.
First of all, we first match the environment, Cocoaasyncsocket is a three-party class library, we need to go to Guthub download or terminal directly installed here is not too much introduction.
With a good framework we need to introduce the cfnetwork.framework framework, which is a direct reference to the framework of Xcode province.
Okay, let's get the environment together. Lets encapsulate a class to manipulate the socket
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
Create a single-instance method
+ (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;
}
Below is the connection, heartbeat, loss of connection after reconnection (long connection) in the. h file, declaring the method, and declaring 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 success Callback
-(void) Onsocket: (Asyncsocket *) sock didconnecttohost: (NSString *) host port: (UInt16) port
{
NSLog (@ "Socket connected successfully");
Send heartbeat packets every 30s like server
Self.connecttimer = [Nstimer scheduledtimerwithtimeinterval:30 target:self selector: @selector (Longconnecttosocket) Userinfo:nil repeats:yes];//a message to be 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 dropped, default is 0
Socketofflinebyuser,//user active cut
};
Declaring a disconnect method
-(void) cutoffsocket; Disconnecting the socket connection
. m
Cut the socket.
-(void) cutoffsocket{
Self.socket.userData = socketofflinebyuser;//declaration is actively cut off by the user
[Self.connecttimer invalidate];
[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 a fixed-format data according to the server's requirements, assuming the directive @ "Longconnect", but it is generally not such a simple instruction
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
{
Parse and convert the resulting data values
[Self.socket readdatawithtimeout:30 tag:0];
}
4. Simple use instructions
We in the user login the first interface to the socket of the initial connection operation, after obtaining the data, the need to display the data in the singleton, the variable is monitored after the corresponding operation can be extended to a more complex,
[Singleton sharedinstance].sockethost = @ "192.186.100.21";//Host setting
[Singleton sharedinstance].socketport = 10045;//port setting
Manual disconnection prior to connection
[Singleton sharedinstance].socket.userdata = Socketofflinebyuser;
[[Singleton sharedinstance] cutoffsocket];
Make sure to disconnect and then crash if you connect to a socket that is in a connected state
[Singleton sharedinstance].socket.userdata = Socketofflinebyserver;
[[Singleton sharedinstance] socketconnecthost];
iOS development--talking about Cocoaasyncsocket programming