Created
March 23, 2026 17:02
-
-
Save AriaEbervine/1cca744c4eabcb8c47506dbeec0061cd to your computer and use it in GitHub Desktop.
чат на TCP
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 <ws2tcpip.h> | |
| #include <iostream> | |
| #include <string> | |
| using namespace std; | |
| #pragma comment (lib, "Ws2_32.lib") | |
| #define MESSAGE_LENGTH 4096 | |
| #define SERVER_IP "127.0.0.1" | |
| #define SERVER_PORT "8888" | |
| SOCKET client_socket; | |
| string nick; | |
| DWORD WINAPI Sender(void* param) { | |
| while (true) { | |
| string query; | |
| getline(cin, query); | |
| send(client_socket, query.c_str(), query.size(), 0); | |
| } | |
| } | |
| DWORD WINAPI Receiver(void* param) { | |
| while (true) { | |
| char response[MESSAGE_LENGTH]; | |
| int result = recv(client_socket, response, MESSAGE_LENGTH, 0); | |
| if (result > 0) { | |
| response[result] = '\0'; | |
| cout << response << "\n"; | |
| } | |
| } | |
| } | |
| BOOL ExitHandler(DWORD what_happens) { | |
| switch (what_happens) { | |
| case CTRL_C_EVENT: | |
| case CTRL_BREAK_EVENT: | |
| case CTRL_CLOSE_EVENT: | |
| case CTRL_LOGOFF_EVENT: | |
| case CTRL_SHUTDOWN_EVENT: | |
| cout << "shutting down...\n"; | |
| Sleep(1000); | |
| send(client_socket, "off", 3, 0); | |
| return TRUE; | |
| default: | |
| return FALSE; | |
| } | |
| } | |
| int main() { | |
| SetConsoleCtrlHandler((PHANDLER_ROUTINE)ExitHandler, true); | |
| system("title Client"); | |
| WSADATA wsaData; | |
| int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); | |
| if (iResult != 0) { | |
| cout << "WSAStartup failed with error: " << iResult << "\n"; | |
| return 1; | |
| } | |
| addrinfo hints{}; | |
| hints.ai_family = AF_UNSPEC; | |
| hints.ai_socktype = SOCK_STREAM; | |
| hints.ai_protocol = IPPROTO_TCP; | |
| addrinfo* result = nullptr; | |
| iResult = getaddrinfo(SERVER_IP, SERVER_PORT, &hints, &result); | |
| if (iResult != 0) { | |
| cout << "getaddrinfo failed with error: " << iResult << "\n"; | |
| WSACleanup(); | |
| return 2; | |
| } | |
| addrinfo* ptr = nullptr; | |
| for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { | |
| client_socket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); | |
| if (client_socket == INVALID_SOCKET) { | |
| cout << "socket creation failed with error: " << WSAGetLastError() << "\n"; | |
| WSACleanup(); | |
| return 3; | |
| } | |
| iResult = connect(client_socket, ptr->ai_addr, (int)ptr->ai_addrlen); | |
| if (iResult == SOCKET_ERROR) { | |
| closesocket(client_socket); | |
| client_socket = INVALID_SOCKET; | |
| continue; | |
| } | |
| break; | |
| } | |
| freeaddrinfo(result); | |
| if (client_socket == INVALID_SOCKET) { | |
| cout << "Unable to connect to server!\n"; | |
| WSACleanup(); | |
| return 5; | |
| } | |
| cout << "Enter your nickname: "; | |
| getline(cin, nick); | |
| send(client_socket, nick.c_str(), nick.size(), 0); | |
| CreateThread(0, 0, Sender, 0, 0, 0); | |
| CreateThread(0, 0, Receiver, 0, 0, 0); | |
| Sleep(INFINITE); | |
| } |
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 <winsock2.h> | |
| #include <ws2tcpip.h> | |
| #include <iostream> | |
| #include <vector> | |
| #include <string> | |
| using namespace std; | |
| #define SERVER_PORT 8888 | |
| #define MAX_CLIENTS 25 | |
| #define MESSAGE_LENGTH 4096 | |
| #pragma comment(lib, "ws2_32.lib") | |
| SOCKET server_socket; | |
| vector<string> history; | |
| struct Client { | |
| SOCKET sock; | |
| string nick; | |
| }; | |
| Client clients[MAX_CLIENTS] = {}; | |
| int main() { | |
| setlocale(0, ""); | |
| system("title Server"); | |
| HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); | |
| SetConsoleTextAttribute(h, 10); | |
| cout << "server started.\n"; | |
| WSADATA wsa; | |
| if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { | |
| cout << "WSAStartup failed with error: " << WSAGetLastError() << "\n"; | |
| return 1; | |
| } | |
| if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { | |
| cout << "socket creation failed: " << WSAGetLastError() << "\n"; | |
| return 2; | |
| } | |
| sockaddr_in server{}; | |
| server.sin_family = AF_INET; | |
| server.sin_addr.s_addr = INADDR_ANY; | |
| server.sin_port = htons(SERVER_PORT); | |
| if (bind(server_socket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) { | |
| cout << "bind failed with error: " << WSAGetLastError() << "\n"; | |
| return 3; | |
| } | |
| listen(server_socket, MAX_CLIENTS); | |
| cout << "server waiting for connections...\nplease run one or more client applications.\n"; | |
| while (true) { | |
| fd_set readfds; | |
| FD_ZERO(&readfds); | |
| FD_SET(server_socket, &readfds); | |
| for (int i = 0; i < MAX_CLIENTS; i++) { | |
| if (clients[i].sock > 0) | |
| FD_SET(clients[i].sock, &readfds); | |
| } | |
| if (select(0, &readfds, NULL, NULL, NULL) == SOCKET_ERROR) { | |
| cout << "select failed with error: " << WSAGetLastError() << "\n"; | |
| return 4; | |
| } | |
| if (FD_ISSET(server_socket, &readfds)) { | |
| sockaddr_in address; | |
| int addrlen = sizeof(sockaddr_in); | |
| SOCKET new_socket = accept(server_socket, (sockaddr*)&address, &addrlen); | |
| if (new_socket == INVALID_SOCKET) { | |
| perror("accept"); | |
| continue; | |
| } | |
| int free_slot = -1; | |
| for (int i = 0; i < MAX_CLIENTS; i++) { | |
| if (clients[i].sock == 0) { | |
| free_slot = i; | |
| break; | |
| } | |
| } | |
| if (free_slot != -1) { | |
| clients[free_slot].sock = new_socket; | |
| clients[free_slot].nick = ""; | |
| for (const string& msg : history) { | |
| send(new_socket, msg.c_str(), msg.size(), 0); | |
| } | |
| char ip_str[INET_ADDRSTRLEN]; | |
| inet_ntop(AF_INET, &address.sin_addr, ip_str, INET_ADDRSTRLEN); | |
| cout << "new connection, socket fd: " << new_socket | |
| << ", ip: " << ip_str | |
| << ", port: " << ntohs(address.sin_port) << "\n"; | |
| cout << "added to socket list at index " << free_slot << "\n"; | |
| } else { | |
| cout << "Maximum clients reached, connection rejected.\n"; | |
| closesocket(new_socket); | |
| } | |
| } | |
| for (int i = 0; i < MAX_CLIENTS; i++) { | |
| SOCKET s = clients[i].sock; | |
| if (s > 0 && FD_ISSET(s, &readfds)) { | |
| char buffer[MESSAGE_LENGTH]; | |
| int len = recv(s, buffer, MESSAGE_LENGTH, 0); | |
| if (len <= 0) { | |
| cout << "client #" << i << " disconnected\n"; | |
| closesocket(s); | |
| clients[i].sock = 0; | |
| clients[i].nick = ""; | |
| continue; | |
| } | |
| buffer[len] = '\0'; | |
| string msg(buffer); | |
| if (msg == "off") { | |
| cout << "client #" << i << " disconnected\n"; | |
| clients[i].sock = 0; | |
| clients[i].nick = ""; | |
| continue; | |
| } | |
| if (clients[i].nick.empty()) { | |
| clients[i].nick = msg; | |
| cout << "client #" << i << " set nickname: " << msg << "\n"; | |
| } else { | |
| string full_msg = clients[i].nick + ": " + msg + "\n"; | |
| history.push_back(full_msg); | |
| for (int j = 0; j < MAX_CLIENTS; j++) { | |
| if (clients[j].sock != 0) { | |
| send(clients[j].sock, full_msg.c_str(), full_msg.size(), 0); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| WSACleanup(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment