首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

关于线程中调用select的有关问题

2012-01-19 
关于线程中调用select的问题DWORDWINAPInetProc(LPVOIDpParam){inti0PArmTheadParammontpmontp(PArmTh

关于线程中调用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,则轮训总汇带来等待。

热点排行