#include #include #include #include #include #include #include #include #include /* * while(true) { * next_fd = select(client_fds) * read from next_fd * send an update to everybody * } */ #include #include using namespace std; vector client_fds; vector sqdescs; /* Protocol: * uint16_t description_length (little endian) * actual description of the stated length */ char temp_buffer[65536]; void read_from_fd(int fd){ uint16_t dlen; ssize_t readlen = read(fd, &dlen, 2); if(readlen != 2) return; readlen = recv(fd, temp_buffer, dlen, MSG_WAITALL); temp_buffer[readlen] = 0; sqdescs.push_back(string(temp_buffer)); // If this fails, that fd is probably disconnected, and needs to be removed from the set for(int fd : client_fds){ write(fd, &dlen, 2); write(fd, temp_buffer, dlen); } } void *recorder_thread(void *p){ while(1){ if(client_fds.size() == 0) { usleep(1000); continue; } fd_set read_set; FD_ZERO(&read_set); int highest = 0; for(auto fd : client_fds) { printf("Adding fd %d to the set\n", fd); FD_SET(fd, &read_set); if(fd > highest) highest = fd; } printf("Calling select, client_fds.size() = %d\n", client_fds.size()); int nfds = select(highest + 1, &read_set, 0, 0, 0); printf("reading from %d fds\n", nfds); if(!nfds) continue; for(auto fd : client_fds) if(FD_ISSET(fd, &read_set)){ read_from_fd(fd); nfds--; if(!nfds) break; } } } int main(int argc, char ** argv){ uint16_t port = 5143; int skt = socket(AF_INET, SOCK_STREAM, 0); // Step 1 if(skt == -1){ perror("socket"); return 1; } struct sockaddr_in sad; sad.sin_addr.s_addr = INADDR_ANY; sad.sin_family = AF_INET; retry_bind: sad.sin_port = htons(port); if( bind(skt, (struct sockaddr*)(&sad), sizeof(struct sockaddr_in)) ){ // step 2 perror("bind"); port++; goto retry_bind; } printf("Listening on port %d\n", port); if( listen(skt, 5) ){ // step 3 perror("listen"); return 1; } pthread_t thread_handle; pthread_create(&thread_handle, 0, recorder_thread, 0); while(1){ int client_fd; struct sockaddr_in client_address; socklen_t address_size = sizeof(struct sockaddr_in); client_fd = accept(skt, (struct sockaddr *)(&client_address), &address_size); // step 4 printf("Connection made from address %s\n", inet_ntoa(client_address.sin_addr)); client_fds.push_back(client_fd); } return 0; }