diff --git a/Topic-12/client_task_6-3.c b/Topic-12/client_task_6-3.c new file mode 100644 index 0000000..61ebb1a --- /dev/null +++ b/Topic-12/client_task_6-3.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include +#include + +void handle_arguments(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "Usage: %s PORT\n", argv[0]); + exit(EXIT_FAILURE); + } +} + +void send_integers(int sockfd, struct sockaddr_in * server_addr) { + int buffer = 42; + + while (1) { + // int rv = sendto(sockfd, buffer.array, sizeof(buffer), 0, (const struct sockaddr *)&server_addr, sizeof(server_addr)); + int rv = sendto(sockfd, &buffer, sizeof(buffer), 0, (const struct sockaddr *)&server_addr, sizeof(server_addr)); + if (rv == -1) { + perror("sendto: "); + exit(EXIT_FAILURE); + } + // printf("Sent %x to the server\n", buffer.number); + sleep(10); + } +} + +void run_client(int port) { + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + fprintf(stderr, "socket: "); + exit(EXIT_FAILURE); + } + + struct sockaddr_in server_addr; + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(port); + if (connect(sockfd, (const struct sockaddr *)&server_addr, sizeof(server_addr))) { + perror("connect"); + exit(EXIT_FAILURE); + } + + pid_t pid; + pid = fork(); + if (pid == -1) { + perror("fork: "); + exit(EXIT_FAILURE); + } + if (pid == 0) { + send_integers(sockfd, &server_addr); + } + + char response[] = "DATA RECEIVED"; + char buffer[100]; + + int rv; + while (1) { + rv = recv(sockfd, buffer, sizeof(buffer), 0); + if (rv < 0) { + fprintf(stderr, "recvfrom: "); + exit(EXIT_FAILURE); + } + if (strlen(buffer)) { + printf("From server: %s\n", buffer); + rv = send(sockfd, response, sizeof(response), 0); + if (rv == -1) { + perror("send"); + exit(EXIT_FAILURE); + } + } + memset(&buffer, 0, sizeof(buffer)); + } +} + +int main(int argc, char *argv[]) { + handle_arguments(argc, argv); + run_client(strtol(argv[1], NULL, 10)); + + return 0; +} \ No newline at end of file diff --git a/Topic-12/server.c b/Topic-12/server.c index ec946e3..7ce9e14 100644 --- a/Topic-12/server.c +++ b/Topic-12/server.c @@ -4,6 +4,7 @@ #include #include #include +#include void handle_arguments(int argc, char *argv[]) { if (argc != 2) { @@ -13,57 +14,57 @@ void handle_arguments(int argc, char *argv[]) { } void run_server(int port) { + // create a socket using Internet protocol int sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd < 0) { - fprintf(stderr, "socket: "); + if (sockfd == -1) { + perror("socket"); exit(EXIT_FAILURE); } + struct sockaddr_in serv_addr, client_addr; - socklen_t client_addr_len; + socklen_t client_addr_len = sizeof(client_addr); memset(&serv_addr, 0, sizeof(serv_addr)); memset(&client_addr, 0, sizeof(client_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 < 0) { - fprintf(stderr, "bind: "); + if (rv == -1) { + perror("bind"); exit(EXIT_FAILURE); } rv = listen(sockfd, 5); - if (rv < 0) { - fprintf(stderr, "listen: "); + if (rv == -1) { + perror("listen"); exit(EXIT_FAILURE); } int accfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addr_len); - if (accfd < 0) { - fprintf(stderr, "accept: "); + if (accfd == -1) { + perror("accept"); exit(EXIT_FAILURE); } - - size_t buffer_size = 100; - char buffer[buffer_size]; + size_t buffer_size = sizeof(uint32_t); + union { + uint32_t number; + char array[buffer_size]; + } buffer; memset(&buffer, 0, buffer_size); while (1) { - read(accfd, buffer, buffer_size); - write(accfd, buffer, buffer_size); + read(accfd, buffer.array, buffer_size); + printf("%d\n", ntohl(buffer.number)); + write(accfd, buffer.array, buffer_size); memset(&buffer, 0, buffer_size); } } int main(int argc, char *argv[]) { - // Socket - // setsockopt - // Bind - // listen() - // accept - // send/recv handle_arguments(argc, argv); run_server(strtol(argv[1], NULL, 10)); diff --git a/Topic-12/server_task_6-4.c b/Topic-12/server_task_6-4.c new file mode 100644 index 0000000..feaa486 --- /dev/null +++ b/Topic-12/server_task_6-4.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} \ No newline at end of file