Pages

Showing posts with label Socket. Show all posts
Showing posts with label Socket. Show all posts

Thursday, July 16, 2020

Simple BSD Socket Client Server Example for macOS iOS

Today I am going to share about a simple Client Server example I have been working on to clear my concepts of BSD Socket. You can work on high leven APIs like CFSocket, But sometimes you need the help of a pure socket. 

I tested this code in macOS

RCDBSDServer.h

//

//  RCDServer.h

//  HelloMacObj

//

//  Created by Razib Chandra Deb on 15/7/20.

//  Copyright © 2020 Razib Chandra Deb. All rights reserved.

//


#import <Foundation/Foundation.h>


NS_ASSUME_NONNULL_BEGIN


@interface RCDBSDServer : NSObject

-(BOOL) startOnPort:(int) port;

-(void) stop;

-(void) sendString: (NSString *) string;

-(void) readData:(int) length;

@end


NS_ASSUME_NONNULL_END



RCDBSDServer.mm


//

//  RCDServer.m

//  HelloMacObj

//

//  Created by Razib Chandra Deb on 15/7/20.

//  Copyright © 2020 Razib Chandra Deb. All rights reserved.

//


#import "RCDBSDServer.h"

#include <netdb.h>

#include <netinet/in.h>

#include <sys/ioctl.h>

#include <sys/un.h>

#include <err.h>

#include <fcntl.h>

#include <arpa/inet.h>

#import <objc/runtime.h>

/*

 

 https://www.tutorialspoint.com/unix_sockets/socket_server_example.htm

Create a socket with the socket() system call.


Bind the socket to an address using the bind() system call. For a server socket on the Internet, an address consists of a port number on the host machine.


Listen for connections with the listen() system call.


Accept a connection with the accept() system call. This call typically blocks until a client connects with the server.


Send and receive data using the read() and write() system calls.

*/

@implementation RCDBSDServer {

    int sockfd, portno, n, newSockFd;

    struct sockaddr serv_addr;

    struct hostent *server;

    

    struct sockaddr_in client_addr;

    socklen_t client_addr_len;

}



-(id) init {

    self = [super init];

    if ( self != nil) {

        

    }

    return self;

}


-(BOOL) startOnPort:(int) port {

    // Connect socket

    struct sockaddr_in addr;

    bzero((char *)&addr, sizeof(addr));

    

    addr.sin_family = AF_INET;

    addr.sin_port = htons(port);

    //addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    //addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

    

    socklen_t socklen = sizeof(addr);

    

    

    /* First call to socket() function */

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    

    if (sockfd < 0) {

        Log(@"[Server] socket creation failed");

        return NO;

    }

    

//    int on = 1;

//    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {

//        close(sockfd);

//        Log(@"Error on setsockopt");

//        return false;

//    }

//

//    if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == -1) {

//        close(sockfd);

//        Log(@"Error on fcntl");

//        return false;

//    }


    if (bind(sockfd, (struct sockaddr*)&addr, socklen) != 0) {

        close(sockfd);

        Log(@"Error on bind");

        return false;

    }

    

    /* Now start listening for the clients, here process will

       * go in sleep mode and will wait for the incoming connection

    */

    if (listen(sockfd, DATA_CHUNK) != 0) {

        close(sockfd);

        Log(@"Error on listen");

        return false;

    }

    else {

        Log(@"listen success");

    }

    

    client_addr_len = sizeof(client_addr);

    /* Accept actual connection from the client */

    newSockFd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addr_len);

     

    if (newSockFd < 0) {

       Log(@"ERROR on accept");

        return false;

    }

    

    /* If connection is established then start communicating */

  

    return true;

}

-(void) stop {

    close(sockfd);

}

-(void) sendString: (NSString *) string {

     const char * buffer = [string cStringUsingEncoding:NSUTF8StringEncoding];

     ssize_t n = write(newSockFd, buffer, (int) strlen(buffer));

     Log(@"[Server] Data sent %zd", n);

}

-(void) readData:(int) length {

    char data[DATA_CHUNK];

    

    memset(data, 0, DATA_CHUNK);

    ssize_t n = read(newSockFd, data, length);

    Log(@"[Server] Data read %zd Data \n%s\n", n, data);

}

@end




RCDBSDClient.h

//

//  RCDBSDClient.h

//  HelloMacObj

//

//  Created by Razib Chandra Deb on 15/7/20.

//  Copyright © 2020 Razib Chandra Deb. All rights reserved.

//


#import <Foundation/Foundation.h>


NS_ASSUME_NONNULL_BEGIN


@interface RCDBSDClient : NSObject

-(BOOL) connectToServerIp:(NSString *) ipAddres withPort:(int) port;

-(void) stop;

-(void) sendString: (NSString *) string;

-(void) readData:(int) length;

@end


NS_ASSUME_NONNULL_END



RCDBSDClient.mm

//

//  RCDBSDClient.m

//  HelloMacObj

//

//  Created by Razib Chandra Deb on 15/7/20.

//  Copyright © 2020 Razib Chandra Deb. All rights reserved.

//


#import "RCDBSDClient.h"

#include <netdb.h>

#include <netinet/in.h>

#include <sys/ioctl.h>

#include <sys/un.h>

#include <err.h>

#include <fcntl.h>

#include <arpa/inet.h>


/*

 https://www.tutorialspoint.com/unix_sockets/socket_client_example.htm

 Create a socket with the socket() system call.


 Connect the socket to the address of the server using the connect() system call.


 Send and receive data. There are a number of ways to do this, but the simplest way is to use the read() and write() system calls.

 */


@implementation RCDBSDClient {

    int sockfd, portno, n;

    struct sockaddr serv_addr;

    struct hostent *client;

}


-(id) init {

    self = [super init];

    if ( self != nil) {

        

    }

    return self;

}



-(BOOL) connectToServerIp:(NSString *) ipAddres withPort:(int) port {

    

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if (sockfd == -1) {

        Log(@"Error on socket");

        return NO;

    }

    

    // prevent SIGPIPE

    int on = 1;

    setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));

    

    struct hostent *serverAddres = gethostbyname([ipAddres cStringUsingEncoding:NSUTF8StringEncoding]);

    

    // Connect socket

    struct sockaddr_in addr;


    

    bzero((char *) &addr, sizeof(addr));

    addr.sin_family = AF_INET;

    bcopy((char *)serverAddres->h_addr, (char *)&addr.sin_addr.s_addr, serverAddres->h_length);

    addr.sin_port = htons(port);

    

    socklen_t socklen = sizeof(addr);

    if (connect(sockfd, (struct sockaddr*)&addr, socklen) == -1) {

        Log(@"Error on connect");

        return NO;

    }

    

    Log(@"Connection Success");

    

    return true;

}

-(void) stop {

    close(sockfd);

}

-(void) sendString: (NSString *) string {

    const char * buffer = [string cStringUsingEncoding:NSUTF8StringEncoding];

    ssize_t n = write(sockfd, buffer, (int) strlen(buffer));

    Log(@"[Client] Data sent %zd", n);

}

-(void) readData:(int) length {

    char data[DATA_CHUNK];

    memset(data, 0, DATA_CHUNK);

    ssize_t n = read(sockfd, data, length);

    Log(@"[Client] Data read %zd Data \n%s\n", n, data);

}

@end




Please feel free to share your thoughts.