其实也没啥,当需要传输的数据大于65536时,记得为套接字申请大一点的 空间 ,加油,摸了两天终于摸出这个坑了。
代码为不完整代码,opencv3.2+Qt5.8,目的就是为了正常的视频通讯。
# 连接
链接: SOCKET通信中TCP、UDP数据包大小的确定.
发送端
- opencv读取本地视频
- 逐帧读取(Mat格式)
- 利用QBuffer,将数据存入到QBytearray中
- 每隔一定长度分段发送出去,(别像我这样写3000)
接收端 - 没有用信号,使用while循环等待数据到来
- 接收到数据判断是否小于3000
- 是的话说明是最后一帧,将其追加到接收的数据区后转换为Mat格式(我需要使用这种格式)
- 不是的话接着追加存储。
发送端
将其写在了线程的run函数中。
void getVideo::run()
{
udpSocket = new QUdpSocket(this);
//这是个大坑我丢!为套接字申请大一点的空间,udp传送数据的缓冲区最大理论值为65536个字节,而我需要发送的帧
//图像最大的大概为20W,导致接收的时候,每帧数据小于65536的才可以正常显示,大于就会卡住。
udpSocket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption,500000 );
string video_path ="D:\\FFOutput\\test14.avi";
VideoCapture camera(video_path);
//int aaa = camera.get(cv::CAP_PROP_FRAME_COUNT);
//qDebug() << "帧数:" << aaa;
if (!camera.isOpened())
{
cout << "read video failure" << endl;
}else
{
cout << "read video success" << endl;
}
QByteArray byte;
QByteArray sendByte;
int ByteLen;
int sendLen;
while(1)
{
camera >> frame;
if(frame.empty())
{
qDebug() << "视频读取完毕" << endl;
//为了方便测试,当本次视频发送完成之后,重新执行run函数。
run();
}
Mat temp;
cvtColor(frame,temp,CV_BGR2RGB);
QImage image((const unsigned char*)(frame.data), frame.cols, frame.rows, frame.step, QImage::Format_RGB888);
QBuffer buffer(&byte);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer,"JPEG");
//每帧图像分多次发送,总大小为ByteLen,每次发送的大小为sendLen,比较可知是否完整发完本帧的数据。
ByteLen = byte.size();
sendLen = 0;
qDebug() << endl << "byte.size :" << ByteLen;
while(ByteLen > sendLen ) //若丢失数据怎么办 0 == len
{
sendByte = byte.mid(sendLen,3000);
int len = udpSocket->writeDatagram(sendByte,sendByte.size(),QHostAddress("192.168.0.16"),12235);
sendLen += len;
qDebug() <<"本次发送出数据长度为:" << len << " 已发送数据长度为:" << sendLen << " 此帧像素数据总长度为:" << ByteLen << endl<<endl;
sendByte.clear();
udpSocket->flush();
}
byte.clear();
QThread::msleep(2);
}
}
接收端
同样写在了线程中
void Video::run()
{
SendDataSocket1 -> bind(QHostAddress("192.168.0.16"),12235);
//同样为套接字申请大一点的空间。
SendDataSocket1->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption,500000 );
//开线程的时候设置flag_A = true;
while(flag_A)
{
int Receivelen;
QByteArray OneFrame;
//等待接收报文
while(SendDataSocket1->hasPendingDatagrams())
{
QByteArray msg;
msg.resize(SendDataSocket1->pendingDatagramSize());
Receivelen = SendDataSocket1->readDatagram(msg.data(),msg.size());
qDebug() << "正在存" << endl;
OneFrame.append(msg);
qDebug() << OneFrame.size();
//接收到一帧数据,每次接收3000字节,当小于3000时说明接收到本帧图像的最后一组数据包。
if(Receivelen < 3000)
{
qDebug() << "接收长度为:" << OneFrame.size() << "得到一帧数据" << endl;
QBuffer buffer(&OneFrame);
QImageReader reader(&buffer,"JPEG");
QImage image = reader.read();
//Img_now 为线程处理函数用到的参数。
QImage2cvMat(image).copyTo(this->Img_now);
OneFrame.clear();
}else
{
//继续接收
qDebug() << "继续接收";
}
}
if(!Img_now.empty())
{
qDebug() << "接收到了帧图像" << endl;
}else
{
gg->my_Timer(300);
continue;
}
//线程处理函数
/*#####################*/
}
}
}