I tested this code in macOS
//
// 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
//
// 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
// 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.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
No comments:
Post a Comment