Skip to content

Instantly share code, notes, and snippets.

@Vinnik67
Created March 14, 2026 16:30
Show Gist options
  • Select an option

  • Save Vinnik67/4d74d3a0a908108e269333f03cf227ec to your computer and use it in GitHub Desktop.

Select an option

Save Vinnik67/4d74d3a0a908108e269333f03cf227ec to your computer and use it in GitHub Desktop.
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <string>
#include <windows.h>
#include <ws2tcpip.h>
using namespace std;
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
#define PAUSE 1
SOCKET ConnectSocket = INVALID_SOCKET;
string nickname; // глобальная переменная для ника
DWORD WINAPI Sender(void* param)
{
while (true)
{
string text;
cout << "Введите сообщение: ";
getline(cin, text);
// Формируем строку "ник: сообщение"
string message = nickname + ": " + text;
int iResult = send(ConnectSocket, message.c_str(), (int)message.size(), 0);
if (iResult == SOCKET_ERROR) {
cout << "Send error: " << WSAGetLastError() << "\n";
closesocket(ConnectSocket);
WSACleanup();
return 15;
}
else {
cout << "Отправлено: " << message << "\n";
Sleep(PAUSE);
}
}
return 0;
}
DWORD WINAPI Receiver(void* param)
{
while (true)
{
char answer[DEFAULT_BUFLEN];
int iResult = recv(ConnectSocket, answer, DEFAULT_BUFLEN, 0);
if (iResult > 0) {
answer[iResult] = '\0';
cout << "\nСообщение от сервера: " << answer << "\n";
}
else if (iResult == 0) {
cout << "Соединение с сервером закрыто.\n";
break;
}
else {
cout << "Receive error: " << WSAGetLastError() << "\n";
break;
}
}
return 0;
}
int main()
{
SetConsoleOutputCP(1251);
system("title CLIENT SIDE");
cout << "Введите ваш ник: ";
getline(cin, nickname);
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
cout << "Failed to initialize Winsock: " << iResult << "\n";
return 11;
}
addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
const char* ip = "localhost";
addrinfo* result = NULL;
iResult = getaddrinfo(ip, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
cout << "getaddrinfo failed: " << iResult << "\n";
WSACleanup();
return 12;
}
for (addrinfo* ptr = result; ptr != NULL; ptr = ptr->ai_next) {
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
cout << "Failed to create socket: " << WSAGetLastError() << "\n";
WSACleanup();
return 13;
}
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
cout << "Unable to connect to server!\n";
WSACleanup();
return 14;
}
CreateThread(0, 0, Sender, 0, 0, 0);
CreateThread(0, 0, Receiver, 0, 0, 0);
Sleep(INFINITE);
}
// !!! CLIENT SIDE: https://gist.github.com/sunmeat/068b8df3d7da02e6548ed53491989443
#define WIN32_LEAN_AND_MEAN // для пришвидшення процесу компіляції: https://stackoverflow.com/questions/11040133/what-does-defining-win32-lean-and-mean-exclude-exactly
#include <iostream>
#include <windows.h>
#include <ws2tcpip.h> // тип WSADATA; функції WSAStartup, WSACleanup та багато інших
using namespace std;
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015" // порт — це логічна конструкція, що ідентифікує конкретний процес або тип мережевої служби - https://en.wikipedia.org/wiki/Port_(computer_networking)
#define PAUSE 1
// прийом клієнтського сокета
SOCKET ClientSocket = INVALID_SOCKET;
DWORD WINAPI Sender(void* param)
{
while (true) {
// надаємо відповідь відправнику
char* answer = new char[200];
cout << "Будь ласка, введіть повідомлення для клієнта: ";
cin.getline(answer, 199);
cout << "процес сервера відправляє відповідь: " << answer << "\n";
int iSendResult = send(ClientSocket, answer, strlen(answer), 0); // функція send відправляє дані по з'єднаному сокету: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send
Sleep(PAUSE);
//////////////////////////////////////////////////////////////////////////////////////////////////////////
if (iSendResult == SOCKET_ERROR) {
cout << "відправка не вдалася з помилкою: " << WSAGetLastError() << "\n";
cout << "упс, відправка (send) відповідного повідомлення не відбулася ((\n";
closesocket(ClientSocket);
WSACleanup();
return 7;
}
else {
//cout << "байтів відправлено: " << iSendResult << "\n";
Sleep(PAUSE);
}
}
return 0;
}
DWORD WINAPI Receiver(void* param)
{
while (true) {
char message[DEFAULT_BUFLEN];
int iResult = recv(ClientSocket, message, DEFAULT_BUFLEN, 0); // функція recv використовується для читання вхідних даних: https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recv
message[iResult] = '\0';
if (iResult > 0) {
cout << "\nпроцес клієнта надіслав повідомлення: " << message << "\n";
Sleep(PAUSE);
//cout << "байтів отримано: " << iResult << "\n";
Sleep(PAUSE);
}
}
return 0;
}
int main()
{
SetConsoleOutputCP(1251);
system("title SERVER SIDE");
// cout << "процес сервера запущено!\n";
Sleep(PAUSE);
///////////////////////////////////////////////////////////////////////////////////////////////////////
// ініціалізація Winsock
WSADATA wsaData; // структура WSADATA містить інформацію про реалізацію Windows Sockets: https://docs.microsoft.com/en-us/windows/win32/api/winsock/ns-winsock-wsadata
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); // функція WSAStartup ініціалізує використання DLL Winsock процесом: https://firststeps.ru/mfc/net/socket/r.php?2
if (iResult != 0) {
cout << "WSAStartup не вдалося з помилкою: " << iResult << "\n";
cout << "підключення Winsock.dll пройшло з помилкою!\n";
return 1;
}
else {
// cout << "підключення Winsock.dll пройшло успішно!\n";
Sleep(PAUSE);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
struct addrinfo hints; // структура addrinfo використовується функцією getaddrinfo для зберігання інформації про хост-адресу: https://docs.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-addrinfoa
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET; // сімейство адрес Інтернет-протоколу версії 4 (IPv4)
hints.ai_socktype = SOCK_STREAM; // забезпечує послідовні, надійні, двосторонні потоки з'єднань з механізмом передачі даних
hints.ai_protocol = IPPROTO_TCP; // протокол TCP (Transmission Control Protocol). Це можливе значення, коли член ai_family є AF_INET або AF_INET6 і член ai_socktype є SOCK_STREAM
hints.ai_flags = AI_PASSIVE; // адреса сокета буде використовуватися в виклику функції "bind"
// отримання адреси та порту сервера
struct addrinfo* result = NULL;
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
cout << "getaddrinfo не вдалося з помилкою: " << iResult << "\n";
cout << "отримання адреси та порту сервера пройшло з помилкою!\n";
WSACleanup(); // функція WSACleanup завершує використання DLL Winsock 2 (Ws2_32.dll): https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-wsacleanup
return 2;
}
else {
// cout << "отримання адреси та порту сервера пройшло успішно!\n";
Sleep(PAUSE);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// створення SOCKET для підключення до сервера
SOCKET ListenSocket = INVALID_SOCKET;
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
cout << "socket не вдалося створити з помилкою: " << WSAGetLastError() << "\n";
cout << "створення сокета пройшло з помилкою!\n";
freeaddrinfo(result);
WSACleanup();
return 3;
}
else {
// cout << "створення сокета на сервері пройшло успішно!\n";
Sleep(PAUSE);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// налаштування сокета для прослуховування
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); // функція bind асоціює локальну адресу з сокетом: https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-bind
if (iResult == SOCKET_ERROR) {
cout << "bind не вдалося з помилкою: " << WSAGetLastError() << "\n";
cout << "внедрення сокета за IP-адресою пройшло з помилкою!\n";
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 4;
}
else {
// cout << "внедрення сокета за IP-адресою пройшло успішно!\n";
Sleep(PAUSE);
}
freeaddrinfo(result);
//////////////////////////////////////////////////////////////////////////////////////////////////////////
iResult = listen(ListenSocket, SOMAXCONN); // функція listen поміщає сокет у стан прослуховування для вхідного з'єднання: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-listen
if (iResult == SOCKET_ERROR) {
cout << "listen не вдалося з помилкою: " << WSAGetLastError() << "\n";
cout << "прослуховування від клієнта не почалося. щось пішло не так!\n";
closesocket(ListenSocket);
WSACleanup();
return 5;
}
else {
cout << "будь ласка, запустіть client.exe\n";
// тут можна було б запустити якийсь прелоадер в окремому потоці
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
ClientSocket = accept(ListenSocket, NULL, NULL); // функція accept дозволяє підключити вхідне з'єднання до сокета: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-accept
if (ClientSocket == INVALID_SOCKET) {
cout << "accept не вдалося з помилкою: " << WSAGetLastError() << "\n";
cout << "з'єднання з клієнтським додатком не встановлено! сумно!\n";
closesocket(ListenSocket);
WSACleanup();
return 6;
}
else {
// cout << "з'єднання з клієнтським додатком встановлено успішно!\n";
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// більше не потрібен серверний сокет
// closesocket(ListenSocket);
CreateThread(0, 0, Receiver, 0, 0, 0);
CreateThread(0, 0, Sender, 0, 0, 0);
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// завершення з'єднання, оскільки робота завершена
/*
iResult = shutdown(ClientSocket, SD_SEND); // функція shutdown вимикає відправку або отримання на сокеті: https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-shutdown
if (iResult == SOCKET_ERROR) {
cout << "shutdown не вдалося з помилкою: " << WSAGetLastError() << "\n";
cout << "упс, розрив з'єднання (shutdown) видав помилку ((\n";
closesocket(ClientSocket);
WSACleanup();
return 9;
}
else {
cout << "процес сервера припиняє свою роботу! до нових запусків! :)\n";
} */
// очищення
//closesocket(ClientSocket);
//WSACleanup();
Sleep(INFINITE);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment