Hello everyone I need to convert std::vector<uchar>
to const char*
or send std::vector<uchar>
over socket using winsock2.h
in windows system.
How can I do this?
I'm compress one image:
std::vector<uchar> buff;//buffer for coding
std::vector<int> param(2);
param[0] = cv::IMWRITE_JPEG_QUALITY;
param[1] = 40;//default(95) 0-100
cv::imencode(".jpeg", frame, buff, param);
Then:
I need to send std::vector<uchar> buff
over socket but the the send()
just accept const char*
.
I have two programs, client and server and I want to send an image through a socket using a JPG buffer to be received by the server and converted back into OpenCV mat.
I already did it that way, but it didn't work:
int bytes = 0;
if (!imgMat.empty())
{
if ((bytes = send(server, (const char*)buff.data() , buff.size(), 0)) < 0) //if ((bytes = send(server, (char*)imgMat.data, imageSize, 0)) < 0)
{
::cout << "Error while sending..";
break;
}
::cout << "Frame sent sucessfuly" << endl;
::cout << bytes << " bytes sent." << endl;
}
else
{
::cout << "Frame was empty" << endl;
break;
}
The purpose is to improve sending speed with an image that takes up less space.
In a comment, you say that you are passing sizeof(buff.data())
to recv()
. This is wrong, you are specifying the size of the pointer itself, not the size of the data that it is pointing at. You need to use buff.size()
instead.
As such, you need to pre-size buff
before you can use it with recv()
. Which means you need to know how many bytes to expect from the sender. So the sender should send its buffer size along with its actual buffer data.
Try something more like this:
sender:
bool sendall(SOCKET sock, const void *data, uint32_t size)
{
const char *ptr = static_cast<const char*>(data);
while (size > 0)
{
int bytes = send(sock, ptr, static_cast<int>(size), 0);
if (bytes < 0) return false;
ptr += bytes;
size -= bytes;
}
return true;
}
...
std::vector<uchar> buff;
std::vector<int> param(2);
param[0] = cv::IMWRITE_JPEG_QUALITY;
param[1] = 40;//default(95) 0-100
if (!cv::imencode(".jpeg", frame, buff, param))
{
std::cout << "Error encoding frame" << std::endl;
break;
}
uint32_t size = buff.size();
if (!(sendall(server, &size, sizeof(size)) &&
sendall(server, buff.data(), size)))
{
std::cout << "Error sending frame" << std::endl;
break;
}
std::cout << "Frame sent successfully" << std::endl;
std::cout << size << " bytes sent" << std::endl;
Receiver:
bool recvall(SOCKET sock, void *data, uint32_t size)
{
return (recv(sock, static_cast<char*>(data), static_cast<int>(size), MSG_WAITALL) > 0);
}
...
uint32_t size;
if (!recvall(client, &size, sizeof(size)))
{
std::cout << "Error while receiving frame" << std::endl;
break;
}
std::vector<uchar> buff(size);
if (!recvall(client, buff.data(), size))
{
std::cout << "Error while receiving frame" << std::endl;
break;
}
cv::Mat imgMat = cv::imdecode(Mat(buff), IMREAD_COLOR);
cv::imshow("Client screen seen from the Server", imgMat);
cv::waitKey(1);
Alternatively, if your code runs on a platform that doesn't support MSG_WAITALL
:
bool recvall(SOCKET sock, void *data, uint32_t size)
{
char *ptr = static_cast<char*>(data);
while (size > 0)
{
int bytes = recv(sock, ptr, static_cast<int>(size), 0);
if (bytes <= 0) return false;
ptr += bytes;
size -= bytes;
}
return true;
}