Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何通过TCP发送10000~20000字节的数据?_C++_Tcp - Fatal编程技术网

C++ 如何通过TCP发送10000~20000字节的数据?

C++ 如何通过TCP发送10000~20000字节的数据?,c++,tcp,C++,Tcp,我可以通过TCP发送大约10000~20000字节的数据吗?我正在将一个图像(60乘60)从Android客户端传输到linux服务器。在安卓系统上,这似乎还可以。在服务器端,如果我试图将图片数据发送回客户端,那么它就不起作用。在客户端,若我解析,那个么我会得到一些不应该得到的奇怪数字 通过TCP传输大数据是否存在技术问题?我该如何解决这个问题? 提前谢谢 char* PictureResponsePacket::toByte(){ /* * HEADER *

我可以通过TCP发送大约10000~20000字节的数据吗?我正在将一个图像(60乘60)从Android客户端传输到linux服务器。在安卓系统上,这似乎还可以。在服务器端,如果我试图将图片数据发送回客户端,那么它就不起作用。在客户端,若我解析,那个么我会得到一些不应该得到的奇怪数字

通过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 * 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;

你是说如果你把图像从Android发送到你的Linux机器上,你就可以成功地发送和读取它吗?如果不是这样,那么如果您的Linux服务器进程不是用Java编写的,这听起来可能是个问题

更新

由于cnicutar有一个很好的答案,我想提供一个替代方案,以避免手动执行协议


当使用它时,它将自动从主机转换到网络并返回。它也可以用来创建C++和java绑定。

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

您尝试做的很简单(20K不是“大”)。到目前为止,发生这种情况的最常见原因是忽略
send
recv
的返回码。你应该记住几件事:

  • send(2)
    无法始终将所有数据从用户空间复制到内核空间。检查返回值
  • 数据不是在同一时间到达的,因此在获取所有数据之前,您必须进行几次
    recv
实际上,在许多系统上,发送大量数据(内核会嘲笑您的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;
}
当收到下列文件时:

m_dataLength = ntohl(m_datalength);

是的,你可以发送那个数量的数据,但通常不在一个包中。显示一些代码,可能会有很多问题。20kB是大数据吗?真的吗?除非有人告诉我我疯了,否则我还是会坚持认为问题的一部分是持久性。在发送之前,请签出所有值并将其转换为网络字节顺序。您仍然没有考虑Endian问题。Java总是大端的。x86上的本机代码理解little endian。我在这里留下我以前的评论,因为从技术上讲这是真的。但此代码只是一个网络流。“他仍然需要使用一个解码器来解决endian的问题。”安德鲁·芬内尔在OP编辑和添加代码之前回答道。事实上,他似乎没有像他应该的那样使用htons/htonl。在他发布代码之前,我们都不知道。在代码更新之前,我一直在猜测。因为你现在是我最完整的+1。
m_dataLength = ntohl(m_datalength);