У меня есть приложение winsock
(сервер, способный принимать несколько клиентов), где в основном потоке я настраиваю сокет и создаю другой поток, где я слушаю клиентов (listen_for_clients
функция).Передача данных в другой поток в приложении C++ winsock
Я также постоянно получаю данные с устройства в основном потоке, которое впоследствии конкатенация на массивы символов (буферы) объектов Client
(BroadcastSample
). В настоящее время я создаю поток для каждого подключенного клиента (ProcessClient
), где я инициализирую объект Client
и нажимаю его на глобальный вектор клиентов, после которого я отправляю данные этому клиенту через сокет, когда буфер в соответствующем объекте Client
превышает 4000 персонажи.
Есть ли способ отправить данные из основного потока в отдельные потоки клиентов, поэтому мне не нужно использовать structs/classes (также для отправки зеленого света, если я хочу отправить уже накопленные данные) и также, если я собираюсь хранить глобальный контейнер объектов, что является хорошим способом удалить отключенный клиентский объект из него без сбоев программы, потому что другой поток использует тот же контейнер?
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);
}
}
Какие темы для носок используются для вас? вызов 'send (socked, buffer, size, 0)' занимает много времени? Я не думаю, что вы что-то набираете, имея эти темы. – Jfevold
@ Jfevold: как правило, если у вас несколько клиентов, все операции ввода-вывода должны выполняться отдельными потоками или асинхронно. В противном случае один неудачный клиент мог бы привести все к кричащей остановке. –
Если вы используете достаточно недавнюю версию C++, вам, вероятно, следует использовать поддержку потоков, которая, без сомнения, включает поточно-безопасные очереди и т. П. Если вы хотите использовать Windows API, [заблокированные отдельные списки] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684121 (v = vs.85) .aspx) может быть подходящий вариант. –