将数据传递给 C++ winsock 应用程序中的另一个线程
Passing data to another thread in a C++ winsock app
所以我有这个 winsock
应用程序(一个服务器,能够接受多个客户端),在主线程中我设置套接字并创建另一个线程,我在其中监听客户端(listen_for_clients
功能)。
我还不断地从主线程中的设备接收数据,然后将其连接到 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] = '[=10=]';
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] = '[=10=]';
}
}
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);
}
}
This link 有一些关于 MS 风格互斥体(muticies?)的 Microsoft 文档。
This other link 有一些关于互斥量的一般信息。
互斥锁是保护被多线程访问的数据的通用机制。有内置线程安全的数据结构,但根据我的经验,它们通常有你最终会错过的警告。那只是我的两分钱。
此外,郑重声明,您不应使用 strcat,而应使用 strncat。此外,如果您的客户端服务线程之一在 strncat 覆盖旧的 '[=10=]'
之后但在附加新的之前访问这些缓冲区之一,您将有一个缓冲区重读(读取已分配缓冲区的末尾)。
互斥体也将解决您当前的忙等待问题。我目前不在 windows 编译器附近,否则我会尽力提供更多帮助。
所以我有这个 winsock
应用程序(一个服务器,能够接受多个客户端),在主线程中我设置套接字并创建另一个线程,我在其中监听客户端(listen_for_clients
功能)。
我还不断地从主线程中的设备接收数据,然后将其连接到 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] = '[=10=]';
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] = '[=10=]';
}
}
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);
}
}
This link 有一些关于 MS 风格互斥体(muticies?)的 Microsoft 文档。
This other link 有一些关于互斥量的一般信息。
互斥锁是保护被多线程访问的数据的通用机制。有内置线程安全的数据结构,但根据我的经验,它们通常有你最终会错过的警告。那只是我的两分钱。
此外,郑重声明,您不应使用 strcat,而应使用 strncat。此外,如果您的客户端服务线程之一在 strncat 覆盖旧的 '[=10=]'
之后但在附加新的之前访问这些缓冲区之一,您将有一个缓冲区重读(读取已分配缓冲区的末尾)。
互斥体也将解决您当前的忙等待问题。我目前不在 windows 编译器附近,否则我会尽力提供更多帮助。