我想做一个C/S模式的小游戏,打算使用socket通信,客户端需要不断的扫描看看有没有服务器发送来的数据。我现在起了一个线程去监听是不是有发送来的数据(是一个死循环)大致代码如下:
while(true)
{
    recv(……);
    if(strcmp(csRecvMsg , "") == 0)
        do sth.
}
可是我发现这样的系统资源会被大量的消耗。
请问各位有没有什么好办法既能扫描数据,又不消耗资源?
有代码更好,THANKS!!!

解决方案 »

  1.   

    不会吧。你居然用死循环来检测有没有数据发送过来?当有数据发送过来时,socket是能够自己响应的。
      

  2.   

    soket分阻塞连接和非阻塞连接如果是阻塞连接,函数在操作完成后才返回,所以上述代码就不是死循环,正常情况也是这么做的,非阻塞连接的话,函数调用后立即返回,上述代码就是死循环。
    为了解决这么问题,Microsoft提供了几个宏,FD_SET,FD_WRITE,FD_READ等来检查,这些资料在一般的winsock编程的电子书里面都有,建议去看看,或许能解决你的问题。
      

  3.   

    while(true)
    {
        recv(……);
        if(strcmp(csRecvMsg , "") == 0)
            do sth.
    }
    死循环,把资源都占掉了
    当然可以设为把socket非阻塞,或者换成异步模式
      

  4.   

    use select to set asynchronism or use CAsyncSocket::OnRecv method
      

  5.   

    开线程做一个循环侦听
    实现asynchronism
      

  6.   

    多线程的解决例子:服务器代码:
    #include <windows.h>
    #include <winsock.h>typedef struct
    {
    int a,b;
    int res;
    }PARAM;DWORD CALLBACK ServiceThread(LPVOID p)
    {
    SOCKET  sock = (SOCKET)p;
    PARAM   param;
    int     size;
    int     len,recvlen,sendlen;

    size = sizeof(PARAM); while (true)
    {
    //接收客户数据
    recvlen = 0;
    while (recvlen != size)
    {
    len = recv(sock,((char *)&param) + recvlen,size - recvlen,0);
    if (len != SOCKET_ERROR)
    recvlen += len;
    else
    {
    printf("receive error: %d\n",WSAGetLastError());
    closesocket(sock);
    return 0;
    }
    }
    if (param.a == 0 && param.b == 0)//两个数都为零表示退出
    {
    printf("A Client Leave\n");
    closesocket(sock);
    return 0;
    }
    param.res = param.a + param.b;
    //发送处理结果
    sendlen = 0;
    while (sendlen != size)
    {
    len = send(sock,(char *)&param + sendlen,size - sendlen,0);
    if (len != SOCKET_ERROR)
    sendlen += len;
    else
    {
    printf("send error: %d\n",WSAGetLastError());
    closesocket(sock);
    return 0;
    }
    }
    }
    }int main(int argc, char* argv[])
    {
    SOCKET server,client;
    SOCKADDR_IN  addr;
    int    addrlen;
    DWORD  dwID; WSADATA  WSAData;    
    if (WSAStartup(MAKEWORD(2,0),&WSAData))
    {  
    printf("Errot to Start WinSock!\n");
    return 0;  
    }      

    addrlen = sizeof(SOCKADDR_IN); server = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    addr.sin_family  = AF_INET;
    addr.sin_addr.S_un.S_addr = INADDR_ANY;
    addr.sin_port    = 8000;;

    bind(server,(SOCKADDR *)&addr,sizeof(SOCKADDR_IN));     

    listen(server,10);
    printf("Listening......");
    while (true)
    {
    client = accept(server,(SOCKADDR *)&addr,&addrlen);
    if (client !=  INVALID_SOCKET)
    {
    printf("\nAccept a client");
    CreateThread(NULL,0,ServiceThread,(LPVOID)client,0,&dwID);
    }
    Sleep(100);
    }
    WSACleanup();
    return 0; 
    }
    客户端代码:
    #include <windows.h>
    #include <winsock.h>typedef struct
    {
    int a,b;
    int res;
    }PARAM;int main(int argc, char* argv[])
    {
    SOCKET client;
    SOCKADDR_IN  addr;
    PARAM  param;

    WSADATA  WSAData;    
    if (WSAStartup(MAKEWORD(2,0),&WSAData))
    {  
    printf("Errot to Start WinSock!\n");
    return 0;  
    }      

    client = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    addr.sin_family  = AF_INET;
    addr.sin_port    = 8000;
    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    printf("Connecting......");
    if (SOCKET_ERROR != connect(client,(SOCKADDR *)&addr,sizeof(SOCKADDR_IN)))
    {
    printf("OK!\n");
    while (true)
    {
    printf("Enter a & b(0 & 0 to Exit):   ");
    scanf("%d%d",&param.a,&param.b); send(client,(char *)&param,sizeof(PARAM),0);
    if (param.a == 0 && param.b == 0) break;
    recv(client,(char *)&param,sizeof(PARAM),0);
    printf("Server Reply:   %d\n",param.res);
    }
    }
    else
    printf("Failed!\n");
    closesocket(client);
    WSACleanup();
    return 0;
    }
    说明:客户端连接到服务器后,发送两个整数给服务器,服务器求出它们的和,返回给客户端。
          服务器对每个客户使用一个服务线程。
      

  7.   


    异步模式例子:客户端代码不变,服务器代码:
    #include <windows.h>
    #include <winsock2.h>#define MAX_CLIENT 64typedef struct _CLIENT
    {
    int          no;
    SOCKET       sock;
    HANDLE       hEvent;
    }CLIENT;typedef struct
    {
    int a,b;
    int res;
    }PARAM;BOOL ProcessClientRequest(SOCKET sock)
    {
    PARAM   param;
    int     size;
    int     len,recvlen,sendlen;

    size = sizeof(PARAM);
    //接收客户数据
    recvlen = 0;
    while (recvlen != size)
    {
    len = recv(sock,((char *)&param) + recvlen,size - recvlen,0);
    if (len != SOCKET_ERROR)
    recvlen += len;
    else
    {
    printf("receive error: %d\n",WSAGetLastError());
    closesocket(sock);
    return FALSE;
    }
    }
    if (param.a == 0 && param.b == 0)//两个数都为零表示退出
    {
    printf("A Client Leave\n");
    closesocket(sock);
    return TRUE;
    }
    param.res = param.a + param.b;
    //发送处理结果
    sendlen = 0;
    while (sendlen != size)
    {
    len = send(sock,(char *)&param + sendlen,size - sendlen,0);
    if (len != SOCKET_ERROR)
    sendlen += len;
    else
    {
    printf("send error: %d\n",WSAGetLastError());
    closesocket(sock);
    return FALSE;
    }
    }
    return TRUE;
    }int main(int argc, char* argv[])
    {
    SOCKET server,clientsock;
    SOCKADDR_IN  addr;
    int    addrlen; int     i,nClient;
    DWORD   dwWaitResult;
    HANDLE  hEvent[MAX_CLIENT];
    CLIENT  client[MAX_CLIENT];
    WSADATA  WSAData;     if (WSAStartup(MAKEWORD(2,0),&WSAData))
    {  
    printf("Errot to Start WinSock!\n");
    return 0;  
    }      

    addrlen = sizeof(SOCKADDR_IN); server = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    addr.sin_family  = AF_INET;
    addr.sin_addr.S_un.S_addr = INADDR_ANY;
    addr.sin_port    = 8000;;
    bind(server,(SOCKADDR *)&addr,sizeof(SOCKADDR_IN));     

    nClient = 1;  //第一个Client实际上指服务监听套接字
    hEvent[0] = CreateEvent(NULL,FALSE,FALSE,NULL);
    WSAEventSelect(server,hEvent[0],FD_ACCEPT);
    listen(server,10);
    printf("Listening......");
    while (true)
    {
    dwWaitResult = ::WaitForMultipleObjects(nClient,hEvent,FALSE,10);
    if (dwWaitResult >= WAIT_OBJECT_0 && dwWaitResult < WAIT_OBJECT_0 + nClient)
    {
    int no;
    no = dwWaitResult - WAIT_OBJECT_0;
    if (no == 0)
    {
    clientsock = accept(server,(SOCKADDR *)&addr,&addrlen);
    if (clientsock !=  INVALID_SOCKET)
    {
    client[nClient].no     = nClient;
    client[nClient].sock   = clientsock;
    client[nClient].hEvent = hEvent[nClient] = CreateEvent(NULL,FALSE,FALSE,NULL);
    WSAEventSelect(clientsock,client[nClient].hEvent,FD_READ);
    nClient++;
    printf("\nAccept a client");
    }
    }
    else
    {
    clientsock = client[no].sock;
    ProcessClientRequest(clientsock);
    }
    }
    } for(i = 0; i < nClient; i++)
    {
    CloseHandle(client[i].hEvent);
    closesocket(client[i].sock);
    }
    WSACleanup();
    return 0; 
    }说明:从上面的线程解决方法修改而来,实现同样的功能。有数据可读的时候,系统触发一个事件。
          程序只需要等待事件就行了。