First commit

This commit is contained in:
2026-09-06 17:43:06 +03:00
commit 0fe9114117
10 changed files with 278 additions and 0 deletions

70
ch1/TCPEchoClient4.c Normal file
View File

@@ -0,0 +1,70 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Practical.h"
int main(int argc, char **argv) {
if (argc < 3 || argc > 4) {
DieWithUserMessage("Parameter(s)", "<Server Address> <Echo Word> [<Server Port>]");
}
const char *server_ip = argv[1];
const char *echo_str = argv[2];
const in_port_t server_port = (argc == 4) ? atoi(argv[3]) : 7; // 7: common echo port
const int sock = socket(AF_INET, SOCK_STREAM, proto_get_num("tcp"));
if (sock < 0) {
DieWithSystemMessage("socket() failed");
}
struct sockaddr_in server_addr = {0};
server_addr.sin_family = AF_INET;
int ret_val = inet_pton(AF_INET, server_ip, &server_addr.sin_addr.s_addr);
if (ret_val == 0) {
DieWithUserMessage("inet_pton() failed", "invalid address string");
} else if (ret_val < 0) {
DieWithSystemMessage("inet_pton() failed");
}
server_addr.sin_port = htons(server_port);
if (connect(sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
DieWithSystemMessage("connect() failed");
}
const size_t echo_str_len = strlen(echo_str);
ssize_t num_bytes = send(sock, echo_str, echo_str_len, 0);
if (num_bytes < 0) {
DieWithSystemMessage("send() failed");
} else if ((size_t) num_bytes != echo_str_len) {
DieWithUserMessage("send()", "sent unexpected number of bytes");
}
unsigned int total_bytes_rcvd = 0;
fputs("Received: ", stdout);
while (total_bytes_rcvd < echo_str_len) {
char buffer[BUFSIZE];
num_bytes = recv(sock, buffer, BUFSIZE - 1, 0);
if (num_bytes < 0) {
DieWithSystemMessage("recv() failed");
} else if (num_bytes == 0) {
DieWithUserMessage("recv()", "connection closed prematurely");
}
total_bytes_rcvd += num_bytes;
buffer[num_bytes] = '\0';
fputs(buffer, stdout);
}
fputc('\n', stdout);
close(sock);
return 0;
}

95
ch1/TCPEchoServer4.c Normal file
View File

@@ -0,0 +1,95 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Practical.h"
#include "TCPServerUtility.h"
static const int MAXPENDING = 5;
int main(int argc, char **argv) {
if (argc != 2) {
DieWithUserMessage("Parameter(s)", "<Server Port>");
}
const in_port_t server_port = atoi(argv[1]);
const int server_sock = socket(AF_INET, SOCK_STREAM, proto_get_num("tcp"));
if (server_sock < 0) {
DieWithSystemMessage("socket() failed");
}
struct sockaddr_in server_addr = {
.sin_family = AF_INET,
.sin_addr = {
.s_addr = htonl(INADDR_ANY),
},
.sin_port = htons(server_port)
};
int ret_val = bind(
server_sock,
(struct sockaddr *) &server_addr,
sizeof(server_addr)
);
if (ret_val < 0) {
DieWithSystemMessage("bind() failed");
}
ret_val = listen(server_sock, MAXPENDING);
if (ret_val < 0) {
DieWithSystemMessage("listen() failed");
} else {
char server_name[INET_ADDRSTRLEN];
const char *ntop_res = inet_ntop(
AF_INET,
&server_addr.sin_addr.s_addr,
server_name,
sizeof(server_name)
);
if (ntop_res != NULL) {
printf("Listening on %s/%d...\n", server_name, server_port);
} else {
puts("Unable to get server address");
}
}
while (1) {
struct sockaddr_in client_addr;
socklen_t client_addr_len = sizeof(client_addr);
int client_sock = accept(
server_sock,
(struct sockaddr *) &client_addr,
&client_addr_len
);
if (client_sock < 0) {
DieWithSystemMessage("accept() failed");
}
char client_name[INET_ADDRSTRLEN];
const char *ntop_res = inet_ntop(
AF_INET,
&client_addr.sin_addr.s_addr,
client_name,
sizeof(client_name)
);
if (ntop_res != NULL) {
printf(
"Handling client %s/%d\n",
client_name,
ntohs(client_addr.sin_port)
);
} else {
puts("Unable to get client address");
}
HandleTCPClient(client_sock);
}
return 0;
}

29
ch1/TCPServerUtility.c Normal file
View File

@@ -0,0 +1,29 @@
#include <sys/socket.h>
#include <unistd.h>
#include "Practical.h"
void HandleTCPClient(const int client_sock) {
char buffer[BUFSIZE];
ssize_t num_bytes_rcvd = recv(client_sock, buffer, BUFSIZE, 0);
if (num_bytes_rcvd < 0) {
DieWithSystemMessage("recv() failed");
}
while (num_bytes_rcvd > 0) {
ssize_t num_bytes_sent = send(client_sock, buffer, num_bytes_rcvd, 0);
if (num_bytes_sent < 0) {
DieWithSystemMessage("send() failed");
} else if (num_bytes_sent != num_bytes_rcvd) {
DieWithUserMessage("send()", "sent unexpected number of bytes");
}
num_bytes_rcvd = recv(client_sock, buffer, BUFSIZE, 0);
if (num_bytes_rcvd < 0) {
DieWithSystemMessage("recv() failed");
}
}
close(client_sock);
}

3
ch1/TCPServerUtility.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
void HandleTCPClient(const int client_sock);

20
ch1/meson.build Normal file
View File

@@ -0,0 +1,20 @@
executable(
'client',
'TCPEchoClient4.c',
common_src,
include_directories: [
common_include
],
c_args: c_args
)
executable(
'server',
'TCPEchoServer4.c',
'TCPServerUtility.c',
common_src,
include_directories: [
common_include
],
c_args: c_args
)