#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; }