Skip to content

Instantly share code, notes, and snippets.

@vlaleli
Created March 13, 2026 11:36
Show Gist options
  • Select an option

  • Save vlaleli/bfeb09ea633cf1f387191cd388532095 to your computer and use it in GitHub Desktop.

Select an option

Save vlaleli/bfeb09ea633cf1f387191cd388532095 to your computer and use it in GitHub Desktop.
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <thread>
#include <csignal>
#define DEFAULT_BUFLEN 4096
#define SERVER_IP "127.0.0.1"
#define DEFAULT_PORT 8888
int client_socket = -1;
volatile sig_atomic_t running = 1;
std::string nickname;
void signal_handler(int) {
running = 0;
if (client_socket >= 0) {
send(client_socket, "off", 3, 0);
shutdown(client_socket, SHUT_RDWR);
close(client_socket);
client_socket = -1;
}
}
void sender() {
while (running) {
std::string text;
std::getline(std::cin, text);
if (!running) {
break;
}
if (text.empty()) {
continue;
}
std::string full_message = nickname + ": " + text;
if (send(client_socket, full_message.c_str(), full_message.size(), 0) < 0) {
std::cerr << "Помилка відправки\n";
running = 0;
break;
}
}
}
void receiver() {
char buffer[DEFAULT_BUFLEN];
while (running) {
ssize_t received = recv(client_socket, buffer, DEFAULT_BUFLEN - 1, 0);
if (received <= 0) {
if (running) {
std::cerr << "З'єднання із сервером втрачено\n";
}
running = 0;
break;
}
buffer[received] = '\0';
std::cout << buffer;
std::cout.flush();
}
}
int main() {
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
std::cout << "Введіть ваш нік: ";
std::getline(std::cin, nickname);
if (nickname.empty()) {
std::cerr << "Нік не може бути порожнім\n";
return 1;
}
client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket < 0) {
std::cerr << "Не вдалося створити сокет\n";
return 2;
}
sockaddr_in server_addr{};
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(DEFAULT_PORT);
if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
std::cerr << "Некоректна IP-адреса сервера\n";
close(client_socket);
return 3;
}
if (connect(client_socket, (sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
std::cerr << "Не вдалося підключитися до сервера\n";
close(client_socket);
return 4;
}
std::cout << "Підключено до сервера " << SERVER_IP << ":" << DEFAULT_PORT << "\n";
std::thread sender_thread(sender);
std::thread receiver_thread(receiver);
sender_thread.join();
running = 0;
shutdown(client_socket, SHUT_RDWR);
receiver_thread.join();
if (client_socket >= 0) {
close(client_socket);
client_socket = -1;
}
std::cout << "Клієнт завершено.\n";
return 0;
}
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#include <vector>
#include <string>
#include <csignal>
#define MAX_CLIENTS 20
#define DEFAULT_BUFLEN 4096
#define PORT 8888
int server_socket = -1;
volatile sig_atomic_t running = 1;
std::vector<std::string> history;
void signal_handler(int) {
running = 0;
if (server_socket >= 0) {
close(server_socket);
server_socket = -1;
}
}
int main() {
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
std::cout << "Запуск сервера...\n";
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket < 0) {
std::cerr << "Не вдалося створити сокет\n";
return 1;
}
int opt = 1;
if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
std::cerr << "Помилка setsockopt\n";
close(server_socket);
return 2;
}
sockaddr_in server_addr{};
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
if (bind(server_socket, (sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
std::cerr << "Помилка bind\n";
close(server_socket);
return 3;
}
if (listen(server_socket, MAX_CLIENTS) < 0) {
std::cerr << "Помилка listen\n";
close(server_socket);
return 4;
}
std::cout << "Сервер очікує вхідні з'єднання на порту " << PORT << "...\n";
fd_set readfds;
int client_sockets[MAX_CLIENTS] = {};
while (running) {
FD_ZERO(&readfds);
FD_SET(server_socket, &readfds);
int max_fd = server_socket;
for (int i = 0; i < MAX_CLIENTS; i++) {
if (client_sockets[i] > 0) {
FD_SET(client_sockets[i], &readfds);
if (client_sockets[i] > max_fd) {
max_fd = client_sockets[i];
}
}
}
int activity = select(max_fd + 1, &readfds, nullptr, nullptr, nullptr);
if (activity < 0) {
if (running) {
std::cerr << "Помилка select\n";
}
break;
}
if (FD_ISSET(server_socket, &readfds)) {
sockaddr_in client_addr{};
socklen_t addrlen = sizeof(client_addr);
int new_socket = accept(server_socket, (sockaddr*)&client_addr, &addrlen);
if (new_socket < 0) {
if (running) {
std::cerr << "Помилка accept\n";
}
} else {
std::cout << "Нове з'єднання: ip " << inet_ntoa(client_addr.sin_addr)
<< ", порт " << ntohs(client_addr.sin_port) << "\n";
for (const auto& msg : history) {
send(new_socket, msg.c_str(), msg.size(), 0);
}
bool added = false;
for (int i = 0; i < MAX_CLIENTS; i++) {
if (client_sockets[i] == 0) {
client_sockets[i] = new_socket;
added = true;
break;
}
}
if (!added) {
std::string full_msg = "Сервер переповнений\n";
send(new_socket, full_msg.c_str(), full_msg.size(), 0);
close(new_socket);
}
}
}
for (int i = 0; i < MAX_CLIENTS; i++) {
int s = client_sockets[i];
if (s > 0 && FD_ISSET(s, &readfds)) {
char buffer[DEFAULT_BUFLEN];
ssize_t received = recv(s, buffer, DEFAULT_BUFLEN - 1, 0);
if (received <= 0) {
std::cout << "Клієнт #" << i << " відключився\n";
close(s);
client_sockets[i] = 0;
continue;
}
buffer[received] = '\0';
std::string message = buffer;
if (message == "off") {
std::cout << "Клієнт #" << i << " вийшов\n";
close(s);
client_sockets[i] = 0;
continue;
}
std::string out = message + "\n";
history.push_back(out);
std::cout << out;
for (int j = 0; j < MAX_CLIENTS; j++) {
int dest = client_sockets[j];
if (dest > 0 && dest != s) {
send(dest, out.c_str(), out.size(), 0);
}
}
}
}
}
if (server_socket >= 0) {
close(server_socket);
}
for (int i = 0; i < MAX_CLIENTS; i++) {
if (client_sockets[i] > 0) {
close(client_sockets[i]);
}
}
std::cout << "Сервер зупинено.\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment