Files
CS-LABS/lab_8/vlad/client.c
2025-12-10 15:14:24 +07:00

140 lines
4.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// client_tcp_pairs.c
// TCP-клиент для лабораторной №8, вариант "во всех парах одинаковых символов
// второй символ заменить на пробел".
// Клиент читает входной файл и передаёт его содержимое серверу по TCP.
#include <stdio.h> // printf, fprintf, perror, FILE, fopen, fclose, fread
#include <stdlib.h> // exit, EXIT_FAILURE, strtol
#include <string.h> // memset, strlen
#include <errno.h> // errno
#include <unistd.h> // close, write
#include <arpa/inet.h> // sockaddr_in, inet_pton, htons
#include <sys/socket.h> // socket, connect
#include <sys/types.h> // типы сокетов
#include <netinet/in.h> // sockaddr_in
#define BUF_SIZE 4096
int main(int argc, char *argv[])
{
// Ожидаемые аргументы:
// argv[1] - IP-адрес сервера (например, 127.0.0.1).
// argv[2] - порт сервера.
// argv[3] - путь к входному файлу.
if (argc < 4) {
fprintf(stderr,
"Usage: %s <server_ip> <server_port> <input_file>\n",
argv[0]);
fprintf(stderr,
"Example: %s 127.0.0.1 5000 input.txt\n",
argv[0]);
return -1;
}
const char *server_ip = argv[1];
const char *server_port = argv[2];
const char *input_path = argv[3];
// Разбор порта.
char *endptr = NULL;
errno = 0;
long port_long = strtol(server_port, &endptr, 10);
if (errno != 0 || endptr == server_port || *endptr != '\0' ||
port_long <= 0 || port_long > 65535) {
fprintf(stderr, "ERROR: invalid port '%s'\n", server_port);
return -1;
}
int port = (int)port_long;
// Открываем входной файл.
FILE *fin = fopen(input_path, "r");
if (!fin) {
perror("fopen(input_file)");
return -1;
}
// Создаём TCP-сокет.
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
fclose(fin);
return -1;
}
// Заполняем структуру адреса сервера.
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
// Переводим строковый IP в бинарную форму.
if (inet_pton(AF_INET, server_ip, &servaddr.sin_addr) != 1) {
fprintf(stderr, "ERROR: invalid IP address '%s'\n", server_ip);
close(sockfd);
fclose(fin);
return -1;
}
// Устанавливаем TCP-соединение.
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("connect");
close(sockfd);
fclose(fin);
return -1;
}
printf("Connected to %s:%d, sending file '%s'\n",
server_ip, port, input_path);
char buf[BUF_SIZE];
for (;;) {
// Читаем блок из файла.
size_t n = fread(buf, 1, sizeof(buf), fin);
if (n > 0) {
// Отправляем блок по TCP.
size_t sent_total = 0;
while (sent_total < n) {
ssize_t sent = write(sockfd,
buf + sent_total,
n - sent_total);
if (sent < 0) {
perror("write");
close(sockfd);
fclose(fin);
return -1;
}
sent_total += (size_t)sent;
}
}
// Если прочитали меньше, чем BUF_SIZE, либо EOF, либо ошибка.
if (n < sizeof(buf)) {
if (ferror(fin)) {
perror("fread");
close(sockfd);
fclose(fin);
return -1;
}
break; // EOF, передачу завершаем.
}
}
// Закрываем файл.
if (fclose(fin) == EOF) {
perror("fclose(input_file)");
}
// Корректно закрываем соединение, чтобы сервер получил EOF.
if (shutdown(sockfd, SHUT_WR) < 0) {
perror("shutdown");
}
close(sockfd);
printf("File '%s' sent to %s:%d, connection closed.\n",
input_path, server_ip, port);
return 0;
}