Files
CS-LABS/mine/lab_8/client.c
2025-12-11 09:40:07 +07:00

126 lines
3.8 KiB
C
Raw Permalink 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.
// UDPклиент: читает файл и отправляет его содержимое серверу блоками UDP.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h> // inet_pton, sockaddr_in
#include <sys/socket.h>
#include <sys/types.h>
#define BUF_SIZE 4096
#define END_MARKER "END_OF_TRANSMISSION"
int main(int argc, char *argv[]) {
// argv[1] — IP сервера, 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 in.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;
}
// Создаём UDPсокет.
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket");
fclose(fin);
return -1;
}
// Заполняем адрес сервера: IPv4 + порт.
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
// inet_pton конвертирует строку IP ("127.0.0.1") в бинарный вид.
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;
}
char buf[BUF_SIZE];
// Читаем файл блоками и каждый блок отправляем одной UDPдатаграммой.
for (;;) {
size_t n = fread(buf, 1, sizeof(buf), fin);
if (n > 0) {
ssize_t sent = sendto(sockfd,
buf,
n,
0,
(struct sockaddr *) &servaddr,
sizeof(servaddr));
if (sent < 0 || (size_t) sent != n) {
perror("sendto");
close(sockfd);
fclose(fin);
return -1;
}
}
// Если прочитали меньше, чем размер буфера — это 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)");
}
// Отправляем серверу маркер конца передачи.
ssize_t sent = sendto(sockfd,
END_MARKER,
strlen(END_MARKER),
0,
(struct sockaddr *) &servaddr,
sizeof(servaddr));
if (sent < 0 || (size_t) sent != strlen(END_MARKER)) {
perror("sendto(END_MARKER)");
close(sockfd);
return -1;
}
printf("File '%s' sent to %s:%d, END marker transmitted.\n",
input_path, server_ip, port);
close(sockfd);
return 0;
}