Created
March 13, 2026 11:36
-
-
Save vlaleli/bfeb09ea633cf1f387191cd388532095 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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