Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лаб. 6 ОСиС

.docx
Скачиваний:
0
Добавлен:
29.12.2024
Размер:
438.1 Кб
Скачать

Лабораторная работа 6

client.c:

#include <stdbool.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <errno.h>

#include <getopt.h>

#include <netdb.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <pthread.h>

struct Server {

    char ip[255];

    int port;

};

uint64_t MultModulo(uint64_t a, uint64_t b, uint64_t mod) {

    uint64_t result = 0;

    a = a % mod;

    while (b > 0) {

        if (b % 2 == 1)

            result = (result + a) % mod;

        a = (a * 2) % mod;

        b /= 2;

    }

    return result % mod;

}

bool ConvertStringToUI64(const char *str, uint64_t *val) {

    char *end = NULL;

    unsigned long long i = strtoull(str, &end, 10);

    if (errno == ERANGE) {

        fprintf(stderr, "Out of uint64_t range: %s\n", str);

        return false;

    }

    if (errno != 0)

        return false;

    *val = i;

    return true;

}

struct ThreadData {

    struct Server server;

    uint64_t begin;

    uint64_t end;

    uint64_t mod;

    uint64_t result;

};

void *send_request(void *arg) {

    struct ThreadData *data = (struct ThreadData *)arg;

    struct sockaddr_in server;

    server.sin_family = AF_INET;

    server.sin_port = htons(data->server.port);

    struct hostent *hostname = gethostbyname(data->server.ip);

    if (hostname == NULL) {

        fprintf(stderr, "gethostbyname failed with %s\n", data->server.ip);

        // pthread_exit(NULL);

        exit(1);

    }

    server.sin_addr.s_addr = *((unsigned long *)hostname->h_addr);

    int sck = socket(AF_INET, SOCK_STREAM, 0);

    if (sck < 0) {

        fprintf(stderr, "Socket creation failed!\n");

        // pthread_exit(NULL);

        exit(1);

    }

    if (connect(sck, (struct sockaddr *)&server, sizeof(server)) < 0) {

        fprintf(stderr, "Connection failed\n");

        // pthread_exit(NULL);

        exit(1);

    }

    char task[sizeof(uint64_t) * 3];

    memcpy(task, &data->begin, sizeof(uint64_t));

    memcpy(task + sizeof(uint64_t), &data->end, sizeof(uint64_t));

    memcpy(task + 2 * sizeof(uint64_t), &data->mod, sizeof(uint64_t));

    if (send(sck, task, sizeof(task), 0) < 0) {

        fprintf(stderr, "Send failed\n");

        // pthread_exit(NULL);

        exit(1);

    }

    char response[sizeof(uint64_t)];

    if (recv(sck, response, sizeof(response), 0) < 0) {

        fprintf(stderr, "Receive failed\n");

        // pthread_exit(NULL);

        exit(1);

    }

    memcpy(&data->result, response, sizeof(uint64_t));

    close(sck);

    // pthread_exit(NULL);

}

int main(int argc, char **argv) {

    uint64_t k = -1;

    uint64_t mod = -1;

    char servers[255] = {'\0'};

    while (true) {

        int current_optind = optind ? optind : 1;

        static struct option options[] = {

            {"k", required_argument, 0, 0},

            {"mod", required_argument, 0, 0},

            {"servers", required_argument, 0, 0},

            {0, 0, 0, 0}};

        int option_index = 0;

        int c = getopt_long(argc, argv, "", options, &option_index);

        if (c == -1)

            break;

        switch (c) {

        case 0: {

            switch (option_index) {

            case 0:

                ConvertStringToUI64(optarg, &k);

                break;

            case 1:

                ConvertStringToUI64(optarg, &mod);

                break;

            case 2:

                memcpy(servers, optarg, strlen(optarg));

                break;

            default:

                printf("Index %d is out of options\n", option_index);

            }

        } break;

        case '?':

            printf("Arguments error\n");

            break;

        default:

            fprintf(stderr, "getopt returned character code 0%o?\n", c);

        }

    }

    if (k == -1 || mod == -1 || !strlen(servers)) {

        fprintf(stderr, "Using: %s --k 1000 --mod 5 --servers /path/to/file\n", argv[0]);

        return 1;

    }

    // Чтение серверов из файла

    FILE *file = fopen(servers, "r");

    if (!file) {

        fprintf(stderr, "Could not open servers file\n");

        return 1;

    }

    unsigned int servers_num = 2;

    struct Server *to = malloc(sizeof(struct Server) * servers_num);

    int server_count = 0;

    while (fscanf(file, "%s %d", to[server_count].ip, &to[server_count].port) != EOF) {

        server_count++;

    }

    fclose(file);

    pthread_t *threads = malloc(sizeof(pthread_t) * server_count);

    struct ThreadData *thread_data = malloc(sizeof(struct ThreadData) * server_count);

    uint64_t chunk_size = k / server_count;

    for (int i = 0; i < server_count; i++) {

        thread_data[i].server = to[i];

        thread_data[i].begin = i * chunk_size + 1;

        thread_data[i].end = (i == server_count - 1) ? k : (i + 1) * chunk_size;

        thread_data[i].mod = mod;

        thread_data[i].result = 1;

        pthread_create(&threads[i], NULL, send_request, &thread_data[i]);

    }

    uint64_t total = 1;

    for (int i = 0; i < server_count; i++) {

        pthread_join(threads[i], NULL);

        total = MultModulo(total, thread_data[i].result, mod);

    }

    printf("Final answer: %lu\n", (unsigned long)total);

    free(threads);

    free(thread_data);

    free(to);

    return 0;

}

server.c:

#include <limits.h>

#include <stdbool.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <getopt.h>

#include <netinet/in.h>

#include <pthread.h>

#include <netinet/ip.h>

#include <sys/socket.h>

struct FactorialArgs {

    uint64_t begin;

    uint64_t end;

    uint64_t mod;

};

uint64_t MultModulo(uint64_t a, uint64_t b, uint64_t mod) {

    uint64_t result = 0;

    a = a % mod;

    while (b > 0) {

        if (b % 2 == 1)

            result = (result + a) % mod;

        a = (a * 2) % mod;

        b /= 2;

    }

    return result % mod;

}

uint64_t Factorial(const struct FactorialArgs *args) {

    uint64_t ans = 1;

    for (uint64_t i = args->begin; i <= args->end; i++) {

        ans = MultModulo(ans, i, args->mod);

    }

    return ans;

}

void *ThreadFactorial(void *args) {

    struct FactorialArgs *fargs = (struct FactorialArgs *)args;

    uint64_t *result = malloc(sizeof(uint64_t));

    *result = Factorial(fargs);

    return result;

}

int main(int argc, char **argv) {

    int tnum = -1;

    int port = -1;

    while (true) {

        int current_optind = optind ? optind : 1;

        static struct option options[] = {

            {"port", required_argument, 0, 0},

            {"tnum", required_argument, 0, 0},

            {0, 0, 0, 0}};

        int option_index = 0;

        int c = getopt_long(argc, argv, "", options, &option_index);

        if (c == -1)

            break;

        switch (c) {

        case 0: {

            switch (option_index) {

            case 0:

                port = atoi(optarg);

                break;

            case 1:

                tnum = atoi(optarg);

                break;

            default:

                printf("Index %d is out of options\n", option_index);

            }

        } break;

        case '?':

            printf("Unknown argument\n");

            break;

        default:

            fprintf(stderr, "getopt returned character code 0%o?\n", c);

        }

    }

    if (port == -1 || tnum == -1) {

        fprintf(stderr, "Using: %s --port 20001 --tnum 4\n", argv[0]);

        return 1;

    }

    int server_fd = socket(AF_INET, SOCK_STREAM, 0);

    if (server_fd < 0) {

        fprintf(stderr, "Can not create server socket!");

        return 1;

    }

    struct sockaddr_in server;

    server.sin_family = AF_INET;

    server.sin_port = htons((uint16_t)port);

    server.sin_addr.s_addr = htonl(INADDR_ANY);

    int opt_val = 1;

    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(opt_val));

    int err = bind(server_fd, (struct sockaddr *)&server, sizeof(server));

    if (err < 0) {

        fprintf(stderr, "Can not bind to socket!");

        return 1;

    }

    err = listen(server_fd, 128);

    if (err < 0) {

        fprintf(stderr, "Could not listen on socket\n");

        return 1;

    }

    printf("Server listening at %d\n", port);

    while (true) {

        struct sockaddr_in client;

        socklen_t client_len = sizeof(client);

        int client_fd = accept(server_fd, (struct sockaddr *)&client, &client_len);

        if (client_fd < 0) {

            fprintf(stderr, "Could not establish new connection\n");

            continue;

        }

        while (true) {

            unsigned int buffer_size = sizeof(uint64_t) * 3;

            char from_client[buffer_size];

            int read = recv(client_fd, from_client, buffer_size, 0);

            if (!read)

                break;

            if (read < 0) {

                fprintf(stderr, "Client read failed\n");

                break;

            }

            if (read < buffer_size) {

                fprintf(stderr, "Client send wrong data format\n");

                break;

            }

            pthread_t threads[tnum];

            struct FactorialArgs args[tnum];

            uint64_t total = 1;

            uint64_t begin = 0;

            uint64_t end = 0;

            uint64_t mod = 0;

            memcpy(&begin, from_client, sizeof(uint64_t));

            memcpy(&end, from_client + sizeof(uint64_t), sizeof(uint64_t));

            memcpy(&mod, from_client + 2 * sizeof(uint64_t), sizeof(uint64_t));

            fprintf(stdout, "Receive: %lu %lu %lu\n", (unsigned long)begin, (unsigned long)end, (unsigned long)mod);

            uint64_t chunk_size = (end - begin + 1) / tnum;

            for (uint32_t i = 0; i < tnum; i++) {

                args[i].begin = begin + i * chunk_size;

                args[i].end = (i == tnum - 1) ? end : (begin + (i + 1) * chunk_size - 1);

                args[i].mod = mod;

                if (pthread_create(&threads[i], NULL, ThreadFactorial, (void *)&args[i])){

                    printf("Error: pthread_create failed!\n");

                    return 1;

                };

            }

            for (uint32_t i = 0; i < tnum; i++) {

                uint64_t *result;

                pthread_join(threads[i], (void **)&result);

                total = MultModulo(total, *result, mod);

            }

            printf("Total: %lu\n", (unsigned long)total);

            char buffer[sizeof(total)];

            memcpy(buffer, &total, sizeof(total));

            err = send(client_fd, buffer, sizeof(total), 0);

            if (err < 0) {

                fprintf(stderr, "Can't send data to client\n");

                break;

            }

        }

        shutdown(client_fd, SHUT_RDWR);

        close(client_fd);

    }

    return 0;

}

servers.txt:

127.0.0.1 20001

127.0.0.1 20002

Командная строка:

./server --port 20001 --tnum 4

./server --port 20002 --tnum 4

./client --k 5 --mod 9 --servers servers.txt

CC = gcc

CFLAGS = -I. -lpthread

all: client server

client: client.o

    $(CC) -o client client.o $(CFLAGS)

server: server.o

    $(CC) -o server server.o $(CFLAGS)

client.o: client.c

    $(CC) -c client.c $(CFLAGS)

server.o: server.c

    $(CC) -c server.c $(CFLAGS)

clean:

    rm -f *.o client server

multmodulo.h:

#ifndef MULTMODULO_H

#define MULTMODULO_H

#include <stdint.h>

uint64_t MultModulo(uint64_t a, uint64_t b, uint64_t mod);

#endif // MULTMODULO_H

multmodulo.c:

#include "multmodulo.h"

uint64_t MultModulo(uint64_t a, uint64_t b, uint64_t mod) {

    uint64_t result = 0;

    a = a % mod;

    while (b > 0) {

        if (b % 2 == 1)

            result = (result + a) % mod;

        a = (a * 2) % mod;

        b /= 2;

    }

    return result % mod;

}

makefile:

CC = gcc

CFLAGS = -I. -lpthread

all: client server

client: client.o multmodulo.o

    $(CC) -o client client.o multmodulo.o $(CFLAGS)

server: server.o multmodulo.o

    $(CC) -o server server.o multmodulo.o $(CFLAGS)

client.o: client.c multmodulo.h

    $(CC) -c client.c $(CFLAGS)

server.o: server.c multmodulo.h

    $(CC) -c server.c $(CFLAGS)

multmodulo.o: multmodulo.c multmodulo.h

    $(CC) -c multmodulo.c $(CFLAGS)

clean:

    rm -f *.o client server

Соседние файлы в предмете Операционные системы и сети