многопоточность — передача данных в другой поток в приложении C ++ winsock

Итак, у меня есть это winsock приложение (сервер, способный принимать несколько клиентов), где в основном потоке я настраиваю сокет и создаю другой поток, где я слушаю клиентов (listen_for_clients функция).

Я также постоянно получаю данные от устройства в главном потоке, которые я впоследствии соединяю с массивами символов (буферами) Client объекты (BroadcastSample функция). В настоящее время я создаю поток для каждого подключенного клиента (ProcessClient функция), где я инициализирую Client объект и отправить его в глобальный вектор клиентов, после чего я посылаю данные этому клиенту через сокет всякий раз, когда буфер в соответствующем Client объект превышает 4000 символов.

Есть ли способ, которым я могу отправить данные из основного потока в отдельные клиентские потоки, чтобы мне не приходилось использовать структуры / классы (также для отправки зеленого индикатора, если я хочу отправить уже накопленные данные), а также если я ‘ Я собираюсь сохранить глобальный контейнер объектов, каков хороший способ удалить из него отключенный клиентский объект без сбоя программы, потому что другой поток использует тот же контейнер?

struct Client{
int buffer_len;
char current_buffer[5000];
SOCKET s;
};

std::vector<Client*> clientBuffers;

DWORD WINAPI listen_for_clients(LPVOID Param)
{
SOCKET client;
sockaddr_in from;
int fromlen = sizeof(from);
char buf[100];
while(true)
{
client = accept(ListenSocket,(struct sockaddr*)&from,&fromlen);
if(client != INVALID_SOCKET)
{
printf("Client connected\n");
unsigned dwThreadId;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ProcessClient, (void*)client, 0, &dwThreadId);
}
}

closesocket(ListenSocket);
WSACleanup();
ExitThread(0);
}

unsigned __stdcall ProcessClient(void *data)
{
SOCKET ClientSocket = (SOCKET)data;
Client * a = new Client();
a->current_buffer[0] = '\0';
a->buffer_len = 0;
a->s = ClientSocket;
clientBuffers.push_back(a);

char szBuffer[255];

while(true)
{
if(a->buffer_len > 4000)
{
send(ClientSocket,a->current_buffer,sizeof(a->current_buffer),0);
memset(a->current_buffer,0,5000);
a->buffer_len = 0;
a->current_buffer[0] = '\0';
}
}
exit(1);
}

//function below is called only in main thread, about every 100ms
void BroadcastSample(Sample s)
{
for(std::vector<Client*>::iterator it = clientBuffers.begin(); it !=  clientBuffers.end(); it++)
{
strcat((*it)->current_buffer,s.to_string);
(*it)->buffer_len += strlen(s.to_string);
}
}

3

Решение

Эта ссылка есть некоторая документация Microsoft по мьютексам в стиле MS (взаимная политика?).

Эта другая ссылка имеет некоторую общую информацию о мьютексах.

Мьютексы — это общий механизм защиты данных, доступ к которым осуществляется несколькими потоками. Существуют структуры данных со встроенной безопасностью потоков, но, по моему опыту, они обычно содержат предупреждения, которые вы в конечном итоге пропустите. Это только мои два цента.

Кроме того, для записи, вы не должны использовать strcat, а скорее strncat. Кроме того, если один из ваших потоков обслуживания клиентов обращается к одному из этих буферов после того, как strncat перезапишет старый '\0' но прежде чем он добавит новый, у вас будет переполнение буфера (чтение за концом выделенного буфера).

Мьютексы также решат вашу текущую проблему ожидания. В настоящее время я не нахожусь рядом с компилятором Windows, или я постараюсь помочь вам больше.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru