如何通过TCP发送10,000~20,000字节的数据?

时间:2011-08-10 13:00:36

标签: c++ tcp

我可以通过TCP发送大约10,000~2,000字节的数据吗?我正在将图像(60 x 60)从Android客户端传输到linux服务器。在Android上似乎没问题。在服务器端,如果我尝试将图片数据发送回客户端,那么它不起作用。在客户端,如果我解析,那么我得到了一些我不应该得到的奇怪数字。

通过TCP传输大数据是否有任何技术问题?我该如何解决? 提前谢谢..

char* PictureResponsePacket::toByte(){

    /*
     * HEADER
     *
     * Magic number (4)
     * Data length  (4)
     * Packet Id    (2)
     * Packet type  (2)
     * Device Id    (48)
     *
     */

    /*
     * BODY
     *
     * Nickname  (48)
     * deviceId  (4)
     * m_pictureSize
     */

    int offset = 0;

    int headerLength = sizeof(int) + sizeof(int) + sizeof(short) + sizeof(short) + 48;
    int bodyLength = 48 + 4 + m_pictureSize;
    int dataLength = headerLength + bodyLength;
    m_dataLength = dataLength;

    log("PictureResponsePacket::toByte(), data length %d \n", m_dataLength);

    char *sendBuffer = new char[dataLength];
    memset(sendBuffer, 0x00, dataLength);

    char *ptr = sendBuffer;

    /*
     * -------------
     * HEADER
     * -------------
     */
    /*
     * Magic number
     */
    memcpy(ptr + offset, m_magicNumberBuffer, sizeof(int));
    offset += sizeof(int);

    /*
     * Data length
     */


    memcpy(ptr + offset, &m_dataLength, sizeof(int));
    offset += sizeof(int);

    /*
     * Packet id
     */
    memcpy(ptr + offset, &m_packetId, sizeof(short));
    offset += sizeof(short);

    /*
     * Packet type
     */
    memcpy(ptr + offset, &m_packetType, sizeof(short));
    offset += sizeof(short);

    /*
     *Device Id
     */

    memcpy(ptr + offset, m_deviceId.c_str(), m_deviceId.size());
    offset += 48;

    /*
     * -------------
     * BODY
     * -------------
     */
    memcpy(ptr + offset, m_senderDeviceId.c_str(), m_senderDeviceId.size());
    offset += 48;

    memcpy(ptr + offset, &m_pictureSize, sizeof(int));
    offset += sizeof(int);

    memcpy(ptr + offset, m_pictureData, m_pictureSize);
    offset += m_pictureSize;


    return sendBuffer;


}

我这样得到char *并像这样发送

                char * sBuffer = reponsePacket->toByte();
                int remainLength = reponsePacket->getDataLength();
                int currentSentLength = 0;
                SocketClient *client = work->getClient();

                while(remainLength > 0){

                    if(remainLength >= MAX_LENGTH)
                        currentSentLength = send(client->getFd(), sBuffer, MAX_LENGTH, MSG_NOSIGNAL);
                    else
                        currentSentLength = send(client->getFd(), sBuffer, remainLength, MSG_NOSIGNAL);

                    if(currentSentLength == -1){
                        log("WorkHandler::workLoop, connection has been lost \n");
                        break;
                    }

                    sBuffer += currentSentLength;
                    remainLength -= currentSentLength;

3 个答案:

答案 0 :(得分:5)

你要做的事情很简单(20K不是“大”)。到目前为止,最常见的原因是忽略了sendrecv的返回代码。你应该记住一些事情:

  • send(2)无法始终将所有数据从用户空间复制到内核空间。检查返回值
  • 数据并非全部同时到达,因此您需要recv几次才能获得所有数据

在实践中,在许多系统上,你可能会忘记send大量数据(内核会嘲笑你的20K),但你必须在循环中接收。这是一个深受Stevens readn启发的功能。使用它而不是recv

ssize_t
readn(int fd, void *vptr, size_t n)
{
    size_t nleft;
    ssize_t nread;
    char *ptr;

    ptr = vptr;
    nleft = n;
    while (nleft > 0) {
        if ((nread = read(fd, ptr, nleft)) < 0) {
            if (errno == EINTR)
                /* Loop back and call read again. */
                nread = 0;
            else
                /* Some other error; can't handle. */
                return -1;
        } else if (nread == 0)
            /* EOF. */
            break;

        nleft -= nread;
        ptr += nread;
    }
    return n - nleft;
}

修改

你似乎忘记了字数(正如Andrew Finnell怀疑的那样)。对于每个整数,您应该在发送之前(memcpy之前)执行类似的操作:

m_dataLength = htonl(m_datalength);

收到时这是:

m_dataLength = ntohl(m_datalength);

答案 1 :(得分:2)

如果您将图像从Android发送到Linux计算机,是否说您可以成功发送和读取图像?如果没有,那么如果您的Linux服务器进程不是用Java编写的话,那么它听起来可能是一个Endian问题。

<强>更新

由于cnicutar有一个很好的答案,我想提供一种替代方法来手动执行你的协议。

Google Protocol Buffer

使用它时,它会自动从主机转换为网络并返回。它还可以用于创建C ++和Java绑定。

答案 2 :(得分:0)

我认为 strace 在客户端和服务器端都有帮助。在strace日志中查找网络错误和发送/接收数据量。