From d98f46ce647846b0aa30b2e16a30fd4e152a1bf5 Mon Sep 17 00:00:00 2001 From: Carlos Maiolino Date: Thu, 10 Jul 2025 22:55:07 +0200 Subject: Add new code Signed-off-by: Carlos Maiolino --- C/netCode/.gitignore | 2 + C/netCode/client.c | 66 +++++++++++++++++ C/netCode/server.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++ C/netCode/types.h | 26 +++++++ 4 files changed, 296 insertions(+) create mode 100644 C/netCode/.gitignore create mode 100644 C/netCode/client.c create mode 100644 C/netCode/server.c create mode 100644 C/netCode/types.h (limited to 'C/netCode') diff --git a/C/netCode/.gitignore b/C/netCode/.gitignore new file mode 100644 index 0000000..f2ad853 --- /dev/null +++ b/C/netCode/.gitignore @@ -0,0 +1,2 @@ +client +server diff --git a/C/netCode/client.c b/C/netCode/client.c new file mode 100644 index 0000000..dafd1e8 --- /dev/null +++ b/C/netCode/client.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "types.h" + +void handle_client(int fd) +{ + char buf[4096] = {0}; + int *data; + proto_hdr_t *hdr = (proto_hdr_t*)buf; + + + read(fd, buf, sizeof(proto_hdr_t) + sizeof(int)); + + hdr->type = ntohl(hdr->type); + hdr->len = ntohs(hdr->len); + + data = (int *)&hdr[1]; + *data = ntohl(*data); + + if (hdr->type != PROTO_HELLO) + printf("Protocol mismatch\n"); + + if (*data != 1) + printf("Protocol version mismatch\n"); + + printf("Client connected - proto: %d ver: %d payload: %d\n", + hdr->type, hdr->len, *data); +} + +int main(int argc, char *argv[]) +{ + int err; + struct sockaddr_in serverInfo = {0}; + int fd = socket(AF_INET, SOCK_STREAM, 0); + + if (argc != 2) { + printf("Usage: ./client \n"); + exit(1); + } + + serverInfo.sin_family = AF_INET; + serverInfo.sin_addr.s_addr = inet_addr(argv[1]);; + serverInfo.sin_port = htons(SERVER_PORT); + + if (fd < 0) { + perror("socket"); + exit(1); + } + + err = connect(fd, (struct sockaddr*)&serverInfo, sizeof(serverInfo)); + if (err < 0) { + perror("connect"); + close(fd); + exit(1); + } + + handle_client(fd); + close(fd); + return 0; +} diff --git a/C/netCode/server.c b/C/netCode/server.c new file mode 100644 index 0000000..0b951eb --- /dev/null +++ b/C/netCode/server.c @@ -0,0 +1,202 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "types.h" + +clientstate_t clientStates[MAX_CLIENTS]; + +void init_clients(void) { + int i; + + for (i = 0; i < MAX_CLIENTS; i++) { + /* -1 means client slot is free */ + clientStates[i].fd = -1; + clientStates[i].state = STATE_NEW; + memset(&clientStates[i].buffer, 0, BUF_SIZE); + } +} + +int find_free_client(void) { + int i = 0; + + for (i = 0; i < MAX_CLIENTS; i++) + if (clientStates[i].fd == -1) + return i; + + return -1; +} + +int find_slot_by_fd(int fd) +{ + int i; + for (i = 0; i < MAX_CLIENTS; i++) { + if (clientStates[i].fd == fd) + return i; + } + return -1; +} + +void handle_client(int fd) +{ + char buf[4096] = {0}; + proto_hdr_t *hdr = (proto_hdr_t*)buf; + int *data; + int reallen; + + hdr->type = htonl(PROTO_HELLO); + reallen = sizeof(int); + hdr->len = htons(reallen); + + data = (int *)&hdr[1]; + *data = htonl(1); + + printf("hdr_ptr: %p data_ptr: %p\n", hdr, data); + write(fd, hdr, sizeof(proto_hdr_t) + reallen); + +} + + +int main(void) +{ + int err; + int listen_fd, conn_fd, nfds, freeSlot; + struct sockaddr_in serverInfo = {0}; + struct sockaddr_in clientInfo = {0}; + socklen_t csize; + int opt = 1; + + struct pollfd fds[MAX_CLIENTS + 1]; + + memset(fds, 9, sizeof(fds)); + serverInfo.sin_family = AF_INET; + serverInfo.sin_addr.s_addr = 0; /* bind to all IPs */ + serverInfo.sin_port = htons(SERVER_PORT); + + init_clients(); + + listen_fd = socket(AF_INET, SOCK_STREAM, 0); + if (listen_fd < 0) { + perror("socket"); + exit(1); + } + + err = bind(listen_fd, + (struct sockaddr *)&serverInfo, + sizeof(serverInfo)); + + if (err < 0) { + perror("bind"); + close(listen_fd); + exit(1); + } + + err = listen(listen_fd, 0); + if (err < 0) { + perror("listen"); + close(listen_fd); + exit(1); + } + + if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) { + perror("setsockopt"); + close(listen_fd); + exit(1); + } + + printf("Server listening to port: %d\n", SERVER_PORT); + + csize = sizeof(clientInfo); + + fds[0].fd = listen_fd; + fds[0].events = POLLIN; + nfds = 1; + + while (1) { + int i, j; + int nevents; + + /* fds is initialized with MAX_CLIENTS + 1 */ + for (i = 0, j = 1; i < MAX_CLIENTS; i++, j++) { + if (clientStates[i].fd != -1) { + /* Add open fd to the poll */ + fds[j].fd = clientStates[i].fd; + fds[j].events = POLLIN; + printf("FD %d added to poll\n", clientStates[i].fd); + } + } + + nevents = poll(fds, nfds, -1); + + if (nevents == -1) { + perror("poll"); + exit(1); + } + + /* if listen_fd is ready, accept it */ + if (fds[0].revents & POLLIN) { + conn_fd = accept(listen_fd, + (struct sockaddr*)&clientInfo, + &csize); + + if (conn_fd < 0) { + perror("accept"); + continue; + } + + printf("New connection from: %s:%d\n", + inet_ntoa(clientInfo.sin_addr), + ntohs(clientInfo.sin_port)); + + freeSlot = find_free_client(); + if (freeSlot < 0) { + printf("Server full - closing connection\n"); + close(conn_fd); + } else { + clientStates[freeSlot].fd = conn_fd; + clientStates[freeSlot].state = STATE_CONNECTED; + nfds++; + printf("Adding fd %d to slot %d\n", + conn_fd, freeSlot); + } + nevents--; + } + + printf("NFDS: %d\n", nfds); + for (i = 1; i <= nfds && nevents > 0; i++) { + int fd, slot; + ssize_t bytes_read; + + if (fds[i].revents & POLLIN) { + nevents--; + + fd = fds[i].fd; + slot = find_slot_by_fd(fd); + bytes_read = read(fd, + &clientStates[slot].buffer, + sizeof(clientStates[slot].buffer)); + if (bytes_read <= 0) { + close(fd); + printf("Connection error\n"); + if (slot == -1) { + printf("Trying to close an invalid fd\n"); + } else { + clientStates[slot].fd = -1; + clientStates[slot].state = STATE_DISCONNECTED; + printf("Client disconnected or error\n"); + nfds--; + } + } else { + printf("Data received: %s\n", clientStates[slot].buffer); + } + } + + } + } + return 0; +} diff --git a/C/netCode/types.h b/C/netCode/types.h new file mode 100644 index 0000000..e70974e --- /dev/null +++ b/C/netCode/types.h @@ -0,0 +1,26 @@ +#define SERVER_PORT 5555 +#define MAX_CLIENTS 5 +#define BUF_SIZE 4096 + +typedef enum { + PROTO_HELLO, +} proto_type_e; + +/* Type-Length-Value */ +typedef struct { + proto_type_e type; + unsigned short len; +} proto_hdr_t; + +typedef enum { + STATE_NEW, + STATE_CONNECTED, + STATE_DISCONNECTED, +} state_e; + +typedef struct { + int fd; + state_e state; + char buffer[BUF_SIZE]; +} clientstate_t; + -- cgit v1.2.3