发送和接收所有数据(C++套接字)

3

请帮助我找出客户端和服务器通信中的问题......

客户端使用以下函数将来自摄像头的JPEG帧每秒发送25次到服务器:

int SendAll(SOCKET &client_socket, string &data){
    int result, bytes_sent, sent_total, bytes_remain, package_size;
    result = bytes_sent = sent_total = package_size = 0;
    bytes_remain = data.size();
    while (bytes_remain && !result){
        package_size = (bytes_remain<KILOBYTE)?bytes_remain:KILOBYTE;
        bytes_sent = send(client_socket, &data[sent_total], package_size, 0);
        if (bytes_sent > 0){
            bytes_remain-= bytes_sent;
            sent_total+= bytes_sent;
        }
        else if(bytes_sent == SOCKET_ERROR){
            result = WSAGetLastError();
            break;
        }
    }
    return result;
}

在线程循环中:
while(CAMERA.Stream){
    OperationStartTime = GetTickCount();
    //RecvBuffer.resize(512);
    result = SendAll(CAMERA.Socket, CameraFrame);
    if(result != 0){
        cout << "error in send - " << result;
        CAMERA.Stream = false;
        break;
    }
    if (recv(CAMERA.Socket, &RecvBuffer, 1, 0) < 0){
        CAMERA.Stream = false;
        break;
    }  
    while(OperationStartTime + StreamRate > GetTickCount()){
        if (!CAMERA.Stream){break;}
        Sleep(1);
    }
}

有时候我会看到“发送错误 - 10053”的提示(在本地测试)。
服务器使用这个函数来接收所有的数据:
int RecvAll(SOCKET &client_socket, string &data){
    data = "";
    int bytes_received = 0;
    int result = 0;
    char* recv_buffer;
    do {
        recv_buffer = (char*)malloc(KILOBYTE);
        bytes_received = recv(client_socket, recv_buffer, KILOBYTE, 0);
        if (bytes_received > 0){
            data.append(recv_buffer, bytes_received);
            if (bytes_received < KILOBYTE || data.size() >= 512*KILOBYTE){
                bytes_received = result = 0;}
        }
        else if(bytes_received == SOCKET_ERROR){
            data.clear();
            result = WSAGetLastError();
        }
        free(recv_buffer);
    }
    while (bytes_received > 0);
    return result;
}

服务器端没有错误。

SendAllRecvAll 函数中出了什么问题,如何实现稳定的数据传输?

PS:有时客户端会停止,只有重新连接才能解决。但如果重新连接,服务器将显示一个新的已连接套接字 - 这意味着 CAMERA.Socket 被阻塞,我不明白为什么。


你是在要求我们为你调试程序吗? - Lightness Races in Orbit
你尝试过查找那个错误代码吗? - Andrew Henle
@BoundaryImposition,并不是要调试,但是也许有人会发现逻辑上的错误。 - Iceman
@AndrewHenle,是的-看起来问题出在客户端。无法确定服务器是否对其产生影响。 - Iceman
我不理解区别,Iceman。 - Lightness Races in Orbit
首先尝试最简单的方法:降低传输速率...控制帧大小以统一小帧... - Dr t
1个回答

5

客户端没有将数据大小发送到服务器,因此服务器不知道每个发送的帧应该读取多少字节。

它也没有处理服务器断开连接的情况,或者正确处理StreamRate计算。

可以尝试采用以下方法:

客户端:

int SendAll(SOCKET client_socket, const void *data, int data_size)
{
    const char *data_ptr = (const char*) data;
    int bytes_sent;

    while (data_size > 0)
    {
        bytes_sent = send(client_socket, data__ptr, data_size, 0);
        if (bytes_sent == SOCKET_ERROR)
            return -1;

        data_ptr += bytes_sent;
        data_size -= bytes_sent;
    }

    return 1;
}

int SendAll(SOCKET client_socket, const string &data)
{
    ulong data_size = htonl(data.size());

    int result = SendAll(client_socket, &data_size, sizeof(data_size));
    if (result == 1)
        result = SendAll(client_socket, data.c_str(), data.size());

    return result;
}

...

int result;
char reply;

while (CAMERA.Stream)
{
    OperationStartTime = GetTickCount();

    result = SendAll(CAMERA.Socket, CameraFrame);
    if (result != 1)
    {
        cout << "error in send - " << WSAGetLastError();
        CAMERA.Stream = false;
        break;
    }

    result = recv(CAMERA.Socket, &reply, 1, 0);
    if (result <= 0)
    {
        if (result == 0)
            cout << "server disconnected";
        else
            cout << "error in read - " << WSAGetLastError();

        CAMERA.Stream = false;
        break;
    }  

    while (CAMERA.Stream && ((GetTickCount() - OperationStartTime) < StreamRate))
    {
        Sleep(1);
    }
}

服务器:

int RecvAll(SOCKET client_socket, void *data, int data_size)
{
    char *data_ptr = (char*) data;
    int bytes_recv;

    while (data_size > 0)
    {
        bytes_recv = recv(client_socket, data_ptr, data_size, 0);
        if (bytes_recv <= 0)
            return bytes_recv;

        data_ptr += bytes_sent;
        data_size -= bytes_sent;
    }

    return 1;
}

int RecvAll(SOCKET client_socket, string &data)
{
    ulong data_size;
    int result;

    data = "";

    result = RecvAll(client_socket, &data_size, sizeof(data_size));
    if (result == 1)
    {
        data_size = ntohl(data_size);
        if (data_size > 0)
        {
            data.resize(data_size);

            result = RecvAll(client_socket, &data[0], data_size);
            if (result != 1)
                data.clear();
        }
    }

    return result;
}

...

string data;
int result;
char reply;

while (true)
{
    result = RecvAll(socket, data);
    if (result != 1)
    {
        if (read == 0)
            cout << "client disconnected";
        else
            cout << "error in read - " << WSAGetLastError();

        break;
    }

    // process data as needed...

    reply = 1;
    if (send(socket, &reply, 1, 0) == SOCKET_ERROR)
    {
        cout << "error in send - " << WSAGetLastError();
        break;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接