Write in front
I have made an application of sending character instruction to middleware. Based on the practical principle, I only use one diagram to replace the basic principle of socket. I will show the use of socket in the form of four middle schools,
The first thing to know: socket transmission is divided into input stream (also called write stream) and output stream (output from client and send to server)
- C language
- BSDSocket
- NSStream
- GCDAsyncSocket
C language
client
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #define MAXRCVLEN 500 #define PORTNUM 2348 int main(int argc, char *argv[]) { char buffer[] = "My name is khan"; /* +1 so we can add null terminator */ int len, mysocket; struct sockaddr_in dest; mysocket = socket(AF_INET, SOCK_STREAM, 0); memset(&dest, 0, sizeof(dest)); /* zero the struct */ dest.sin_family = AF_INET; dest.sin_addr.s_addr = inet_addr("127.0.0.1"); /* set destination IP number */ dest.sin_port = htons(PORTNUM); /* set destination port number */ connect(mysocket, (struct sockaddr *)&dest, sizeof(struct sockaddr)); len = send(mysocket, buffer, strlen(buffer), 0); perror("len\n"); /* We have to null terminate the received data ourselves */ buffer[len] = '\0'; printf("sent %s (%d bytes).\n", buffer, len); close(mysocket); return EXIT_SUCCESS; }
Server side
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #define PORTNUM 2348 #define bufferLength 500 int main(int argc, char *argv[]) { char buffer[bufferLength]; struct sockaddr_in dest; /* socket info about the machine connecting to us */ struct sockaddr_in serv; /* socket info about our server */ int mysocket; /* socket used to listen for incoming connections */ socklen_t socksize = sizeof(struct sockaddr_in); memset(&serv, 0, sizeof(serv)); /* zero the struct before filling the fields */ serv.sin_family = AF_INET; /* set the type of connection to TCP/IP */ serv.sin_addr.s_addr = htonl(INADDR_ANY); /* set our address to any interface */ serv.sin_port = htons(PORTNUM); /* set the server port number */ mysocket = socket(AF_INET, SOCK_STREAM, 0); /* bind serv information to mysocket */ bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr)); /* start listening, allowing a queue of up to 1 pending connection */ listen(mysocket, 1); int consocket; int cpid; while(1) { consocket = accept(mysocket, (struct sockaddr *)&dest, &socksize); perror("consocket\n"); if( (cpid = fork()) == 0 ) { printf("inside child process\n\n\n"); close(mysocket); close(consocket); int recivedBytes = recv(consocket, buffer, bufferLength, 0); buffer[recivedBytes] = '\0'; printf("recieved data %s \n", buffer); return 0; } else close(consocket); } close(mysocket); return EXIT_SUCCESS; }
BSDSocket
1. Create a thread join event
NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:@"%@:%d", HOST, PORT]]; NSThread * backgroundThread = [[NSThread alloc] initWithTarget:self selector:@selector(loadDataFromServerWithURL:) object:url]; [backgroundThread start];
2. Data returned from sending to response receiving server
-(void)loadDataFromServerWithURL:(NSURL*)url{ NSString * host = [url host]; NSInteger port = [[url port] integerValue]; //Create Client CFStreamClientContext ctx = {0, (__bridge void *)(self), NULL, NULL, NULL}; //The specific time to register the trigger time of callback events is described in the following callback functions one by one CFOptionFlags registeredEvents = (kCFStreamEventHasBytesAvailable |kCFStreamEventNone|kCFStreamEventOpenCompleted| kCFStreamEventCanAcceptBytes|kCFStreamEventEndEncountered | kCFStreamEventErrorOccurred); //Create write stream CFWriteStreamRef writeStream ; CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef)host, (UInt32)port, NULL, &writeStream) ; //Join runloop if (CFWriteStreamSetClient( writeStream , registeredEventsTwo, socketCallbackCFWriteStreamRef, &ctx)) { CFWriteStreamScheduleWithRunLoop( writeStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); }else{ [self networkFailedWithErrorMessage:@"CFWriteStreamSetClient Failed to assign callback method"]; return; } //Enable write stream if (CFWriteStreamOpen( writeStream) == NO) { [self networkFailedWithErrorMessage:@"Failed to open write stream"]; return; } CFErrorRef error2 = CFWriteStreamCopyError(writeStream); if (error2 != NULL) { if (CFErrorGetCode(error2) != 0) { NSString * errorInfo = [NSString stringWithFormat:@"Failed to connect stream; error2 '%@' (code %ld)", (__bridge NSString*)CFErrorGetDomain(error2), CFErrorGetCode(error2)]; [self networkFailedWithErrorMessage:errorInfo]; } //release CFRelease(error2); } // Start process CFRunLoopRun(); }
void socketCallbackCFWriteStreamRef(CFWriteStreamRef stream, CFStreamEventType event, void * myPtr) { NSLog(@"socketCallbackCFWriteStreamRef >> in Thread %@", [NSThread currentThread]); StreamViewController * controller = (__bridge StreamViewController *)myPtr; switch(event) { //Open flow case kCFStreamEventOpenCompleted: break; //Data flow can accept data. Here you need to send your data to the server case kCFStreamEventCanAcceptBytes:{ NSString *testString = @"168353b1-6b6c-4ebd-891e-0b51d81be166|1|f4c1b518-80fe-47aa-8f87-58b5a062dcb9"; NSData *testData = [testString dataUsingEncoding: NSUTF8StringEncoding]; Byte *testByte = (Byte *)[testData bytes]; CFWriteStreamWrite( stream, testByte, testData.length); } break; //In case of an unexpected call, for example, you send data to the server, and the data returned by the server is read here case kCFStreamEventErrorOccurred: { [controller networkFailedWithErrorMessage:@"socketCallbackCFWriteStreamRef Write failed"]; break; } //Read server data case kCFStreamEventHasBytesAvailable:{ //Read data until no data is returned while (CFReadStreamHasBytesAvailable(stream)) { UInt8 buffer[kBufferSize]; int numBytesRead = CFReadStreamRead(stream, buffer, kBufferSize); [controller didReceiveData:[NSData dataWithBytes:buffer length:numBytesRead]]; } break; } break; //Complete data receiving, close flow case kCFStreamEventEndEncountered: [controller didFinishReceivingData]; // Clean up free memory CFWriteStreamClose(stream); CFWriteStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); CFRunLoopStop(CFRunLoopGetCurrent()); break; default: break; }
NSStream
NSStream is a simple encapsulation of CFReadStreamRef or CFWriteStreamRef above
NSSream is divided into input stream (NSOutputStream: for the client, it comes from the server side) and output stream (NSInputStream: output from the client, send to the server side)
//Output stream uint8_t * buffer ; char * str = "168353b1-6b6c-4ebd-891e-0b51d81be166|1|ddef2049-761a-45a0-9e77-ebf684c4b8f0"; NSOutputStream * outputStream = [NSOutputStream outputStreamToBuffer:buffer capacity:sizeof(buffer)]; //Configure HOST PORT agent NSStreamDelegate [outputStream setProperty:@"123.123.118.67" forKey:NSStreamSOCKSProxyHostKey]; [outputStream setProperty:@"4521" forKey:NSStreamSOCKSProxyPortKey]; [outputStream setDelegate:self]; //Join common search [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; NSLog(@"%@", [outputStream propertyForKey:NSStreamSOCKSProxyHostKey]); //Open output stream [outputStream open];
Proxy callback
#pragma mark -NSStreamDelegate - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{ //This is very similar to the previous one. You can learn by comparison. I will not introduce it in detail here switch (eventCode) { case NSStreamEventOpenCompleted: NSLog(@"NSStreamEventOpenCompleted"); break; case NSStreamEventHasBytesAvailable: NSLog(@"NSStreamEventHasBytesAvailable"); uint8_t buf[1024]; unsigned int len = 0; len = [(NSInputStream *)aStream read:buf maxLength:1024]; if(len) { [_data appendBytes:(const void *)buf length:len]; // bytesRead is an instance variable of type NSNumber. } else { NSLog(@"no buffer!"); } break; //Write data case NSStreamEventHasSpaceAvailable: break; case NSStreamEventErrorOccurred: break; case NSStreamEventEndEncountered: [aStream close]; [aStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; aStream = nil; // aStream is a pointer to avoid the generation of wild pointer. Null value is assigned here; break; default: break; } }
CocoaAsyncSocket
Create socket
Socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
Link server or middleware (Internet of things device intermediate control)
//Disconnect if (Socket.isConnected) { NSLog(@"Link is broken,Reopen link"); [Socket disconnect]; } //Of course, the company's ip and port can't be publicized. Please replace them with your own NSError *err = nil; if (![Socket connectToHost:@"123.155.118.167" onPort:4521 error:&err]) //Asynchronous! { //If there was an error, it's likely something like "already connected" or "no delegate set" NSLog(@"I goofed: %@", err); return; }else{ NSLog(@"Linking"); }
Execute proxy method - GCDAsyncSocketDelegate
#pragma mark-GCDAsyncSocketDelegate //Call after successful link server - (void)socket:(GCDAsyncSocket *)sender didConnectToHost:(NSString *)host port:(UInt16)port { NSLog(@"Link succeeded Cool, I'm connected! That was easy.%@",[NSThread currentThread]); //Send data to the server here NSString *testString = @"168353B1-6B6C-4EBD-891E-0B51D81BE166|1|DDEF2049-761A-45A0-9E77-EBF684C4B8F0"; NSString * lowerString =testString.lowercaseString; NSData *data = [lowerString dataUsingEncoding:NSUTF8StringEncoding]; //send data [Socket writeData:data withTimeout:-1 tag:1]; } //Disconnect from server call -(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{ NSLog(@"Broken link%@",[NSThread currentThread]); } //Call after sending data -(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{ NSLog(@"didWriteDataWithTag %@",[NSThread currentThread]); switch (tag) { case 1: NSLog(@"First write request issued"); //Read the server's return information (do not call this method and do not call the following method) [sock readDataWithTimeout:-1 tag:10 ]; break; case 2: NSLog(@"2nd write request issued"); break; default: NSLog(@"3rd write request issued"); break; } } //Server return data call -(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{ NSLog(@"didReadData %@",[NSThread currentThread]); if (receiveData == nil) { //If not, create a new receiveData = [[NSMutableData alloc] init]; } while(data){ [receiveData appendData:data];//Add the received data to the } [Socket readDataToData:data withTimeout:-1 tag:TAG_MSG]; NSLog(@"data %@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]); } // - (void)socketDidCloseReadStream:(GCDAsyncSocket *)sock{ NSLog(@"%s",__func__); [sock disconnect]; sock = nil; }
reference resources
Write it at the back
This article is mainly for sending data to the server and directly reading the content of the server, please refer to self change
——————————– write 3 / 21 / 2017 11:57
Reprint please indicate the website (yanqinglove.xyz)