Winsock:如何在不关闭连接的情况下停止发送/接收

时间:2010-09-22 13:29:15

标签: c sockets winsock

我开发了一个共享一些相机图像的客户端/服务器应用程序。一般周期是:

  1. 客户端捕获相机图像并将其压缩为二进制图像。之后,它将其发送到服务器
  2. 服务器确切地知道缓冲区的大小(640 * 480/8字节),因此他只能通过一次recv调用接收孔图像。下一个recv-call将获得第二个图像,依此类推
  3. 收到图像后,服务器使用图像,然后将另一张图像发送回客户端。但问题是:图像是jpeg压缩的,所以客户端不知道文件大小,也不能像固定缓冲区长度的服务器那样接收图像。
  4. 如果服务器在发送图像后关闭连接,我认为这不会有问题。但我不想关闭连接,因为在下一个周期中,我将通过同一连接发送下一个图像。

    我的问题是:如何告诉客户端服务器在不关闭连接的情况下发送孔图像?

    这是一些代码: (客户端将二进制映像发送到服务器)

    void sendToServer(char* sendbuf, int sendbuflen) {
        int iResult = send(ConnectSocket, sendbuf, sendbuflen, 0);
        if (iResult == SOCKET_ERROR) {
            (*errCallbackFunc)("Sending image error", -1);
        }
    }
    

    (服务器接收只有一个功能的图像 - recbuflen = 640 * 480/8)

    int receiveCameraImages(ARUint8* dataPtr) {
    int         iResult;
    
    iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
    if (iResult > 0) {
        if ((*(recvbuf+0)) != 'U' || (*(recvbuf+((xsize*ysize/8)-1))) != 'U')
            return RECEIVING_INCOMPLETE;
    
        convertBWChartoBGR(recvbuf, dataPtr, recvbuflen);
    
        return RECEIVING_SUCCEEDED;
    } else if (iResult == 0) {
        (*errCallbackFunc)("Connection closing", -1);
        return RECEIVING_CONN_CLOSED;
    }
    else {
        (*errCallbackFunc)("recv failed", WSAGetLastError());
        return RECEIVING_ERROR;
    }
    }
    

    (现在服务器处理图像并发回另一个jpeg压缩图像)

    int sendObjectImage(ARUint8* dataPtr, int bufLen) {
    int iResult;
    
    /* send the openGLBuffer back to the client */
    iResult = send(ClientSocket, dataPtr, bufLen, 0);
    if (iResult == SOCKET_ERROR) (*errCallbackFunc)("send openglbuffer back to client failed", WSAGetLastError());
    }
    

    (并且客户端不知道缓冲区有多大,因此它接收512Byte部分)

    int receiveFromServer(ARUint8* dataPtr) {
    int iResult, returnBufLen = 0;
    int recvBufLen = DEFAULT_BUFFER_LEN;
    ARUint8 recvBuf[DEFAULT_BUFFER_LEN];
    
    /* receive openGL buffer */
    do {
        iResult = recv(ConnectSocket, recvBuf, recvBufLen, 0);
        if (iResult > 0) {
            printf("Bytes received: %d\n", iResult);
            returnBufLen += iResult;
        }
        else if (iResult == 0)
            printf("Connection closed\n");
        else
            printf("recv failed: %d\n", WSAGetLastError());
    } while (iResult >= DEFAULT_BUFFER_LEN);
    
    dataPtr = recvBuf;
    
    return returnBufLen;
    }
    

    with while(iResult> = DEFAULT_BUFFER_LEN)我认为它会停止接收(因为如果一个部分小于512Bytes,它必须是结束)。但我的recvBuf只包含最后一个字节。

    也许我可能不理解孔winsock的东西,但我认为recvBuf将包含我收到的空洞缓冲区。那是错的吗?如何在不关闭连接的情况下获得孔接收缓冲区?

1 个答案:

答案 0 :(得分:4)

  1. 不要依赖对recv()send()的单次调用才能运行完成并处理您要求的数据量。您必须准备好循环运行它们几次,直到传输了所需数量的数据。

  2. 对于服务器想要返回未知长度的图像的情况,只需先使用定义良好的格式(例如网络字节顺序为32位整数)发送长度。然后,客户端可以执行两个单独的接收,一个用于大小,一个用于数据。同样,意味着它只能进行两次recv()次呼叫。