CocoaAsyncSocket learning for IOS development

Source: Internet
Author: User

The following content is translated from:

Http://code.google.com/p/cocoaasyncsocket/

Cocoaasyncsocket supports TCP and UDP. Where:

  • The asyncsocket class supports TCP
  • Asyncudpsocket supports UDP

AsyncSockeT is the TCP/IP Socket network library that encapsulates cfsocket and cfsteam. It provides asynchronous operations and complete support for local cocoa classes based on delegate. It has the following features:

  • Non-blocking read and write of the queue, and optional timeout. You can call it to read and write data. It will notify you after completion.
  • Automatic socket reception. If you call it to receive connections, it will start new instances for each connection. Of course, you can also immediately close these connections.
  • Delegation is supported. Errors, connections, reception, complete reading, complete writing, progress, and disconnection can all be called in delegate Mode
  • Based on the run loop, rather than the thread. Although it can be used in the main thread or working thread, you do not need to do so. It calls the delegate method asynchronously and uses the nsunloop. The delegate method includes socket parameters, which can be distinguished among multiple instances.
  • Self-contained in a class. You don't need to operate the stream or socket. This class helps you do everything
  • Supports IPV4 and IPV6-based TCP streams

Asyncudpsocket is a UDP/IP socket network library packaged from cfsocket. It works like a TCP version, but is only used to process UDP. It includes sending and receiving operations based on non-blocking queues, complete delegation support, self-contained classes based on runloop, and support for IPv4 and IPv6.

The following content is based on official website reference:

Http://code.google.com/p/cocoaasyncsocket/wiki/Reference_AsyncSocket

Example.

 

Preparation: How to Use

You can follow the link on the official website to execute:

Http://code.google.com/p/cocoaasyncsocket/wiki/iPhone

There are basically two steps:

  1. Drag the. h and. m files in the CocoaAsyncSocket project to the Classes directory of your project.
  2. Add framework: CFNetwork

 

Write a simple TCP Connection

Write a simple TCP connection application. HTTP is actually built on the TCP protocol. Here we will use a request and a response to the website for demonstration.

To illustrate the image, first simulate HTTP manually. Telnet is required. This is a command line tool. If you press:

C: \ Users \ login Al Wu> Telnet
'Telnet 'is not an internal or external command or a program that can be run.
Or batch files.

 

It indicates that you are using Windows Vista or Windows 7, because Windows XP installs the software by default.

I am using Mac OSX, which comes with this tool. If the problem occurs, referUse telnet in vistaInstall Telnet.

Then, you can use this tool to send the socket information and receive the information returned by the socket. The following describes the procedure,

The following uses cocoaasyncsocket.

First, implement the related delegate:

# Import <UIKit/UIKit. h>

# Import "AsyncSocket. h"

@ Interface SocketDemosViewController: UIViewController<AsyncSocketDelegate>

 

Then, in the implementation code:

-(Void) onSocket :( AsyncSocket *) sock didConnectToHost :( NSString *) host port :( UInt16) port {

NSLog (@ "did connect to host ");
}

-(Void) onSocket :( AsyncSocket *) sock didReadData :( NSData *) data withTag :( long) tag {

NSLog (@ "did read data ");
NSString * message = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding] autorelease];

NSLog (@ "message is: \ n % @", message );
}

 

The methods in AsyncSocketDelegate are optional. I have implemented a listener for establishing a connection and reading data.

These listeners can be used only when an AsyncSocket instance is created and used. The following code is used:

