├── Makefile ├── README.md ├── include ├── data.h ├── hyper-socket.h └── utils.h └── src ├── client.c ├── data.c ├── hyper-socket.c ├── receiver.c ├── server.c ├── stream.c └── utils.c /Makefile: -------------------------------------------------------------------------------- 1 | #libdata.dylib: include/utils.h include/data.h src/utils.c src/data.c 2 | # gcc -dynamiclib -o libdata.dylib -fPIC -I./include/ -dy src/utils.c src/data.c 3 | all: client server stream receiver 4 | 5 | stream: include/utils.h include/data.h include/hyper-socket.h libdata.so src/stream.c 6 | gcc -g -o stream -I./include/ -L. -ldata src/stream.c 7 | server: include/utils.h include/data.h include/hyper-socket.h libdata.so src/server.c 8 | gcc -o server -I./include/ -L. -ldata src/server.c 9 | receiver: include/utils.h include/hyper-socket.h libdata.so src/receiver.c 10 | gcc -o receiver -I./include -L. -ldata src/receiver.c 11 | client: include/utils.h include/hyper-socket.h libdata.so src/receiver.c 12 | gcc -o client -I./include -L. -ldata src/client.c 13 | libdata.so: include/utils.h include/data.h include/hyper-socket.h src/utils.c src/data.c src/hyper-socket.c 14 | gcc -shared -o libdata.so -fPIC -I./include/ src/utils.c src/hyper-socket.c src/data.c 15 | clean: 16 | rm -f libdata.so client server stream receiver 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hyper Socket 2 | 3 | **Note:** The project that this work supported has concluded. 4 | 5 | ## Purpose 6 | The purpose of this project was to write a network socket that would allow the transportation of TCP data at ~10Gb/s in order to support on-going research in distributed systems like Apache Spark, Apache Kafka, and Apache Mesos. 7 | 8 | ## Current Status 9 | This work concluded with approximately: 8Gb/s throughput from source to sink, which is close enough to the goal to support the research (see Supported Research). 10 | 11 | ## Supported Research 12 | This socket supported the following research projects: 13 | - High-Throughput Apache Spark Streaming 14 | - On GitHub (https://github.com/LeStarch/hyper-spark) 15 | - At Apache Con Europe (http://sched.co/400u) 16 | - High-Throughput Kafka and Kafka in HPC https://github.com/LeStarch/kafka-benchmarking 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /include/data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fs-buffer.h 3 | * 4 | * Created on: Jul 28, 2015 5 | * Author: lestarch 6 | */ 7 | 8 | #ifndef HYPER_SOCKET_INCLUDE_DATA_H_ 9 | #define HYPER_SOCKET_INCLUDE_DATA_H_ 10 | #define BLOCK_SIZE 65536ull 11 | /** 12 | * Data structure to hold data and metadata 13 | */ 14 | typedef struct { 15 | size_t size; 16 | unsigned char* buffer; 17 | } Data; 18 | 19 | //Function prototypes 20 | /** 21 | * Allocate a data object of given size 22 | * @param size - size of buffers 23 | * @return - data object 24 | */ 25 | Data* allocate(size_t size); 26 | /** 27 | * Deallocate data object 28 | * @param data - data object 29 | */ 30 | void deallocate(Data* data); 31 | /** 32 | * Load the data object from the given file 33 | * @param data - data object to load 34 | * @param file - file to read 35 | */ 36 | void load(Data* data, char* file); 37 | /** 38 | * Save the data object to given file 39 | * @param data - data object to save 40 | * @param file - file to save to 41 | */ 42 | void save(Data* data, char* file); 43 | /** 44 | * Save the data object to given file 45 | * @param data - data object to save 46 | * @param fd - file descriptor to save to 47 | */ 48 | void saveToFd(Data* data, int fd); 49 | /** 50 | * Buffer bytes of the given file in-memory. 51 | * @param file - path to file to buffer 52 | * @param size - size to buffer in memory 53 | * @return Data object 54 | */ 55 | Data* bufferBySize(char* file,size_t size); 56 | /** 57 | * Buffer the full contents of the given file in-memory. 58 | * @param file - path to file to buffer 59 | * @return Data object 60 | */ 61 | Data* buffer(char* file); 62 | 63 | #endif /* HYPER_SOCKET_INCLUDE_DATA_H_ */ 64 | -------------------------------------------------------------------------------- /include/hyper-socket.h: -------------------------------------------------------------------------------- 1 | /* 2 | * hyper-socket.h 3 | * 4 | * Created on: Jul 28, 2015 5 | * Author: lestarch 6 | */ 7 | 8 | #ifndef HYPER_SOCKET_INCLUDE_HYPER_SOCKET_H_ 9 | #define HYPER_SOCKET_INCLUDE_HYPER_SOCKET_H_ 10 | #define PORT 8089 11 | typedef enum { 12 | SERVER, 13 | CLIENT 14 | } Type; 15 | /** 16 | * Opens up an internet socket on geiven port 17 | * @param port - port number to open 18 | * @return socket descriptor 19 | */ 20 | int internet(short port,long address,Type type); 21 | /** 22 | * Accepts an incoming connection for the given port and returns the connection descriptor. 23 | * @return connection descriptor 24 | */ 25 | int establish(int sd); 26 | #endif /* HYPER_SOCKET_INCLUDE_HYPER_SOCKET_H_ */ 27 | -------------------------------------------------------------------------------- /include/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * utils.h 3 | * 4 | * Created on: Jul 28, 2015 5 | * Author: mstarch 6 | */ 7 | 8 | #ifndef HYPER_SOCKET_INCLUDE_UTILS_H_ 9 | #define HYPER_SOCKET_INCLUDE_UTILS_H_ 10 | /** 11 | * Finds minimum of two unsigned long longs 12 | * @param ull1 - first argument 13 | * @param ull2 - second argument 14 | * @return minimum of argument 1 and argument 2 15 | */ 16 | unsigned long long minll(unsigned long long m1, unsigned long long m2); 17 | /** 18 | * Malloc or fail 19 | * @param size - size of buffer 20 | @ @return void* to new buffer 21 | */ 22 | void* mallocf(size_t size); 23 | /** 24 | * Fail if equivalent 25 | * @param result - result to check 26 | * @param check - check value 27 | */ 28 | void fail(int result, int check, char* message); 29 | /** 30 | * Get the current time as a double in seconds since boot 31 | * @return seconds (double) 32 | */ 33 | double now(); 34 | #endif /* HYPER_SOCKET_INCLUDE_UTILS_H_ */ 35 | -------------------------------------------------------------------------------- /src/client.c: -------------------------------------------------------------------------------- 1 | /* 2 | * client.c 3 | * 4 | * Created on: Jul 29, 2015 5 | * Author: lestarch 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "hyper-socket.h" 16 | #include "utils.h" 17 | #include "data.h" 18 | 19 | //Globals for signal handling 20 | double start,end; 21 | int conn = -1; 22 | size_t total = 0; 23 | 24 | static void catch(int signo) { 25 | printf("Total %zu bytes in %f seconds or %fB/s\n",total,(end-start),total/(end-start)); 26 | close(conn); 27 | exit(0); 28 | } 29 | 30 | /** 31 | * Main program 32 | */ 33 | int main(int argc, char** argv) { 34 | int r = signal(SIGINT, catch) == SIG_ERR; 35 | fail(r,1,"Failed to register signal handler"); 36 | if (argc != 3 ) 37 | { 38 | printf("%s:\n\t\n",argv[0]); 39 | exit(-1); 40 | } 41 | short port = (short)atoi(argv[2]); 42 | char buffer[BLOCK_SIZE]; 43 | printf("Establishing connection to: %d\n",port); 44 | conn = internet(port,inet_addr(argv[1]),CLIENT); 45 | printf("Reading data from: %s:%d\n",argv[1],port); 46 | int ret = 1; 47 | start = now(); 48 | 49 | while (0 < ret) { 50 | sigset_t set,old; 51 | sigfillset(&set); 52 | sigprocmask(SIG_BLOCK,&set,&old); 53 | ret = read(conn,buffer,BLOCK_SIZE); 54 | total += ret; 55 | end = now(); 56 | sigprocmask(SIG_SETMASK,&old,NULL); 57 | } 58 | 59 | printf("Read %zu bytes in %f seconds or %fB/s\n",total,(end-start),total/(end-start)); 60 | close(conn); 61 | } 62 | -------------------------------------------------------------------------------- /src/data.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "utils.h" 9 | #include "data.h" 10 | /** 11 | * Allocate a data object of given size 12 | * @param size - size of buffers 13 | * @return - data object 14 | */ 15 | Data* allocate(size_t size) 16 | { 17 | printf("Creating data object of size %zu...",size); 18 | unsigned char* buffer = (unsigned char*)mallocf(size); 19 | Data* data = (Data*) mallocf(sizeof(Data)); 20 | data->size = size; 21 | data->buffer = buffer; 22 | printf("%s","\n"); 23 | return data; 24 | } 25 | /** 26 | * Deallocate data object 27 | * @param data - data object 28 | */ 29 | void deallocate(Data* data) 30 | { 31 | printf("%s\n","Releasing data object"); 32 | free(data->buffer); 33 | free(data); 34 | } 35 | /** 36 | * Load the data object from the given file 37 | * @param data - data object to load 38 | * @param file - file to read 39 | */ 40 | void load(Data* data, char* file) { 41 | int fd = open(file,O_RDONLY); 42 | fail(fd,-1,"Failed to open file for read"); 43 | size_t total = data->size; 44 | while (total > 0) 45 | { 46 | size_t tmp = read(fd,data->buffer+(data->size - total),minll(BLOCK_SIZE,total)); 47 | fail(tmp,-1,"Failed to read file"); 48 | total -= tmp; 49 | } 50 | close(fd); 51 | } 52 | /** 53 | * Save the data object to given file 54 | * @param data - data object to save 55 | * @param file - file to save to 56 | */ 57 | void save(Data* data, char* file) { 58 | int fd = open(file,O_WRONLY|O_CREAT); 59 | fail(fd,-1,"Failed to open file for write"); 60 | saveToFd(data,fd); 61 | close(fd); 62 | } 63 | /** 64 | * Save the data object to given file 65 | * @param data - data object to save 66 | * @param fd - file descriptor to save to 67 | */ 68 | void saveToFd(Data* data, int fd) { 69 | size_t total = data->size; 70 | while (total > 0) 71 | { 72 | size_t tmp = write(fd,data->buffer+(data->size - total),minll(BLOCK_SIZE,total)); 73 | fail(tmp,-1,"Failed to write file"); 74 | total -= tmp; 75 | } 76 | } 77 | /** 78 | * Buffer bytes of the given file in-memory. 79 | * @param file - path to file to buffer 80 | * @param size - size to buffer in memory 81 | * @return Data object 82 | */ 83 | Data* bufferBySize(char* file,size_t size) { 84 | Data* data = allocate(size); 85 | load(data,file); 86 | return data; 87 | } 88 | /** 89 | * Buffer the full contents of the given file in-memory. 90 | * @param file - path to file to buffer 91 | * @return Data object 92 | */ 93 | Data* buffer(char* file) { 94 | struct stat stats; 95 | int rt = stat(file,&stats); 96 | fail(rt,-1,"Failed get filesize to buffer"); 97 | if (stats.st_size == 0) 98 | { 99 | printf("Cannot buffer full contents of non-file device. Please specify size.\n"); 100 | exit(-1); 101 | } 102 | return bufferBySize(file,stats.st_size); 103 | } 104 | -------------------------------------------------------------------------------- /src/hyper-socket.c: -------------------------------------------------------------------------------- 1 | #include 2 | //#include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "hyper-socket.h" 10 | #include "utils.h" 11 | 12 | //#define TYPE AF_UNIX 13 | #define TYPE AF_INET 14 | 15 | 16 | /** 17 | * Opens up an internet socket on geiven port 18 | * @param port - port number to open 19 | * @return socket descriptor 20 | */ 21 | int internet(short port,long address,Type type) 22 | { 23 | //Get socket descriptor 24 | int sd = socket(TYPE,SOCK_STREAM,0); 25 | fail(sd,-1,"Failed to allocate socket"); 26 | //Setup an address (port) 27 | struct sockaddr_in addr; 28 | memset(&addr,0,sizeof(addr)); 29 | addr.sin_family = AF_INET; 30 | addr.sin_addr.s_addr = address; 31 | addr.sin_port = htons(port); 32 | //Bind to that address (port) 33 | if (type == SERVER) { 34 | int ret = bind(sd,(struct sockaddr*)&addr,sizeof(addr)); 35 | fail(ret,-1,"Failed to bind socket"); 36 | } else if (type == CLIENT) { 37 | int ret = connect(sd,(struct sockaddr*)&addr,sizeof(addr)); 38 | fail(ret,-1,"Failed to connect to socket"); 39 | } 40 | return sd; 41 | } 42 | /** 43 | * Accepts an incoming connection for the given port and returns the connection descriptor. 44 | * @return connection descriptor 45 | */ 46 | int establish(int sd) { 47 | int ret = listen(sd,0); 48 | fail(ret,-1,"Failed to listen on socket"); 49 | return accept(sd,NULL,NULL); 50 | } 51 | 52 | -------------------------------------------------------------------------------- /src/receiver.c: -------------------------------------------------------------------------------- 1 | /* 2 | * client.c 3 | * 4 | * Created on: Jul 29, 2015 5 | * Author: lestarch 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "hyper-socket.h" 16 | #include "utils.h" 17 | #include "data.h" 18 | 19 | //Globals for signal handling 20 | double start,end; 21 | int conn,list = -1; 22 | size_t total = 0; 23 | 24 | static void catch(int signo) { 25 | printf("Total %zu bytes in %f seconds or %fB/s\n",total,(end-start),total/(end-start)); 26 | close(conn); 27 | close(list); 28 | exit(0); 29 | } 30 | 31 | /** 32 | * Main program 33 | */ 34 | int main(int argc, char** argv) { 35 | int r = signal(SIGINT, catch) == SIG_ERR; 36 | fail(r,1,"Failed to register signal handler"); 37 | if (argc != 2) 38 | { 39 | printf("%s:\n\t\n",argv[0]); 40 | exit(-1); 41 | } 42 | short port = (short)atoi(argv[2]); 43 | char buffer[BLOCK_SIZE]; 44 | printf("Establishing connection to: %d\n",port); 45 | list = internet(port,htonl(INADDR_ANY),SERVER); 46 | printf("Establishing connection to: %d\n",port); 47 | conn = establish(list); 48 | printf("Reading data from: %s:%d\n",argv[1],port); 49 | int ret = 1; 50 | start = now(); 51 | 52 | while (0 < ret) { 53 | sigset_t set,old; 54 | sigfillset(&set); 55 | sigprocmask(SIG_BLOCK,&set,&old); 56 | ret = read(conn,buffer,BLOCK_SIZE); 57 | total += ret; 58 | end = now(); 59 | sigprocmask(SIG_SETMASK,&old,NULL); 60 | } 61 | 62 | printf("Read %zu bytes in %f seconds or %fB/s\n",total,(end-start),total/(end-start)); 63 | close(conn); 64 | close(list); 65 | } 66 | -------------------------------------------------------------------------------- /src/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "hyper-socket.h" 6 | #include "utils.h" 7 | #include "data.h" 8 | 9 | /** 10 | * Main program 11 | */ 12 | int main(int argc, char** argv) { 13 | size_t dsize = 10737418240ull; 14 | Data* data = NULL; 15 | if (argc < 2 || argc > 3) 16 | { 17 | printf("%s:\n\t [size]\n",argv[0]); 18 | exit(-1); 19 | } 20 | else if (argc == 3) 21 | { 22 | dsize = atol(argv[3]); 23 | fail(dsize,0,"Invalid length to read\n"); 24 | data = bufferBySize(argv[1],dsize); 25 | } 26 | else 27 | { 28 | data = buffer(argv[1]); 29 | } 30 | short port = PORT; 31 | printf("Establishing connection to: %d\n",port); 32 | int listen = internet(port,htonl(INADDR_ANY),SERVER); 33 | int conn = establish(listen); 34 | double start,end; 35 | printf("Saving %zu bytes to: %d\n",dsize,port); 36 | start = now(); 37 | saveToFd(data,conn); 38 | //write(conn,data->buffer,data->size); 39 | end = now(); 40 | printf("Written %zu bytes in %f seconds or %fB/s\n",data->size,(end-start),data->size/(end-start)); 41 | deallocate(data); 42 | close(conn); 43 | close(listen); 44 | } 45 | -------------------------------------------------------------------------------- /src/stream.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "hyper-socket.h" 8 | #include "utils.h" 9 | #include "data.h" 10 | //Globals for signal handling 11 | double start,end; 12 | Data* data; 13 | int conn = -1,list = -1; 14 | size_t total = 0; 15 | 16 | static void catch(int signo) { 17 | printf("Total %zu bytes in %f seconds or %fB/s\n",total,(end-start),total/(end-start)); 18 | deallocate(data); 19 | close(conn); 20 | close(list); 21 | exit(0); 22 | } 23 | 24 | /** 25 | * Main program 26 | */ 27 | int main(int argc, char** argv) { 28 | int ret = signal(SIGINT, catch) == SIG_ERR; 29 | fail(ret,1,"Failed to register signal handler"); 30 | size_t dsize = 10737418240ull; 31 | if (argc < 3 || argc > 4) 32 | { 33 | printf("%s:\n\t [size]\n",argv[0]); 34 | exit(-1); 35 | } 36 | else if (argc == 4) 37 | { 38 | dsize = atol(argv[3]); 39 | fail(dsize,0,"Invalid length to read\n"); 40 | data = bufferBySize(argv[1],dsize); 41 | } 42 | else 43 | { 44 | data = buffer(argv[1]); 45 | } 46 | short port = (short)atoi(argv[2]); 47 | list = internet(port,htonl(INADDR_ANY),SERVER); 48 | printf("Establishing connection to: %d\n",port); 49 | conn = establish(list); 50 | start = now(); 51 | total = 0; 52 | while (1) { 53 | double new; 54 | size_t tmp = 0; 55 | printf("Saving %zu bytes to: %d\n",dsize,port); 56 | new = now(); 57 | size_t unwritten = data->size; 58 | while (unwritten > 0) 59 | { 60 | sigset_t set,old; 61 | sigfillset(&set); 62 | sigprocmask(SIG_BLOCK,&set,&old); 63 | tmp = write(conn,data->buffer+(data->size - unwritten),minll(BLOCK_SIZE,unwritten)); 64 | if (tmp == -1) { 65 | end = now(); 66 | break; 67 | } 68 | unwritten -= tmp; 69 | total += tmp; 70 | end = now(); 71 | sigprocmask(SIG_SETMASK,&old,NULL); 72 | } 73 | //saveToFd(data,conn); 74 | //write(conn,data->buffer,data->size); 75 | printf("Written %zu bytes in %f seconds or %fB/s\n",(data->size - unwritten),(end-new),(data->size - unwritten)/(end-new)); 76 | if (tmp == -1) 77 | break; 78 | } 79 | printf("Total %zu bytes in %f seconds or %fB/s\n",(total),(end-start),total/(end-start)); 80 | } 81 | -------------------------------------------------------------------------------- /src/utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "utils.h" 9 | /** 10 | * Finds minimum of two unsigned long longs 11 | * @param ull1 - first argument 12 | * @param ull2 - second argument 13 | * @return minimum of argument 1 and argument 2 14 | */ 15 | unsigned long long minll(unsigned long long m1, unsigned long long m2) 16 | { 17 | return (m1 > m2)? m2: m1; 18 | } 19 | /** 20 | * Malloc or fail 21 | * @param size - size of buffer 22 | @ @return void* to new buffer 23 | */ 24 | void* mallocf(size_t size) 25 | { 26 | void* buff = NULL; 27 | int try = 3; 28 | printf("%s","allocating"); 29 | while (NULL == (buff = (void*)malloc(size))) 30 | { 31 | if (try-- <= 0) 32 | { 33 | printf("%s"," failed"); 34 | exit(-1); 35 | } 36 | printf("%s"," retry..."); 37 | } 38 | printf("%s"," done"); 39 | return buff; 40 | } 41 | /** 42 | * Fail if equivalent 43 | * @param result - result to check 44 | * @param check - check value 45 | */ 46 | void fail(int result, int check, char* message) 47 | { 48 | if (result != check) 49 | return; 50 | printf("%s with error %s\n",message,strerror(errno)); 51 | exit(-1); 52 | } 53 | /** 54 | * Get the current time as a double in seconds since boot 55 | * @return seconds (double) 56 | */ 57 | double now() 58 | { 59 | struct timeval tv; 60 | if (gettimeofday(&tv,NULL) != 0) 61 | return -1.0; 62 | double stamp = (double)tv.tv_sec; 63 | stamp += ((double)tv.tv_usec)/1000000.0; 64 | return stamp; 65 | } 66 | --------------------------------------------------------------------------------