【问题标题】:error on tcp sending buffer of a MatMat 的 tcp 发送缓冲区出错
【发布时间】:2015-09-18 18:04:33
【问题描述】:

我正在尝试通过 TCP 发送 Mat 图像。首先将 Mat 转换为 uchar,然后转换为 char 格式。整张 char 格式的图像会逐个缓冲区发送出去,缓冲区大小为 1024 字节。以下是我的代码。

Mat decodeImg = imdecode(Mat(bufferFrame), 1);

uchar *transferImg = decodeImg.data;
char* charImg = (char*) transferImg;
int length = strlen(charImg);
int offset = 0;
while (true)
{
    bzero(bufferSend, BUFFER_SIZE);

    if (offset + BUFFER_SIZE <= length)
    {
        for (int i = 0; i < BUFFER_SIZE; i++)
        {
            bufferSend[i] = charImg[i + offset];
        }
        //          memcpy(charImg+offset, bufferSend,BUFFER_SIZE);
        if (send(sockfd, bufferSend, sizeof(bufferSend), 0) < 0)
        {
            printf("Send FIle Failed,total length is%d,failed offset is%d\n",
                   length,
                   offset);
            break;
        }
    }
    else
    {
        for (int i = 0; i < length - offset; i++)
        {
            bufferSend[i] = charImg[i + offset];
        }
        if (send(sockfd, bufferSend, sizeof(bufferSend), 0) < 0)
        {
            printf("Send FIle Failed,total length is%d,failed offset is%d\n",
                   length,
                   offset);
            break;
        }
        break;
    }
    offset += BUFFER_SIZE;
}

代码输出显示:发送文件失败,总长度为251035,失败偏移量为182272。

非常感谢您的帮助。提前谢谢!

【问题讨论】:

  • 可能你需要encode base64
  • 如果是这种情况,唯一的问题应该是服务器无法识别图像。但是,当前的问题是该客户端无法发送整个缓冲区。
  • 什么是bufferFrame?你不应该发送imencoded char 缓冲区吗?
  • 系统调用总是失败,原因您可以查询:errno。使用strerror(errno)perror。您应该阅读他们的文档。
  • @black 很奇怪,两个人怎么能在问题提出一个小时后同时发布本质上相同的帖子。

标签: c++ opencv tcp


【解决方案1】:

在这里拔出水晶球。这可能是 OP 的问题,但如果不是,这肯定是一个需要解决的问题。

Mat decodeImg = imdecode(Mat(bufferFrame), 1);
uchar *transferImg = decodeImg.data;

获取数据。如果这是您需要发送的内容,这不是一个坏主意。

char* charImg = (char*) transferImg;

从上面获取字节数组并将其视为字符数组。

int length = strlen(charImg);

还有繁荣。矩阵数据不是ascii格式的数据,是一个字符串,所以不应该把它当成字符串来对待。

strlen 对数据进行计数,直到它到达一个空字符,一个数值为 0 的字符,它在正常的字母数字世界中不存在,因此可以用作一个金丝雀值来表示字符串的结束。计数是字符串中第一个空字符之前的字符数。

在这种情况下,我们没有字符串。我们有一堆二进制数,其中任何一个都可能是 0。任何地方都可能有一个空值。一开始可能是对的。可能是一百个字节。在读取所有有效图像数据后很长时间内可能不会有空值。

无论如何,strlen 几乎肯定会返回错误的值。字节太少,接收器没有得到所有的图像数据,我不知道它做了什么。该代码对我们不可用。它可能会感到不安并丢弃结果。也许它崩溃了。没有办法知道。如果信息太多,我们也不知道会发生什么。也许它会愉快地处理文件并忽略发送的额外废话。可能会崩溃。

但是如果它有足够的字节就关闭 TCP/IP 连接怎么办?这使得发送方试图将少量未发送和不需要的字节写入封闭的套接字。 send 将失败,并将错误代码设置为套接字关闭。

解决方案:

获取正确大小的数据。

我从 openCV 文档中读到的是 Mat 内部的 Mat::elemSize,它将为您提供矩阵中每个项目的大小,Mat::size 返回包含行和列的 Size 对象。乘以 rows * columns * elemSize,你应该有要发送的字节数。

编辑

This looks to be a better way to get the size.

【讨论】:

  • 是的。应该先google一下。以前一定有人遇到过这个问题。事实证明我的答案是stackoverflow.com/questions/22849790/…
  • 好吧,对于不了解 OpenCV 的人来说还不错!实际上,我一直看到发送 base64 编码的数据,但你似乎比我更了解这种东西......
  • 感谢您指出这个我从未意识到的问题。我目前的想法是可以将 Mat 转换为 jpg 格式并发送 jpg 吗?由于我的原始代码是发送一个 jpg 文件,但是从磁盘读取文件需要花费更多时间,所以我现在正在做的是将存储在内存中的 Mat 格式的结果直接发送到客户端。
  • @Miki 我的半生似乎都花在打开套接字和发送不同类型的数据上。
  • @wuyang 您应该能够将 jpg 编码到内存缓冲区,然后将内存缓冲区写入套接字。应该比发送未压缩的 mat 数据快很多,但是如果保真度是一个问题,jpg 压缩会稍微损坏数据。
猜你喜欢
  • 2011-09-27
  • 2015-05-01
  • 2014-05-10
  • 1970-01-01
  • 2019-12-18
  • 1970-01-01
  • 1970-01-01
  • 2019-12-22
  • 1970-01-01
相关资源
最近更新 更多