wuyang
wuyang

Reputation: 73

error on tcp sending buffer of a Mat

I am trying to send out Mat image by TCP. Firstly the Mat has been transferred into uchar and then into char format. The whole image in char format will be send out buffer by buffer whose size is 1024 byte. The following is my code.

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;
}

The output of the code shows : send file failed, total length is 251035, failed offset is 182272.

I am really appreciated on your help. Thank you in advance!

Upvotes: 1

Views: 496

Answers (1)

user4581301
user4581301

Reputation: 33952

Pulling out the crystal ball here. This might be OP's problem, but if it isn't, this is certainly a problem that needs to be addressed.

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

Get data. Not a bad idea if that's what you need to send.

char* charImg = (char*) transferImg;

Take the array of bytes from above and treat it as an array of characters.

int length = strlen(charImg);

And Boom. Matrix data is not ascii formated data, a string, so it should not be treated like a string.

strlen counts data until it reaches a null character, a character with the numerical value 0, which does not exist in the normal alpha numeric world and thus can be used as a canary value to signal the end of a string. The count is the number of characters before the first null character in the string.

In this case we don't have a string. We have a blob of binary numbers, any one of which could bee 0. There could be a null value anywhere. Could be right at the beginning. Could be a hundred bytes in. There might not be a null value in the until long after all of the valid image data has been read.

Anyway, strlen will almost certainly return the wrong value. Too few bytes and the receiver doesn't get all of the image data and I have no idea what it does. That code's not available to us. It probably gets upset and discards the result. Maybe it crashes. There's no way to know. If there is too much information, we also don't know what happens. Maybe it processes the file happily and ignores the extra crap that's sent. Maybe it crashes.

But what if it closes the TCP/IP connection when it has enough bytes? That leaves the sender trying to write a handful of unsent and unwanted bytes into a closed socket. send will fail and set the error code to socket closed.

Solution:

Get the right size of the data.

What I'm reading from the openCV documentation is inside a Mat is Mat::elemSize which will give you the size of each item in the matrix and Mat::size which returns a Size object containing the rows and columns. Multiply rows * columns * elemSize and you should have the number of bytes to send.

EDIT

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

Upvotes: 2

Related Questions