TCP Socket: Data Transfer without Single Byte loss using Objective-C(XCode)
This clip shows how to transfer data over TCP socket without single byte loss using Objective-C, Cocoa Framework, XCode
Enjoy!!!
don’t forget to subscribe on youtube as more code comming.
watch video and configure your project and used below code
GUIHandler.h
//
// GUIHandler.h
// TCPDataTransfer
//
// Created by Rahul Yadav on 30/12/15.
// Copyright © 2015 Rahul Yadav. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import "ServerThread.h"
#import "ClientThread.h"
@interface GUIHandler : NSObject{
ServerThread *obj_server_thread;
ClientThread *obj_client_thread;
@public
__weak IBOutlet NSTextField *tx_send_data;
__weak IBOutlet NSTextField *tx_recv_data;
}
- (IBAction)StartServerNow:(id)sender;
- (IBAction)StopServerNow:(id)sender;
- (IBAction)ConnectToServerNow:(id)sender;
- (IBAction)DisconnectFromServer:(id)sender;
- (IBAction)SendDataToServer:(id)sender;
@end
GUIHandler.m
//
// GUIHandler.m
// TCPDataTransfer
//
// Created by Rahul Yadav on 30/12/15.
// Copyright © 2015 Rahul Yadav. All rights reserved.
//
#import "GUIHandler.h"
@implementation GUIHandler
- (IBAction)StartServerNow:(id)sender {
obj_server_thread=[[ServerThread alloc]init];
[obj_server_thread initializeServer:tx_recv_data];
[obj_server_thread start];
}
- (IBAction)StopServerNow:(id)sender {
[obj_server_thread StopServer];
[obj_server_thread cancel];
}
- (IBAction)ConnectToServerNow:(id)sender {
obj_client_thread=[[ClientThread alloc]init];
[obj_client_thread InitializeClient];
[obj_client_thread start];
}
- (IBAction)DisconnectFromServer:(id)sender {
[obj_client_thread DisconnectFromServer];
[obj_client_thread cancel];
}
- (IBAction)SendDataToServer:(id)sender {
[obj_client_thread SendTCPDataPacket:[[tx_send_data stringValue]UTF8String]];
}
@end
ServerThread.h
//
// ServerThread.h
// TCPDataTransfer
//
// Created by Rahul Yadav on 30/12/15.
// Copyright © 2015 Rahul Yadav. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#include <sys/socket.h>
#include <netinet/in.h>
@interface ServerThread : NSThread
{
CFSocketRef obj_server;
@public
NSTextField *tx_recv;
}
-(void)initializeServer:(NSTextField *) target_text_field;
-(void)main;
-(void)StopServer;
@end
ServerThread.m
//
// ServerThread.m
// TCPDataTransfer
//
// Created by Rahul Yadav on 30/12/15.
// Copyright © 2015 Rahul Yadav. All rights reserved.
//
#import "ServerThread.h"
#import "ClientThread.h"
@implementation ServerThread
-(void)initializeServer:(NSTextField *) target_text_field{
tx_recv=target_text_field;
CFSocketContext sctx={0,(__bridge void *)(self),NULL,NULL,NULL};
obj_server=CFSocketCreate(kCFAllocatorDefault, AF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, TCPServerCallBackHandler, &sctx);
int so_reuse_flag=1;
setsockopt(CFSocketGetNative(obj_server), SOL_SOCKET, SO_REUSEADDR, &so_reuse_flag, sizeof(so_reuse_flag));
setsockopt(CFSocketGetNative(obj_server), SOL_SOCKET, SO_REUSEPORT, &so_reuse_flag, sizeof(so_reuse_flag));
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_len=sizeof(sock_addr);
sock_addr.sin_family=AF_INET;
sock_addr.sin_port=htons(6658);
sock_addr.sin_addr.s_addr=INADDR_ANY;
CFDataRef dref=CFDataCreate(kCFAllocatorDefault, (UInt8*)&sock_addr, sizeof(sock_addr));
CFSocketSetAddress(obj_server, dref);
CFRelease(dref);
}
-(void)main{
CFRunLoopSourceRef loopref=CFSocketCreateRunLoopSource(kCFAllocatorDefault, obj_server, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), loopref, kCFRunLoopDefaultMode);
CFRelease(loopref);
CFRunLoopRun();
}
-(void)StopServer{
CFSocketInvalidate(obj_server);
CFRelease(obj_server);
CFRunLoopStop(CFRunLoopGetCurrent());
}
void TCPServerCallBackHandler(CFSocketRef s, CFSocketCallBackType callbacktype,CFDataRef address, const void *data,void *info){
switch (callbacktype) {
case kCFSocketAcceptCallBack:
{
ServerThread * obj_server_ptr=(__bridge ServerThread *)info;
ClientThread *obj_accepted_socket=[[ClientThread alloc]init];
[obj_accepted_socket InitializeNative:*(CFSocketNativeHandle*)data showRecvData:obj_server_ptr->tx_recv];
[obj_accepted_socket start];
}
break;
default:
break;
}
}
@end
ClientThread.h
//
// ClientThread.h
// TCPDataTransfer
//
// Created by Rahul Yadav on 30/12/15.
// Copyright © 2015 Rahul Yadav. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@interface ClientThread : NSThread{
CFSocketRef obj_client;
@public
NSTextField* tx_recv;
}
-(void)InitializeClient;
-(void)InitializeNative:(CFSocketNativeHandle) native_socket showRecvData:(NSTextField *) target_text_field;
-(void)main;
-(void)DisconnectFromServer;
-(void)SendTCPDataPacket:(const char*) data;
-(char*)ReadData;
@end
ClientThread.m
//
// ClientThread.m
// TCPDataTransfer
//
// Created by Rahul Yadav on 30/12/15.
// Copyright © 2015 Rahul Yadav. All rights reserved.
//
#import "ClientThread.h"
@implementation ClientThread
-(void)InitializeClient{
CFSocketContext sctx={0,(__bridge void *)(self),NULL,NULL,NULL};
obj_client=CFSocketCreate(kCFAllocatorDefault, AF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketConnectCallBack, TCPClientCallBackHandler, &sctx);
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_len=sizeof(sock_addr);
sock_addr.sin_family=AF_INET;
sock_addr.sin_port=htons(6658);
inet_pton(AF_INET, "127.0.0.1", &sock_addr.sin_addr);
CFDataRef dref=CFDataCreate(kCFAllocatorDefault, (UInt8*)&sock_addr, sizeof(sock_addr));
CFSocketConnectToAddress(obj_client, dref, -1);
CFRelease(dref);
}
-(void)main{
CFRunLoopSourceRef loopref=CFSocketCreateRunLoopSource(kCFAllocatorDefault, obj_client, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), loopref, kCFRunLoopDefaultMode);
CFRelease(loopref);
CFRunLoopRun();
}
-(void)DisconnectFromServer{
CFSocketInvalidate(obj_client);
CFRelease(obj_client);
CFRunLoopStop(CFRunLoopGetCurrent());
}
-(void)SendTCPDataPacket:(const char*) data
{
int initialize[1]={2};//initialize
int separator[1]={4};
int data_length=(int)strlen(data);
int target_length=snprintf(NULL, 0, "%d",data_length);
char* data_length_char=malloc(target_length+1);
snprintf(data_length_char, target_length+1, "%d",data_length);// this line of code convert (45 into "45")
int ele_count=(int)strlen(data_length_char);
int *size_buff=(int*)malloc(ele_count*sizeof(int));
for (int counter=0; counter<ele_count; counter++) {
size_buff[counter]=(int)data_length_char[counter];
}
int packet_length= 1+1+ele_count+(int)strlen(data);
UInt8 *packet=(UInt8*)malloc(packet_length * sizeof(UInt8));
memcpy(&packet[0], initialize, 1);
for (int counter=0; counter<ele_count; counter++) {
memcpy(&packet[counter+1], &size_buff[counter], 1);
}
memcpy(&packet[0+1+ele_count], separator, 1);
memcpy(&packet[0+1+ele_count+1], data, strlen(data));
CFDataRef dref=CFDataCreate(kCFAllocatorDefault, packet, packet_length);
CFSocketSendData(obj_client, NULL, dref, -1);
free(packet);
free(size_buff);
free(data_length_char);
CFRelease(dref);
}
-(void)InitializeNative:(CFSocketNativeHandle) native_socket showRecvData:(NSTextField *) target_text_field{
tx_recv=target_text_field;
CFSocketContext sctx={0,(__bridge void *)(self),NULL,NULL,NULL};
obj_client=CFSocketCreateWithNative(kCFAllocatorDefault, native_socket, kCFSocketReadCallBack, TCPClientCallBackHandler, &sctx);
}
-(char*)ReadData{
char *data_buff;
NSMutableString *buff_length=[[NSMutableString alloc]init];
char buf[1];
read(CFSocketGetNative(obj_client), &buf, 1 );
while ((int)*buf!=4) {
[buff_length appendFormat:@"%c", (char)(int)*buf];
read(CFSocketGetNative(obj_client), &buf, 1 );
}
int data_length=[[buff_length stringByTrimmingCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet]invertedSet]]intValue];
data_buff=(char*)malloc(data_length*sizeof(char));
ssize_t byte_read=0;
ssize_t byte_offset=0;
while (byte_offset<data_length) {
byte_read=read(CFSocketGetNative(obj_client), data_buff+byte_offset, 50);
byte_offset+=byte_read;
}
return data_buff;
}
void TCPClientCallBackHandler(CFSocketRef s, CFSocketCallBackType callbacktype,CFDataRef address, const void *data,void *info){
switch (callbacktype) {
case kCFSocketConnectCallBack:
if(data){
CFSocketInvalidate(s);
CFRelease(s);
CFRunLoopStop(CFRunLoopGetCurrent());
}
else{
NSLog(@"Client Connected to Server");
}
break;
case kCFSocketReadCallBack:{
char buf[1];
read(CFSocketGetNative(s), &buf, 1 );
if((int)*buf==2){
ClientThread * obj_client_ptr=(__bridge ClientThread*) info;
char *recv_data=[obj_client_ptr ReadData];
[obj_client_ptr->tx_recv setStringValue:[NSString stringWithUTF8String:recv_data]];
free(recv_data);
}
}
break;
default:
break;
}
}
@end