-(Void) viewDidLoad {
[Super viewDidLoad];

AsyncSocket * socket = [[AsyncSocket alloc] initWithDelegate: self];
[Socket connectToHost: @ "www.baidu.com" onPort: 80 error: nil];

[Socket readDataWithTimeout: 3 tag: 1];
[Socket writeData: [@ "GET/HTTP/1.1 \ n" dataUsingEncoding: NSUTF8StringEncoding] withTimeout: 3 tag: 1];

 

I wrote this part of Code directly to the controller's viewDidLoad.

The execution log is as follows:

17:17:46. 545 SocketDemos [27120: 207] did connect to host
17:17:46. 620 SocketDemos [27120: 207] did read data
17:17:46. 621 SocketDemos [27120: 207] message is:
HTTP/1.1 200 OK
Date: Tue, 19 Jul 2011 09:17:46 GMT
Server: BWS/1.0.
Content-Length: 7691
Content-Type: text/html; charset = gb2312
Cache-Control: private
Expires: Tue, 19 Jul 2011 09:17:46 GMT
Set-Cookie: BAIDUID = 9389BA38262D7997D220A564154CCA87: FG = 1; expires = Tue, 19-Jul-41 09:17:46 GMT; path =/; domain = .baidu.com

P3P: CP = "oti dsp cor iva our ind com"
Connection: Keep-Alive

The HTTP response is truncated because we do not want to write the function that actually receives the HTTP response, so this defect can be ignored.

Originally, the HTTP request should be disabled by the server. For example, if you use telent for access, you can see the following ending:

Therefore, the server does not disconnect the connection because the HTTP response is not completely received. You can close the connection on the client, as shown in the following code:

[Socket readDataWithTimeout: 3 tag: 1];
[Socket writeData: [@ "GET/HTTP/1.1 \ n" dataUsingEncoding: NSUTF8StringEncoding] withTimeout: 3 tag: 1];

[Socket disconnect];

In addition, you can implement this method in delegate:

-(Void) onSocketDidDisconnect :( AsyncSocket *) sock {
NSLog (@ "socket did disconnect ");
}

 

In this way, you can monitor the closed connection information in the log.

 

The TCP connection reads data of the specified length.

Socket connections often encounter such a requirement to read fixed-length bytes. This can be achieved through the following example.

It is also a demonstration based on HTTP connections. For example, take twice, 50 bytes each time. Then stop the socket.

You can write as follows:

-(Void) viewdidload {
[Super viewdidload];

Socket = [[asyncsocket alloc] initwithdelegate: Self];
[Socket connecttohost: @ "www.baidu.com" onport: 80 error: Nil];

Data = [[nsmutabledata datawithlength: 50] retain];

[Socket readdatatolength: 50 withtimeout: 5 Tag: 1];
[Socket readdatatolength: 50 withtimeout: 5 Tag: 2];
[Socket writedata: [@ "Get/HTTP/1.1 \ n" datausingencoding: nsutf8stringencoding] withtimeout: 3 tag: 1];

 

In delegate, this method mainly works:

-(Void) onsocket :( asyncsocket *) sock didreaddata :( nsdata *) _ DATA withtag :( long) Tag {

Nslog (@ "did read data ");
Nsstring * message = [[[nsstring alloc] initwithdata: _ data encoding: nsutf8stringencoding] autorelease];

Nslog (@ "message is: \ n % @", message );

If (TAG = 2 ){
[Socket Disconnect];
}
}

The log is similar to the following:

The highlighted red is the byte content retrieved twice.

 

Write server Socket

Echo examples are compiled to illustrate the simplest method of writing server-side socket. ECHO is an echo. The server returns an echo of what is sent through Telnet. Similar to this:

The server needs to listen to the client connection. Wait for the client to send a message. The Code is as follows:

Socket = [[asyncsocket alloc] initwithdelegate: Self];
Nserror * err = nil;

If ([socket acceptOnPort: 4322 error: & err]) {
NSLog (@ "accept OK .");
} Else {
NSLog (@ "accept failed .");
}

If (err ){
NSLog (@ "error: % @", err );
}

 

If this step succeeds, there should be only one log:

12:27:03. 228 SocketDemos [611: 707] accept OK.

In this case, if a client establishes a connection with it, for example, telnet. The following method will call the delegate of AsyncSocket in sequence:

  • OnSocket: didAcceptNewSocket: AsyncSocket creates a new Socket for processing requests from the client. If you do not intend to retain the new socket instance (retain), the connection to the client will be rejected.
  • OnSocket: wantsRunLoopForNewSocket: Provides the runloop instance of the thread to AsyncSocket. The latter uses this runloop to perform socket communication.
  • OnSocketWillConnect:, the connection is to be established, and some preparation work can be done at this time, if necessary
  • OnSocket: didConnectToHost: port:. This method is executed after a connection is established. Generally, the write or read socket operation is called here.

In the Echo example, you do not want to execute multiple threads or support multi-client connections, and the server and client will establish a persistent connection. The corresponding socket is released only when the client is disconnected.

The Code is as follows:

-(Void) onSocket :( AsyncSocket *) sock didAcceptNewSocket :( AsyncSocket *) newSocket {

If (! AcceptSocket ){
AcceptSocket = [newSocket retain];
NSLog (@ "did accept new socket ");
}
}

-(Nsunloop *) onSocket :( AsyncSocket *) sock wantsRunLoopForNewSocket :( AsyncSocket *) newSocket {

NSLog (@ "wants runloop for new socket .");
Return [nsunloop currentRunLoop];
}

-(BOOL) onSocketWillConnect :( AsyncSocket *) sock {
NSLog (@ "will connect ");
Return YES;
}

-(Void) onSocket :( AsyncSocket *) sock didConnectToHost :( NSString *) host port :( UInt16) port {

NSLog (@ "did connect to host ");
[AcceptSocket readDataWithTimeout:-1 tag: 1];
}

-(Void) onSocket :( AsyncSocket *) sock didReadData :( NSData *) data withTag :( long) tag {

NSLog (@ "did read data ");
NSString * message = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding] autorelease];

NSLog (@ "message is: \ n % @", message );
[AcceptSocket writeData: data withTimeout: 2 tag: 1];
}

-(Void) onSocket :( AsyncSocket *) sock didWriteDataWithTag :( long) tag {

NSLog (@ "message did write ");
[AcceptSocket readDataWithTimeout:-1 tag: 1];
}

