Почему при групповой рассылке, при отправке клиентом сообщение, оно приходит только серверу, а не всем клиентам? C++
Проблема заключается в том, что я отправляю клиентом сообщение на сервер, он его получает, и также работает наоборот. Но когда я запускаю еще одного клиента, сообщение приходит только серверу, а не всем клиентам группы. Можете подсказать, пожалуйста, в чем может быть проблема?
Server:
#include "Headers.h"
DWORD WINAPI ReceiveMess(LPVOID lpParameter);
int main()
{
WinSockInitializer* initializer = nullptr;
HANDLE hEvent = CreateEvent(NULL, FALSE /* ручной сброс события */, FALSE /* несигнальное состояние */, TEXT("{2BA7C99B-D9F7-4485-BB3F-E4735FFEF1789}"));
try {
initializer = WinSockInitializer::GetInstance();
UDPClient* client = new UDPClient;
cout << "Client started" << endl;
client->SetName();
char ip[50];
cout << "Enter an ip: ";
cin >> ip;
int port;
cout << "Enter a port: ";
cin >> port;
client->bind(ip, port);
char groupIp[255];
cout << "Enter a group ip: ";
cin >> groupIp;
client->setsockopt(groupIp);
HANDLE hReceiveMess = CreateThread(NULL, 0, ReceiveMess, client, 0, NULL);
CloseHandle(hReceiveMess);
if (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0)
{
while (true)
{
char request[1024] = "";
char text[1024] = "";
_getch();
cout << "Enter request text: ";
cin.ignore();
cin.getline(text, 1024);
sprintf_s(request, "Client %s: %s", client->GetName(), text);
if (strstr(request, "EXIT") != 0)
{
break;
}
client->sendto(request, strlen(request) + 1, client->GetAddrFrom());
}
}
client->shutdown();
delete initializer;
delete client;
}
catch (SocketException& ex)
{
cout << ex.what() << endl;
if (initializer != nullptr)
{
delete initializer;
}
}
system("pause");
}
DWORD __stdcall ReceiveMess(LPVOID lpParameter)
{
HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, 0, TEXT("{2BA7C99B-D9F7-4485-BB3F-E4735FFEF1789}"));
UDPClient* client = (UDPClient*)lpParameter;
while (true)
{
try
{
client->recvfrom();
cout << client->GetRecvbuf() << endl;
}
catch (...)
{
cout << "ERROR R:" << WSAGetLastError() << endl;
cout << client->GetRecvbuf() << endl;
}
SetEvent(hEvent);
}
delete client;
return 0;
}
Client:
#pragma comment(lib, "UDPSockets.lib")
#include "Headers.h"
DWORD WINAPI ReceiveMess(LPVOID lpParameter);
int main()
{
HANDLE hEvent = CreateEvent(NULL, FALSE /* ручной сброс события */, TRUE /* сигнальное состояние */, TEXT("{2BA7C99B-D9F7-4485-BB3F-E4735FFEF1589}"));
WinSockInitializer* initializer = nullptr;
try {
initializer = WinSockInitializer::GetInstance();
UDPClient* client = new UDPClient;
cout << "Client started" << endl;
client->SetName();
char ip[50];
cout << "Enter an ip: ";
cin >> ip;
int port;
cout << "Enter a port: ";
cin >> port;
_addrTo.sin_family = AF_INET;
_addrTo.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &_addrTo.sin_addr.s_addr);
HANDLE hReceiveMess = CreateThread(NULL, 0, ReceiveMess, client, 0, NULL);
CloseHandle(hReceiveMess);
while (true)
{
char request[1024] = "";
char text[1024] = "";
_getch();
cout << "Enter request text: ";
cin.ignore();
cin.getline(text, 1024);
sprintf_s(request, "Client %s: %s", client->GetName(), text);
if (strstr(request, "EXIT") != 0)
{
break;
}
client->sendto(request, strlen(request) + 1, client->GetAddrTo());
}
client->shutdown();
delete initializer;
delete client;
}
catch (SocketException& ex)
{
cout << ex.what() << endl;
if (initializer != nullptr)
{
delete initializer;
}
}
system("pause");
}
DWORD __stdcall ReceiveMess(LPVOID lpParameter)
{
HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, 0, TEXT("{2BA7C99B-D9F7-4485-BB3F-E4735FFEF1589}"));
UDPClient* client = (UDPClient*)lpParameter;
while (true)
{
try
{
client->recvfrom();
cout << client->GetRecvbuf() << endl;
}
catch (...)
{
//cout << "ERROR R:" << WSAGetLastError() << endl;
//cout << client->GetRecvbuf() << endl;
}
}
delete client;
return 0;
}
Методы:
void UDPClient::bind(string ipAddress, unsigned short port)
{
//инициализация структуры для указания ip адреса и порта, с которым мы хотим соединиться
_addrTo.sin_family = AF_INET;
_addrTo.sin_port = htons(port);
//inet_pton(AF_INET, ipAddress.c_str(), &_addrTo.sin_addr.s_addr);
_addrTo.sin_addr.s_addr = htonl(INADDR_ANY);
if (::bind(_clientSocket, (SOCKADDR*)&_addrTo, sizeof(_addrTo)) != NO_ERROR)
{
throw SocketException("bind failed with error ");
}
}
void UDPClient::setsockopt(char* groupIp)
{
inet_pton(AF_INET, groupIp, &_mreq.imr_multiaddr.s_addr);
_mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (::setsockopt(_clientSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&_mreq, sizeof(_mreq)) != NO_ERROR)
{
throw SocketException("socket failed with error: ");
}
}
void UDPClient::recvfrom()
{
int addrFromSize = sizeof(_addrFrom);
int result = ::recvfrom(_clientSocket, _recvbuf, 1024, 0, (SOCKADDR*)&_addrFrom, &addrFromSize);
if (result == SOCKET_ERROR)
{
throw SocketException("recvfrom failed with error ");
}
}
void UDPClient::sendto(char* request, size_t length, sockaddr_in addr)
{
try
{
int sendResult = ::sendto(_clientSocket, request, length, 0, (SOCKADDR*)&addr, sizeof(addr));
if (sendResult == SOCKET_ERROR)
{
throw SocketException("send failed: ");
}
}
catch (...)
{
cout << "ERROR S" << endl;
}
}