Large File Transfer using Objective-C ( XCode )

This video shows how to code an Objective-C application to transfer Large file in small chunks.

Mac OS X Version: 10.10.5
Xcode Version: 7.1.1

Enjoy!!!
don’t forget to subscribe on YouTube as more code coming.

Watch above video, configure your project and use 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 NSProgressIndicator *b_upload;
    
}
- (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];
    [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->tx_recv=b_upload;
    [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]];
    dispatch_async(dispatch_get_main_queue(), ^{
        NSOpenPanel *opendlg=[NSOpenPanel openPanel];
        [opendlg setCanChooseFiles:TRUE];
        [opendlg beginWithCompletionHandler:^(NSInteger result) {
            if(result==NSFileHandlingPanelOKButton){
                obj_client_thread->rf=[NSFileHandle fileHandleForReadingAtPath:[[opendlg URL] path]];
                obj_client_thread->file_length=[obj_client_thread->rf seekToEndOfFile];
                NSString *data=[[[opendlg URL] path] lastPathComponent];
                [obj_client_thread SendTCPDataPacket:[@"123" UTF8String] data_to_send:[data UTF8String] data_length:[data length]];
            }
        }];
    });
}
@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
    
}

-(void)initializeServer;
-(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{
    
    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:
        {
            
            ClientThread *obj_accepted_socket=[[ClientThread alloc]init];
            [obj_accepted_socket InitializeNative:*(CFSocketNativeHandle*)data];
            
            [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
    NSProgressIndicator* tx_recv;
    NSFileHandle *rf;
    long file_pointer;
    long file_length;
}

-(void)InitializeClient;
-(void)InitializeNative:(CFSocketNativeHandle) native_socket;
-(void)main;

-(void)DisconnectFromServer;
-(void)SendTCPDataPacket:(const char *)cmd data_to_send:(const char*) data data_length:(long)target_data_length;
-(char*)ReadData:(int*)recv_data_length;
@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|kCFSocketReadCallBack, 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 *)cmd data_to_send:(const char*) data data_length:(long)target_data_length
{
    int initialize[1]={2};//initialize
    int separator[1]={4};
    
    int target_length=snprintf(NULL, 0, "%ld",target_data_length);
    char* data_length_char=malloc(target_length+1);
    snprintf(data_length_char, target_length+1, "%ld",target_data_length);// this line of code convert (45 into "45")
    
    int ele_count=(int)strlen(data_length_char);
    
    
    long packet_length= 1+strlen(cmd)+ele_count+1+target_data_length;
    
    UInt8 *packet=(UInt8*)malloc(packet_length * sizeof(UInt8));
    
    memcpy(&packet[0], initialize, 1);
    memcpy(&packet[0+1], cmd, strlen(cmd));
  
    memcpy(&packet[0+1+strlen(cmd)],data_length_char , ele_count);
    
    
    memcpy(&packet[0+1+strlen(cmd)+ele_count], separator, 1);
    memcpy(&packet[0+1+strlen(cmd)+ele_count+1], data, target_data_length);
    CFDataRef dref=CFDataCreate(kCFAllocatorDefault, packet, packet_length);
    CFSocketSendData(obj_client, NULL, dref, -1);
    free(packet);
    free(data_length_char);
    CFRelease(dref);
    
}
-(void)InitializeNative:(CFSocketNativeHandle) native_socket{
   
    CFSocketContext sctx={0,(__bridge void *)(self),NULL,NULL,NULL};
    obj_client=CFSocketCreateWithNative(kCFAllocatorDefault, native_socket, kCFSocketReadCallBack, TCPClientCallBackHandler, &sctx);
}
-(char*)ReadData:(int*)recv_data_length{
    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];
    *recv_data_length=data_length;
    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 cmd[3];
                read(CFSocketGetNative(s), &cmd, 3 );
                int iCmd;
                int irecv_data_length;
                sscanf(cmd, "%d",&iCmd);
                char *recv_data=[obj_client_ptr ReadData:&irecv_data_length];
                //[obj_client_ptr->tx_recv setStringValue:[NSString stringWithUTF8String:recv_data]];
                switch (iCmd) {
                    case 123://server side
                    {
                        NSFileManager *fmng=[NSFileManager defaultManager];
                        [fmng createFileAtPath:[NSString stringWithFormat:@"/Users/rahulsnippet/Documents/%s",recv_data] contents:nil attributes:nil ];
                        obj_client_ptr->rf=[NSFileHandle fileHandleForWritingAtPath:[NSString stringWithFormat:@"/Users/rahulsnippet/Documents/%s",recv_data] ];
                        obj_client_ptr->file_pointer=0;
                        int target_length=snprintf(NULL, 0, "%ld",obj_client_ptr->file_pointer);
                        char* data_length_char=malloc(target_length+1);
                        snprintf(data_length_char, target_length+1, "%ld",obj_client_ptr->file_pointer);
                        [obj_client_ptr SendTCPDataPacket:[@"124" UTF8String] data_to_send:data_length_char data_length:strlen(data_length_char)];
                        
                    }
                        break;
                    case 124://client side
                    {
                        sscanf(recv_data, "%ld",&obj_client_ptr->file_pointer);
                        if(obj_client_ptr->file_pointer!=obj_client_ptr->file_length){
                            [obj_client_ptr->rf seekToFileOffset:obj_client_ptr->file_pointer];
                            long chunck_size=obj_client_ptr->file_length-obj_client_ptr->file_pointer<20000?obj_client_ptr->file_length-obj_client_ptr->file_pointer:20000;
                            ;
                            [obj_client_ptr SendTCPDataPacket:[@"125" UTF8String] data_to_send:[[obj_client_ptr->rf readDataOfLength:chunck_size] bytes] data_length:chunck_size];
                            [obj_client_ptr->tx_recv setDoubleValue:((double)obj_client_ptr->file_pointer+chunck_size/(double)obj_client_ptr->file_length)*100];
                            [obj_client_ptr->tx_recv setNeedsDisplay:YES];
                        }
                        else{
                            [obj_client_ptr SendTCPDataPacket:[@"126" UTF8String] data_to_send:[@"Close" UTF8String] data_length:5];
                            [obj_client_ptr->rf closeFile];
                            obj_client_ptr->rf=nil;
                        }
                        
                    }break;
                    case 125:
                    {
                        [obj_client_ptr->rf seekToFileOffset:obj_client_ptr->file_pointer];
                        [obj_client_ptr->rf writeData:[NSData dataWithBytes:recv_data length:irecv_data_length]];
                        obj_client_ptr->file_pointer=[obj_client_ptr->rf offsetInFile];
                        int target_length=snprintf(NULL, 0, "%ld",obj_client_ptr->file_pointer);
                        char* data_length_char=malloc(target_length+1);
                        snprintf(data_length_char, target_length+1, "%ld",obj_client_ptr->file_pointer);
                        [obj_client_ptr SendTCPDataPacket:[@"124" UTF8String] data_to_send:data_length_char data_length:strlen(data_length_char)];
                        free(data_length_char);
                    }
                        break;
                    case 126:
                    {
                        [obj_client_ptr->rf closeFile];
                        obj_client_ptr->rf=nil;
                    }
                        break;
                        
                    default:
                        break;
                }
                free(recv_data);
            }
        }
            break;
        
        default:
            break;
    }
}
@end

You may also like...