Created
August 4, 2020 07:28
-
-
Save databoose/85f0d7592bf43676428392e1cf3702c4 to your computer and use it in GitHub Desktop.
server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <arpa/inet.h> | |
#include <netinet/in.h> | |
#include <pthread.h> | |
#include <stdbool.h> | |
#define SA struct sockaddr // cast shortener | |
#define SERVER_TICKRATE 300 // every 300ms is a tick | |
#define SERVER_BACKLOG 50 // max 50 clients in queue | |
#define TIMEOUT_IN 16 | |
#define TIMEOUT_OUT 16 | |
int servsockfd; // global so we can pass it around functions | |
int usleep(__useconds_t usec); // millisecond sleep | |
pid_t self_pid; | |
char cmd_str[26]; | |
int lengthofchar(char* tempstring) | |
{ | |
int cnt; | |
int charcount; | |
charcount = 0; | |
for(cnt=0; tempstring[cnt]; cnt++) { | |
if(tempstring[cnt] != ' ') { | |
charcount++; | |
} | |
} | |
return charcount; | |
} | |
void set_timeout(int servsockfd, int timeout_input_seconds, int timeout_output_seconds) | |
{ | |
/* | |
Setting options : | |
- SO_RCVTIMO, to set timeout for input operations | |
- SO_SNDTIMEO, to set timeout for output operations | |
*/ | |
struct timeval timeout; | |
timeout.tv_usec = 0; | |
timeout.tv_sec = 0; | |
timeout.tv_sec = timeout_input_seconds; | |
if (setsockopt(servsockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0) { | |
printf("setsockopt so_rcvtimeo unsuccessful : %s (Error code %d)\n", strerror(errno), errno); | |
} | |
else | |
{ | |
timeout.tv_sec = timeout_output_seconds; | |
if (setsockopt(servsockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0) { | |
printf("setsockopt so_sndtimo unsuccessful : %s (Error code %d)\n", strerror(errno), errno); | |
} | |
} | |
//printf("Timeout set\n"); | |
} | |
void handle_connection(void* p_clisock) // thread functions need to be a void pointer, and they need to accept any arg variable as a void pointer as well | |
{ | |
printf("Thread ID : %ld (",(pthread_self() / 100000)); | |
printf("Thread count : "); | |
int sysret = system(cmd_str); // it should print here, but somehow prints before? | |
if(sysret == -1) { | |
printf("system() (getting thread count) unsuccessful : %s (Error code %d)\n", strerror(errno), errno); | |
} | |
set_timeout(servsockfd,TIMEOUT_IN,TIMEOUT_OUT); | |
/* | |
for(int i = 0; i < 10; i++) { | |
printf("(Job %ld) : ", (pthread_self() / 1000000)); | |
printf("%d\n", i); | |
sleep(2); | |
} | |
*/ | |
int clisock = *((int*)p_clisock); | |
free (p_clisock); // we don't need the pointer anymore. | |
char *verif_recv_str = "Ar4#8Pzw<&M00Nk"; | |
char verif_send_str[110] = "4Ex{Y**y8wOh!T00"; | |
char recv_buf[110]; | |
int recv_status; | |
recv_status = recv(clisock, (void *)recv_buf, (size_t)sizeof(recv_buf), 0); | |
if (recv_status == -1) { | |
printf("Error reading from socket : %s\n", strerror(errno)); | |
printf("%s (%d) \n",strerror(errno),errno); | |
close(clisock); | |
pthread_exit(0); | |
} | |
printf("\nWaiting for verification string from client ... \n"); | |
if (strcmp(verif_recv_str, recv_buf) == 0) | |
{ | |
printf("[VERIFY SUCCESS] Verification string \"%s\" received\n", verif_recv_str); | |
memset(&recv_buf[0], '\0', sizeof(recv_buf)); | |
int send_status; | |
send_status = send(clisock, (void *)verif_send_str, (size_t)lengthofchar(verif_send_str), 0); | |
if (send_status == -1) { | |
printf("Error writing to socket : "); | |
printf("%s (Error code %d) \n",strerror(errno),errno); | |
close(clisock); | |
pthread_exit(0); | |
} | |
} | |
close(clisock); | |
pthread_exit(0); | |
} | |
int main() { | |
self_pid = getpid(); | |
sprintf(cmd_str, "ps hH p %d | wc -l\n", self_pid); | |
servsockfd = socket(AF_INET, SOCK_STREAM, 0); | |
struct sockaddr_in serv_addr; | |
struct sockaddr_in cli_addr; | |
serv_addr.sin_family = AF_INET; | |
serv_addr.sin_port = htons(64912); | |
serv_addr.sin_addr.s_addr = inet_addr("10.0.0.224"); | |
memset(&cli_addr, 0, sizeof(struct sockaddr_in)); //initializing cli_addr struct | |
if (setsockopt(servsockfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) { | |
printf("setsockopt so_reuseaddr unsuccessful : %s (Error code %d)\n", strerror(errno), errno); | |
} | |
printf("Set reuse\n"); | |
printf("Binding...\n"); | |
int bind_status; | |
bind_status = bind(servsockfd, (SA*)&serv_addr, sizeof(serv_addr)); | |
if (bind_status == -1) { | |
printf("Bind unsuccessful : %s (Error code %d)\n", strerror(errno), errno); | |
if (errno == 98) { | |
printf("More than one process running maybe?\n"); | |
exit(0); | |
} | |
} | |
int listen_status; | |
printf("Listening...\n"); | |
listen_status = listen(servsockfd, SERVER_BACKLOG); // second param is backlog, aka how many connections can wait in one point in time | |
if (listen_status == -1) { | |
printf("Listen unsuccessful : %s (Error code %d)\n", strerror(errno), errno); | |
} | |
for (;;) { | |
usleep(SERVER_TICKRATE); | |
int clisock; | |
socklen_t cli_addr_size = sizeof(cli_addr); | |
clisock = accept(servsockfd, (SA*)&cli_addr, &cli_addr_size); // last two parameters should fill an optionable client struct for info | |
if (clisock >= 0) { | |
printf("\n"); | |
printf("Connection accepted from : %s:%d\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)); | |
pthread_t sckthread; | |
int *pclient = malloc(sizeof(int)); | |
*pclient = clisock; | |
pthread_create(&sckthread, NULL, (void *)handle_connection, pclient); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment