AAE-CNAS-Labs/Topic-12/server_task_6-4.c
2021-05-30 20:25:49 +02:00

100 lines
2.7 KiB
C

#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void handle_arguments(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s PORT N_OF_CLIENTS\n", argv[0]);
exit(EXIT_FAILURE);
}
}
void run_child(int sockfd) {
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
memset(&client_addr, 0, sizeof(client_addr));
while (1) {
int accfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addr_len);
if (accfd == -1) {
perror("accept");
exit(EXIT_FAILURE);
}
printf("A new connection has been accepted!\n");
size_t buffer_size = sizeof(int);
int buffer;
while (read(accfd, &buffer, buffer_size)) {
printf("%d\n", buffer);
// write(accfd, buffer.array, buffer_size);
memset(&buffer, 0, buffer_size);
}
printf("A connection with the client has been closed!\n");
}
}
void run_server(int port, int n_of_clients) {
// create a socket using Internet protocol
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
// bind sockfd to serv_addr
int rv = bind(sockfd, (const struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (rv == -1) {
perror("bind");
exit(EXIT_FAILURE);
}
// man 2 listen
// The behavior of the backlog argument on TCP sockets changed with Linux 2.2. Now it specifies the queue length for completely established sockets waiting to be accepted, instead of the number of
// incomplete connection requests. The maximum length of the queue for incomplete sockets can be set using /proc/sys/net/ipv4/tcp_max_syn_backlog. When syncookies are enabled there is no logical
// maximum length and this setting is ignored. See tcp(7) for more information.
rv = listen(sockfd, 5);
if (rv == -1) {
perror("listen");
exit(EXIT_FAILURE);
}
pid_t pid;
int status[n_of_clients];
int children_pids[n_of_clients];
for (int i = 0; i < n_of_clients; ++i) {
pid = fork();
if (pid == -1) {
perror("fork: ");
exit(EXIT_FAILURE);
}
if (pid == 0) {
printf("A new child has been spawned!\n");
run_child(sockfd);
}
}
for (int i = 0; i < n_of_clients; ++i) {
children_pids[i] = pid;
waitpid(children_pids[i], &status[i], 0);
}
}
int main(int argc, char *argv[]) {
handle_arguments(argc, argv);
run_server(strtol(argv[1], NULL, 10), strtol(argv[2], NULL, 10));
return 0;
}