This is the code I have so far, I essentially have a fd sock_comm
which is the listening socket, then multiple client socket connections will be established and added. I need to be able to accept new connections but also receive on existing ones, so I am using select
. I am running into a problem when trying to iterate through existing connections where the while loop is restarting unexpectedly.
int n = sock_comm+1;
int max_sock;
while (1) {
max_sock = n;
printf("sock_comm: %d\n", sock_comm);
// Clear the fd_set and add back connections
FD_ZERO(&readfds);
for (int i=sock_comm; i < max_sock; i++) {
FD_SET(i, &readfds);
}
select(n, &readfds, NULL, NULL, NULL);
printf("max socket: %d\n", max_sock);
fd = sock_comm;
// Iterate through each connection
while (fd < max_sock) {
printf("fd: %d\n", fd);
printf("sock_comm2: %d\n", sock_comm);
// If activity on current connection
if (FD_ISSET(fd, &readfds)) {
printf("Connection on %d\n", fd);
// If connection on listener, accept
if (fd == sock_comm) {
if ((new_s = accept(sock_comm, (struct sockaddr *)&client_addr, &len)) < 1) {
perror("tcpserver: accept");
exit(1);
}
n++;
client_info.sockid = new_s;
// Join handler thread
pthread_create(&threads[0],NULL,join_handler,&client_info);
pthread_join(threads[0],&exit_value);
printf("sock_comm3: %d\n", sock_comm);
} else {
// Create and join thread for receiving data
}
}
fd++;
printf("sock_comm4: %d\n", sock_comm);
}
}
I would expect the output after an initial connect to be as such:
sock_comm: 3
max socket: 4
fd: 3
sock_comm2: 3
Connection on 3
sock_comm3: 3
sock_comm4: 3
sock_comm: 3
Then the select process begins again. What is happening though is this:
sock_comm: 3
max socket: 4
fd: 3
sock_comm2: 3
Connection on 3
sock_comm3: 3
sock_comm4: 3
fd: 1
sock_comm2: 3
sock_comm4: 3
fd: 2
sock_comm2: 3
sock_comm4: 3
fd: 3
sock_comm2: 3
Connection on 3
As you can see, the while (fd < max_sock)
loop is resetting and somehow starting at 1 but fd
never should drop below 3. I don't know what's wrong with my code, does it have to do with using select
in a loop? I've never used it before, but it's causing odd behavior. It gets stuck in an accept state when there is nothing to accept.
Join handler:
void *join_handler(struct global_table *rec) {
int newsock;
struct packet packet_reg;
newsock = rec->sockid;
for (int i=0; i < REQUEST_NO; i++) {
if (recv(newsock, &packet_reg, sizeof(packet_reg), 0) < 1) {
printf("Could not receive RG-%d\n", i+1);
exit(1);
} else {
printf("Registered received: %s\n",packet_reg.data);
}
}
// add to table
pthread_mutex_lock(&my_mutex);
counter++;
record[counter].sockid = newsock;
pthread_mutex_unlock(&my_mutex);
// send response acknowledging registration
packet_reg.type = htons(221);
sprintf(packet_reg.data, "%d", newsock);
if(send(newsock, &packet_reg, sizeof(packet_reg), 0) < 1) {
printf("ACK send failed\n");
exit(1);
}
pthread_exit(NULL);
}