-(Void) onSocket :( AsyncSocket *) sock willDisconnectWithError :( NSError *) err {

NSLog (@ "onSocket: % p willDisconnectWithError: % @", sock, err );
}

-(Void) onSocketDidDisconnect :( AsyncSocket *) sock {
NSLog (@ "socket did disconnect ");
[AcceptSocket release];
AcceptSocket = nil;
}

 

Here, the timeout is set to-1, so that the persistent connection can be maintained.

 

Write a simple UDP Application

First, write an example of sending a UDP datagram. This requires a server to receive the content. A simple acceptor is written in Java:

Public static void main (String [] args) throws IOException {
InetSocketAddress address = new InetSocketAddress ("0.0.0.0", 5555 );
DatagramSocket datagramSocket = new DatagramSocket (address );

System. out. println ("start udp server ");

Byte [] buffer = new byte [1024];

For (;;){
Datagrampacket = new datagrampacket (buffer, buffer. Length );
Datagramsocket. Receive (datagrampacket );
System. Out. println ("receive data:" + new string (datagrampacket. getdata (), 0, datagrampacket. getlength ()));

}
}

 

The code for sending is as follows:

Asyncudpsocket * socket = [[asyncudpsocket alloc] initwithdelegate: Self];

Nsdata * Data = [@ "hello from iPhone" datausingencoding: nsutf8stringencoding];

[Socket senddata: Data tohost: @ "192.168.0.165" port: 5555 withtimeout:-1 Tag: 1];
Nslog (@ "Send UPD complete .");

 

After execution, the following content is successfully output at the receiving end:

Below, write the code of the acceptor:

AsyncUdpSocket * socket = [[AsyncUdpSocket alloc] initWithDelegate: self];

NSError * error = nil;
[Socket bindToPort: 5555 error: & error];

If (error ){
NSLog (@ "error: % @", error );
}

[Socket receiveWithTimeout:-1 tag: 1];
NSLog (@ "start udp server ");

In addition, at least write the delegate method:

-(BOOL) onUdpSocket :( AsyncUdpSocket *) sock
DidReceiveData :( NSData *) data
WithTag :( long) tag
FromHost :( NSString *) host
Port :( UInt16) port {
NSLog (@ "received data: % @", [[[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding] autorelease]);

Return YES;
}

 

The sender, or write a test code using java:

Public static void main (String [] args) throws IOException {
DatagramSocket datagramSocket = new DatagramSocket ();
Byte [] buffer = "Hello! ". GetBytes ();
DatagramPacket datagramPacket = new DatagramPacket (buffer,
Buffer. length, new InetSocketAddress ("192.168.0.144", 5555 ));
DatagramSocket. send (datagramPacket );
}

 

In the iPhone log:

15:23:33. 571 SocketDemos [795: 707] start udp server
15:23:47. 395 SocketDemos [795: 707] received data: Hello!

Received the datagram.

 

Send and receive multicast using UDP

The main concern here is the reception. On the one hand, it is the requirement, and on the other hand, it has encounteredAndroid Wifi gets MulticastThe problem is that iOS has a similar mechanism. Later, the test found that it was not so troublesome (enable the multicast lock ).

For testing, a simple code for sending UDP broadcasts is written in java:

Public static void main (String [] args) throws IOException {
Int port = 3333;
MulticastSocket socket = new MulticastSocket (port );
InetAddress address = InetAddress. getByName ("239.0.0.1 ");
Socket. joinGroup (address );
Byte [] data = "Hello everyone.". getBytes ();
DatagramPacket datagramPacket = new DatagramPacket (data, data. length, address, port );

Socket. send (datagramPacket );
System. out. println ("send OK .");

 

IOS code:

Asyncudpsocket * socket = [[asyncudpsocket alloc] initwithdelegate: Self];

Nserror * error = nil;
[Socket bindtoport: 3333 error: & error];
[Socket enablebroadcast: Yes error: & error];
[Socket joinmulticastgroup: @ "239.0.0.1" error: & error];

If (error ){
Nslog (@ "error: % @", error );
}

[Socket receivewithtimeout:-1 Tag: 1];
Nslog (@ "Start UDP server ");

 

The delegate is exactly the same as the preceding normal UDP:

-(Bool) onudpsocket :( asyncudpsocket *) sock
Didreceivedata :( nsdata *) data
Withtag :( long) Tag
Fromhost :( nsstring *) Host
Port :( uint16) Port {
Nslog (@ "received data: % @", [[[nsstring alloc] initwithdata: data encoding: nsutf8stringencoding] autorelease]);

Return yes;
}

 

Test logs:

16:14:30. 338 socketdemos [860: 707] Start UDP Server
16:14:42. 829 socketdemos [860: 707] received data: Hello everyone.

It indicates that you have received the message.

Sending multicast is similar to the preceding UDP sending, but the join group operation is needed. I will not talk about it here.

Original article: http://marshal.easymorse.com/archives/4533

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.