Нашёл на ютубе пример минимального консольного чата на WinSock. Там в примере к серверу может подключаться только один клиент. Скопипастил код и скомпилировал - работает.
Но вот что странно. Если дописать код, который будет в цикле слать серверу сообщения, то на сервере они очень часто перемешиваются. То есть, несколько отправленных сообщений обрабатываются сервером как одно целое.
Код сервера:
#include <iostream>
#include <WS2tcpip.h>
#pragma comment (lib, "ws2_32.lib")
int main()
{
WSAData wsaData;
unsigned short winsockVersion = MAKEWORD(2, 2);
int wsaInitCode = WSAStartup(winsockVersion, &wsaData);
if (wsaInitCode)
{
std::cerr << "WSAStartup() failed! Code " << wsaInitCode << std::endl;
return 1;
}
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, NULL);
if (serverSocket == 0 || serverSocket == INVALID_SOCKET)
{
std::cerr << "Failed to create a socket!" << std::endl;
WSACleanup();
return 1;
}
const int PORT = 54000;
sockaddr_in serverAddress;
ZeroMemory(&serverAddress, sizeof(sockaddr_in));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.S_un.S_addr = INADDR_ANY;
serverAddress.sin_port = htons(PORT);
if (bind(serverSocket, (sockaddr*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR)
{
std::cerr << "Failed to bind a socket!" << std::endl;
closesocket(serverSocket);
WSACleanup();
return 1;
}
if (listen(serverSocket, SOMAXCONN) == SOCKET_ERROR)
{
std::cerr << "Failed to listen a socket!" << std::endl;
closesocket(serverSocket);
WSACleanup();
return 1;
}
std::cout << "Server is started on port " << PORT << std::endl;
bool active = true;
while (active)
{
sockaddr_in clientAddress;
int clientAddressSize = sizeof(clientAddress);
SOCKET clientSocket = accept(serverSocket, (sockaddr*)&clientAddress, &clientAddressSize);
char host[NI_MAXHOST];
char service[NI_MAXSERV];
ZeroMemory(&host, sizeof(host));
ZeroMemory(&service, sizeof(service));
if (getnameinfo((sockaddr*)&clientAddress, clientAddressSize, host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
std::cout << host << " connected on port " << service << std::endl;
}
else
{
inet_ntop(AF_INET, &clientAddress.sin_addr, host, NI_MAXHOST);
std::cout << host << " connected on port " << htons(clientAddress.sin_port) << std::endl;
}
const int BUFFER_SIZE = 4096;
char* buffer = (char*)_malloca(sizeof(char) * BUFFER_SIZE);
if (buffer)
{
while (true)
{
ZeroMemory(buffer, BUFFER_SIZE);
int bytesReceived = recv(clientSocket, buffer, BUFFER_SIZE, 0);
if (bytesReceived == SOCKET_ERROR)
{
std::cerr << "recv() failed!" << std::endl;
closesocket(clientSocket);
break;
}
std::cout << "Received: " << buffer << std::endl;
send(clientSocket, buffer, bytesReceived + 1, 0);
if (bytesReceived == 1 && buffer[0] == 'q')
{
std::cout << "The QUIT command received! Quitting!" << std::endl;
active = false;
break;
}
if (bytesReceived == 1 && buffer[0] == 'z')
{
std::cout << "Disconnecting the client!" << std::endl;
break;
}
}
_freea(buffer);
}
closesocket(clientSocket);
}
closesocket(serverSocket);
WSACleanup();
return 0;
}
Код клиента:
#include <iostream>
#include <string>
#include <WS2tcpip.h>
#pragma comment (lib, "ws2_32.lib")
int main()
{
WSAData wsaData;
unsigned short winsockVersion = MAKEWORD(2, 2);
int wsaInitCode = WSAStartup(winsockVersion, &wsaData);
if (wsaInitCode)
{
std::cerr << "WSAStartup() failed! Code " << wsaInitCode << std::endl;
return 1;
}
const int PORT = 54000;
const char* IP = (char*)"*.*.*.*";
sockaddr_in serverAddress;
ZeroMemory(&serverAddress, sizeof(sockaddr_in));
serverAddress.sin_family = AF_INET;
in_addr ipAddr;
if (inet_pton(AF_INET, IP, &ipAddr) <= 0)
{
std::cerr << "Failed to parse an IP address!" << std::endl;
WSACleanup();
return 1;
}
serverAddress.sin_addr = ipAddr;
serverAddress.sin_port = htons(PORT);
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, NULL);
if (clientSocket == 0 || clientSocket == INVALID_SOCKET)
{
std::cerr << "Failed to create a socket!" << std::endl;
WSACleanup();
return 1;
}
if (connect(clientSocket, (sockaddr*)&serverAddress, sizeof(sockaddr)) == SOCKET_ERROR)
{
std::cerr << "Connection failed!" << std::endl;
closesocket(clientSocket);
WSACleanup();
return 1;
}
while (true)
{
std::string msg = "Fuck you!\0";
int len = msg.length();
if (send(clientSocket, msg.c_str(), len, 0) == SOCKET_ERROR)
{
break;
}
Sleep(1);
}
send(clientSocket, "z", 1, 0);
Sleep(1);
closesocket(clientSocket);
WSACleanup();
return 0;
}
Если идти по циклу отправки дебаггером, то видно, что на строчке send
он не задерживается. То есть, функция send
выполняется и выполнение сразу идёт дальше. При этом, в консоли сервера видно, что сообщение он ещё не получил (или не успел обработать). Хотя, чего там обрабатывать? 9 символов + служебный трафик.
Должна приходить вот такая строка:
Received: Fuck you!
Но очень часто приходит такое:
MY_HOST connected on port 52519
Received: Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!F}чe!╧
Received: uck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!Fuck you!
Received: Fuck you!
Received: Fuck you!
Received: Fuck you!
Received: Fuck you!
Received: Fuck you!
Received: Fuck you!
Received: Fuck you!
Received: Fuck you!
Это момент, когда вижуалка только что загрузила клиент в дебаггере и там на фоне ещё всякие средства диагностики грузятся и т.п.
А когда всё уже загружено, то слепляет меньше. Но всё-равно неприятно. Увеличение задержки между отправками не помогает. При этом не важно, где находится сервер - на localhost
или в соседнем здании.
Когда-то давно уже была такая же проблема с сокетами TServerSocket
/ TClientSocket
на Delphi. Там я каждую секунду передавал клиентам информацию о свободном месте на жёстких дисках. И сообщения тоже довольно часто смешивались.