最近需要用VC设计一个数据采集系统。系统要求是这样的:多个数据采集模块通过WiFi与连接到无线路由器的主机进行通信。主机需要实时显示更新当前在线的所有数据采集模块。通过用户界面控制何时将数据从模块采集到主机。
我的思路是这样的:使用异步套接字,响应客户端连接消息,然后为每一个连接到主机的模块建立一个线程与模块进行交互。这些线程通过发送消息通知界面更新当前在线的模块状态。同时,这些线程接收用户对界面的操作消息,决定何时将数据采集过来并保存到文件。现在在线程接收界面控制的实现上有点疑问,我能想到的办法是,在子线程中使用select()函数实现对非阻塞的recv()操作,然后查询由用户操作而发送过来的控制消息。也就是用查询的方式等待接收界面控制消息和采集模块发送的消息。不知道能不能在子线程中用消息驱动的方式实现数据接收和消息接收,这样就不用查询的办法了,可以提高不少效率。我现在分比较少,请大家多原谅
我的思路是这样的:使用异步套接字,响应客户端连接消息,然后为每一个连接到主机的模块建立一个线程与模块进行交互。这些线程通过发送消息通知界面更新当前在线的模块状态。同时,这些线程接收用户对界面的操作消息,决定何时将数据采集过来并保存到文件。现在在线程接收界面控制的实现上有点疑问,我能想到的办法是,在子线程中使用select()函数实现对非阻塞的recv()操作,然后查询由用户操作而发送过来的控制消息。也就是用查询的方式等待接收界面控制消息和采集模块发送的消息。不知道能不能在子线程中用消息驱动的方式实现数据接收和消息接收,这样就不用查询的办法了,可以提高不少效率。我现在分比较少,请大家多原谅
2.没有窗口的程序,或者像直接在子线程做消息循环用WSAEventSelect线程消息通信可以用PostThreadMessage,我的博客里有篇文章
我想的流程是这样的:
主线程->创建监听线程->有终端连接过来,创建子线程与终端模块和用户界面交互。
现在的问题是,感觉在子线程中循环查询是否接收到消息和是否有用户操作通知消息太费资源,在连接的终端很多的时候估计效率很低。所以我想能不能实现这样的结果:有数据接收到消息或用户操作消息后触发子进程的回调函数进行消息处理。
请大侠多指教啊,分我可以再加的
WSAEventSelect可以在子线程中处理,它是用个while循环检测是否有数据到来.
FD_ZERO(&fdR);
FD_SET(sock, &fdR);
switch (select(sock + 1, &fdR, NULL, NULL, &timeout)) {
case -1:
break;
case 0:
break;
default:
if (FD_ISSET(sock, &fdR)) {
SockRet = recv(sock, RecvBuf, sizeof(RecvBuf), 0);
if (SOCKET_ERROR == SockRet) { // 有错误发生
AfxMessageBox("Socket error on receive!");
BreakFlag = 1;
break;
} else if (0 == SockRet) { // 套接字已经被关闭
AfxMessageBox("the connection has been gracefully closed!");
BreakFlag = 1;
break;
}
if ('\0' != RecvBuf[SockRet - 1]) {
RecvBuf[SockRet] = '\0';
}
sprintf(MsgBuf, "RecvRet = %d , Data = %s, Cnt = %ld", SockRet, RecvBuf, Cnt);
::PostMessage(hwnd, WM_RECVDATA, 0, (LPARAM)MsgBuf); // 向UI线程发送消息
sEcho = MsgBuf;
SockRet = send(sock, sEcho, sEcho.GetLength(), 0);
if (SOCKET_ERROR == SockRet) {
AfxMessageBox("Socket error on send");
BreakFlag = 1;
break;
} // if (SOCKET_ERROR == SockRet) {
} // if (FD_ISSET(sock, &fdR)) {
} // switch (select(sock + 1, &fdR, NULL, NULL, &timeout)) {
if (BreakFlag == 1) {
break; // 退出while循环
} // if (BreakFlag == 1)
Cnt ++;
if (100000 == Cnt) {
AfxMessageBox("Cnt == 100000");
Cnt = 0;
}
MSG msg;
if(PeekMessage(
&msg, // message information
NULL, // handle to window
0, // first message
0, // last message
PM_REMOVE // removal options
)) {
if (WM_WORKTHREADMSG == msg.message) {
AfxMessageBox((char*)msg.lParam);
} // if (WM_WORKTHREADMSG == msg.message) {
} // if(PeekMessage(
} // while (1) {这是我现在子线程的程序,用循环查询的方法接收数据和UI线程消息
你想在子线程中以消息方式响应那是不可能的,因为子线程没有窗口.
只能就想你上面做的不断查询套字节是否可读可写;或者是WSAEventSelect设置网络事件和事件对象关联起来,在死循环中用WSAEnumNetworkEvents函数便可获得到底发生了什么网络事件(FD_READ/FD_ACCEPT/FD_CLOSE等等)