关于线程中调用select的问题
DWORD WINAPI netProc(LPVOID pParam)
{
int i = 0;
PArmTheadParam montp;
montp = (PArmTheadParam)pParam;
int res;
char recvBuf[100];
while (!b_stopFlag)
{
for(i = 0;i < montp-> GunNum ; i++)
{
fd_set fdRead;
timeval mWaitTime;
mWaitTime.tv_sec = 1;
mWaitTime.tv_usec = 0;
memset(recvBuf,0,100);
memset(Buf,0,250);
FD_ZERO(&fdRead);
FD_SET(montp-> s[i],&fdRead);
res = select((montp-> s[i])+1,&fdRead,NULL,NULL,&mWaitTime);
if(res > 0)
{
if(FD_ISSET(montp-> s[i],&fdRead))
{
recv(montp-> s[i],recvBuf,22,0);
GUNSTATE GunState;
memcpy(&GunState,recvBuf+17,5);
//如果任何一个模块有异常,则返回模块异常
if((GunState. mGS[0].MState== 0) || (GunState.mGS[1].MState == 0)|| (GunState.mGS[2].MState == 0) || (GunState.mGS[3].MState == 0))
{
// closesocket(montp-> s[i]);
// WSACleanup();
COPYDATASTRUCT cpd; /*给COPYDATASTRUCT结构赋值*/
cpd.dwData = GUN_MSTATE_ERROR;
cpd.cbData = 4;
cpd.lpData = (PVOID)&(montp-> beginAddr[i]);
SendMessage(montp-> recvHd,WM_COPYDATA,(WPARAM)(montp-> threadHd),(LPARAM)&cpd);//消息处理函数
}
if(recvBuf[10] == 0x01)
{
COPYDATASTRUCT cpd; /*给COPYDATASTRUCT结构赋值*/
cpd.dwData = GUN_GATE_CHANGED;
cpd.cbData = 4;
cpd.lpData = (PVOID)&(montp-> beginAddr[i]);
SendMessage(montp-> recvHd,WM_COPYDATA,(WPARAM)(montp-> threadHd),(LPARAM)&cpd);
}
if(recvBuf[10] == 0x02)
{
int j ,k;
for(j = 0 ;j < 4 ; j++)
{
for(k = 0 ; k < 6;k++)
{
//memcpy(Buf+30*j+5*k,&(montp-> beginAddr[i]),4);
Buf[30*j+5*k] = (char)((montp-> beginAddr[i]) & 0xff);
Buf[30*j+5*k+1] = (char)(((montp-> beginAddr[i])> > 8)& 0xff);
Buf[30*j+5*k+2] = (char)(((montp-> beginAddr[i])> > 16)& 0xff);
Buf[30*j+5*k+3] = (char)(((montp-> beginAddr[i])> > 24)& 0xff);
Buf[30*j+5*(k+1)-1] = (GunState.mGS[j].GS > > k)& 1;
montp-> beginAddr[i]++;
}
}
montp-> beginAddr[i] = montp-> beginAddr[i] - 24 ;
if(montp-> recvHd != NULL)
{
COPYDATASTRUCT cpd; /*给COPYDATASTRUCT结构赋值*/
cpd.dwData = GUN_STATUS_CHANGED;
cpd.cbData = 120;
cpd.lpData = (PVOID)Buf;
SendMessage(montp-> recvHd,WM_COPYDATA,(WPARAM)(montp-> threadHd),(LPARAM)&cpd);//消息处理函数
}
}
}
}
Sleep(100);
}
}
COPYDATASTRUCT cpd; /*给COPYDATASTRUCT结构赋值*/
cpd.dwData = MSG_COPYDATA_STOP;
cpd.cbData = 0;
cpd.lpData = NULL;
SendMessage(montp-> recvHd,WM_COPYDATA,(WPARAM)(montp-> threadHd),(LPARAM)&cpd);
b_threadRunning = FALSE;
CloseHandle(hThread);
for(i = 0;i < montp-> GunNum;i++)
{
closesocket(montp-> s[i]);
}
WSACleanup();
ExitThread(0);
return 0;
}
NETGUNCABDLL_API int NetStartMonitor(unsigned long *netIp, unsigned short netPort,int GunNum,unsigned long *beginAddr,HWND recvHd ,HANDLE *threadHd)
{
DWORD tId;
PArmTheadParam pMontp; // 设置传入参数
pMontp = new _ArmThreadParam;
pMontp-> GunNum = GunNum;
pMontp-> netPort = netPort;
pMontp-> recvHd = recvHd;
int i;
for(i = 0;i < GunNum; i++)
{
pMontp-> netIp[i] = netIp[i];
pMontp-> beginAddr[i] = beginAddr[i];
}
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2,2); //初始化socket链接的版本号
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
return STARTUP_FAILED;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup();
return VERSION_FAILED;
}
SOCKET s[256];
for(i = 0;i < GunNum;i++)
{
if((s[i] = socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR) //生成SOCKET
{
closesocket(s[i]);
WSACleanup();
return CREATESOCKET_ERROR;
}
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = netIp[i];
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(netPort);
if(connect(s[i],(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)) == SOCKET_ERROR) //连接socket
{
closesocket(s[i]);
WSACleanup();
return CONNECT_ERROR;
}
pMontp-> s[i] = s[i];
}
*threadHd = CreateThread(NULL,0,netProc,(LPVOID)pMontp,CREATE_SUSPENDED,&tId); //线程挂起
if(*threadHd == NULL)
{
return CREATE_THREAD_FAILED;
}
pMontp-> threadHd = *threadHd;
b_threadRunning = true;
ResumeThread(*threadHd); // 线程运行
delete pMontp;
return 0;
}
我这是一个线程中希望调用select判断是否有数据可读的情况,按照需要由于需要轮询多个socket,所以设置了超时,但是我始终不能接收到数据,希望高手指教一下,这个函数哪里除了问题。
[解决办法]
首先,我看你的程序中有一段:
if(connect(s[i],(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)) == SOCKET_ERROR) //
{
closesocket(s[i]);
WSACleanup();
return CONNECT_ERROR;
}
那么连接中如果出现错误,那么线程函数就不会调用,你调试以下看看这里是否出现了问题
[解决办法]
mWaitTime改长些试试
[解决办法]
wzbhbb(灯火阑珊) 的方法可以同时盯着5个socket。理论上可以同时盯着64个。如果要轮训更多的,则把超时设成0:
mWaitTime.tv_sec = 0;
mWaitTime.tv_usec = 0;
但是这样又带来问题,所有的SOCKET轮训后如果立即又轮训,那么CPU是不是占用太多?如果超时不设成0,则轮训总汇带来等待。