Socket-Based C/S network communication (medium) in iOS)
Based on the previous knowledge, next we will introduce Socket programming based on the TCP protocol. Because the Socket requires a client and a server, what is implemented now is a simple program about the server. The server uses the CFStream class for implementation.
This server uses the Command Line Tool in Xcode as the server; of course, you can also use the iPhone as the server, but to use other frameworks, such as AsyncSocket (https://github.com/roustem/AsyncSocket ), there are sockets implemented by UDP and TCP. There are also many operations on data streams in the source program, which can be used for in-depth understanding. Of course, it is also complicated.
Let's take a look at the simple TCP server program: (TCPServer. m)
# Import
# Include
# Include
# Define PORT 9000 void AcceptCallBack (CFSocketRef, signature, CFDataRef, const void *, void *); void Merge (CFWriteStreamRef stream, CFStreamEventType eventType, void *); void Merge (CFReadStreamRef stream, CFStreamEventType eventType, void *); int main (int argc, const char * argv []) {/* defines a Server Socket reference */CFSocketRef sserver; /* Create socket context */C FSocketContext CTX = {0, NULL};/* create server socket TCP IPv4 to set the callback function */sserver = CFSocketCreate (NULL, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack) AcceptCallBack, & CTX); if (sserver = NULL) return-1;/* set whether to rebind the flag */int yes = 1; /* set the socket property SOL_SOCKET to set tcp SO_REUSEADDR to rebind, yes to re-bind */setsockopt (CFSocketGetNative (sserver), SOL_SOCKET, SO _ REUSEADDR, (void *) & yes, sizeof (yes);/* set the port and address */struct sockaddr_in addr; memset (& addr, 0, sizeof (addr )); // The memset function copies the specified address in memory. sin_len = sizeof (addr); addr. sin_family = AF_INET; // AF_INET is used to set IPv4 addr. sin_port = htons (PORT); // The value of the unsigned short integer in the htons function is converted to the "Network byte order" addr. sin_addr.s_addr = htonl (INADDR_ANY); // INADDR_ANY has kernel allocation. The htonl function converts the unsigned long integer to "Network byte order"/* replicates data from the specified byte buffer zone, an unchangeable CFData object */CFDataRef address = CFDataCreate (kCFAllocatorDefault, (UInt8 *) & addr, sizeof (addr);/* set Socket */if (CFSocketSetAddress (sserver, (CFDataRef) address )! = KCFSocketSuccess) {fprintf (stderr, "Socket binding failed \ n"); CFRelease (sserver); return-1 ;} /* Create a Run Loop Socket source */CFRunLoopSourceRef sourceRef = kernel (kCFAllocatorDefault, sserver, 0);/* Add the Socket source to the Run Loop */CFRunLoopAddSource (CFRunLoopGetCurrent (), sourceRef, kCFRunLoopCommonModes); CFRelease (sourceRef); printf ("Socket listening on port % d \ n", PORT);/* Run Loop */CFRunLoo PRun ();}/* after receiving the client request, the callback function */void AcceptCallBack (CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void * data, void * info) {CFReadStreamRef readStream = NULL; CFWriteStreamRef writeStream = NULL;/* the meaning of the data parameter is: if the data type is bytes, the data is a pointer of the encoding type */CFSocketNativeHandle sock = *) data;/* Create a read/write Socket stream */CFStreamCreatePairWithSocke T (kCFAllocatorDefault, sock, & readStream, & writeStream); if (! ReadStream |! WriteStream) {close (sock); fprintf (stderr, "CFStreamCreatePairWithSocket () failed \ n"); return;} CFStreamClientContext streamCtxt = {0, NULL }; // register two callback functions: CFReadStreamSetClient (readStream, callback, ReadStreamClientCallBack, & streamCtxt); CFWriteStreamSetClient (writeStream, callback, WriteStreamClientCallBack, & streamCtxt); // Add CFReadS to the loop TreamScheduleWithRunLoop (readStream, CFRunLoopGetCurrent (), iterator); iterator (writeStream, CFRunLoopGetCurrent (), iterator); CFReadStreamOpen (readStream); CFWriteStreamOpen (writeStream );} /* call */void ReadStreamClientCallBack (CFReadStreamRef stream, CFStreamEventType eventType, void * clientCallBackInfo) {UInt8 buff [255]; CFReadStrea MRef inputStream = stream; if (NULL! = InputStream) {CFReadStreamRead (stream, buff, 255); printf ("received data: % s \ n", buff); CFReadStreamClose (inputStream); CFReadStreamUnscheduleFromRunLoop (inputStream, CFRunLoopGetCurrent (), callback); inputStream = NULL;}/* The write stream operation client calls */void WriteStreamClientCallBack (CFWriteStreamRef stream, CFStreamEventType eventType, void * clientCallBackInfo) when reading data) {CFWriteStreamRef outputStream = strea M; // output UInt8 buff [] = "Hello Client! "; If (NULL! = OutputStream) {CFWriteStreamWrite (outputStream, buff, strlen (const char *) buff) + 1); // close the output stream CFWriteStreamClose (outputStream); CFWriteStreamUnscheduleFromRunLoop (outputStream, CFRunLoopGetCurrent (), kCFRunLoopCommonModes); outputStream = NULL ;}}
This program only involves simple data flow operations. For detailed data flow operations, see the source code of AsyncSocket. So far, a server has been implemented.
To be continued ......