I am learning about sockets and followed the GeeksForGeeks tutorial here. As a test, I added a while loop to enclose the sending and receiving of data on both the client and server side. I then noticed that if I killed the client process, the server process also exited. And that's where I'm confused -- the client and server both have separate PIDs, so why would this happen? It seems like the client should have been the only process to have been killed.
I see on this post that the trick is putting the server accept() call inside the while loop. But still, shouldn't the server have been stuck in its own while-loop, attempting to read and send data on the no longer active socket, no matter what the client is doing? There is no condition in my while loop which would have exited upon the connection closing. I suppose my real question is what kind of IPC is going on here that would cause this behavior?
I am attaching my code for reference.
Server.c
int server_fd, new_socket, valread;
struct sockaddr_in address;
int addrlen = sizeof(address);
int opt = 1;
char buffer[1024] = { 0 };
char *hello = "Hello from server";
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
while (1) {
valread = read(new_socket, buffer, sizeof(buffer));
printf("%s\n", buffer);
send(new_socket, hello, strlen(hello), 0);
}
close(new_socket);
shutdown(server_fd, SHUT_RDWR);
return 0;
}
Client.c
int client_fd, status, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char buffer[1024] = { 0 };
if ((client_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
perror("Address not supported");
exit(EXIT_FAILURE);
}
if ((status = connect(client_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) < 0) {
perror("Connection failed");
}
while (1) {
send(client_fd, hello, strlen(hello), 0);
printf("Hello message sent\n");
valread = read(client_fd, buffer, sizeof(buffer));
printf("%s\n", buffer);
}
close(client_fd);
return 0;
I tried to output the pids of the client server process to validate they have separate process IDs. I also looked up about shared resources between clients and servers, but found nothing that would indicate the processes themselves would be interdependent.