当recv()不是预期的字节数

时间:2015-11-18 10:56:16

标签: c client-server winsock

我在C中有一个必须读取数据并处理它的服务器端应用程序。现在它处理两条消息:将屏幕截图发送到客户端并单击鼠标。在调试时我发现它在客户端询问屏幕截图时收到16个字节,但是当我发送单击鼠标消息时,服务器收到32个字节并挂起。为什么会发生这种情况以及如何正确处理所有传入的数据包?我是winsock的新手,并没有太多解释信息或示例如何处理野外数据。这是服务器的主要代码:

struct coord
{
    int x;
    int y;
};


struct send_packet
{
    int magic;
    int cmd;
    coord Coords;
};


struct recv_packet
{
    int magic;
    int code;
    int length;
    BYTE body[0];

};
do
        {
            ZeroMemory(&buff, BUFLEN);
            int numRcvBytes = 0;
            while (numRcvBytes < sizeof(send_packet))
            {
                iResult = recv(ClientSocket, buff + numRcvBytes, BUFLEN, 0);
                //if (iResult <= 0)
                //  closesocket(ClientSocket);
                if (iResult == SOCKET_ERROR)
                {
                    printf("Error %d", WSAGetLastError());
                    closesocket(ClientSocket);
                    WSACleanup();
                }
                numRcvBytes += iResult;

            }

            numRcvBytes = 0;        


            if (iResult > 0)
            {
                send_packet *pkt;
                pkt = (send_packet *)buff;
                printf("magc %d  cmd %d\n", pkt->magic, pkt->cmd);
                printf("Received %d %s\n", iResult, buff);
                printf("m:%d c:%d x:%d y:%d\n", pkt->magic, pkt->cmd, pkt->Coords.x, pkt->Coords.y);

                int command = pkt->cmd;
                recv_packet *rcv_pkt;
                int buff_size = 0;
                BYTE *data_buffer = NULL;
                int size;

                int coordX;
                int coordY;

                wchar_t message[512];

                switch (command)
                {
                    case GET_SCREEN:

                        data_buffer = GetScreeny(75, &buff_size);
                        rcv_pkt = (recv_packet *)malloc(sizeof(recv_packet)+buff_size);
                        rcv_pkt->magic = MAGIC;
                        rcv_pkt->code = 0;
                        rcv_pkt->length = buff_size;
                        memcpy(rcv_pkt->body, data_buffer, buff_size);
                        size = sizeof(rcv_pkt->magic) + sizeof(rcv_pkt->code) + sizeof(rcv_pkt->length) + buff_size;

                        if (send(ClientSocket, (char *)rcv_pkt, size, 0) == SOCKET_ERROR)
                        {
                            printf("Error %d\n", WSAGetLastError());
                            closesocket(ClientSocket);
                            //WSACleanup();
                            //return 1;
                        }

                        free(rcv_pkt);

                   break;

                   case CLICK_MOUSE:

                        coordX = pkt->Coords.x;
                        coordY = pkt->Coords.y;
                        //wsprintf(message, L"x:%d y:%d", coordX, coordY);
                        //MessageBox(NULL, message, NULL, MB_OK);                           
                        MoveMouse(coordX, coordY);
                        ClickMouse();   

                    break;

                    default:
                    break;
                }


                /*
                char send_buff[1024+1] = "";
                ZeroMemory(&send_buff, 1025);
                memset(send_buff, 'A', 1024);
                recv_packet *rcv_pkt = (recv_packet *)malloc(sizeof(recv_packet)+1024+1);
                //recv_packet rcv_pkt = { 0 };
                rcv_pkt->magic = MAGIC;
                rcv_pkt->code = 0;
                rcv_pkt->length = strlen(send_buff)+1;
                memcpy(rcv_pkt->body, send_buff, 1025);
                int size = sizeof(rcv_pkt->magic) + sizeof(rcv_pkt->code) + sizeof(rcv_pkt->length) + 1024 + 1;
                //printf("%d", size);
                //getchar();
                //return 0;
                */

            }

        } while (iResult > 0);

我将不胜感激任何帮助!谢谢。

1 个答案:

答案 0 :(得分:1)

您一次只能阅读一条消息。如果套接字中有2条消息可用,则当前代码将同时读取这两条消息,但仅处理第一条消息。

将您的阅读更改为:

            iResult = recv(ClientSocket, buff + numRcvBytes, sizeof(send_packet) - numRcvBytes, 0);

更好的方法是将接收提取到一个单独的功能:

int recvBytes(int socket, size_t numBytes, void *buffer) {
    int numRcvBytes = 0;
    while (numRcvBytes < numBytes)
    {
        iResult = recv(socket, buff + numRcvBytes, numBytes - numRcvBytes, 0);
        if (iResult == SOCKET_ERROR)
        { 
            // Leave cleanup to caller
            return SOCKET_ERROR;
        }
        numRcvBytes += iResult;
    }
    return numRcvBytes;
}