首先,我规定好数据传输的格式:char 数组,RGBARGBARGBA.......................,主要是将RGBA四个通道的数据按一定格式和顺序写好,然后发过来接收并解析就行
然后,就是数据的接收与解析,先讲一点很少有人注意到的细节,Socket的recv函数并不是你指定接收多长的数据就一定能接到完整的数据,你必须通过它的返回值去判断,它到底接收了多少数据。在图片尺寸较小或者单通道图片时候,基本上可以忽略这个,但是当你的图片是三通道以上的时候就必须注意了。正确的写法如下
int iLenth = SrcImg.rows* SrcImg.cols * 4;//图片的大小乘上通道数,比如我这里用的是4通道的
char *data = new char[iLenth];
int recvLen = 0;
std::string bStr;
while (recvLen < iLenth-1)//主要看这里,判断接收到的字符长度符不符合你的图片大小
{
char *bData = new char[iLenth];
memset(data, NULL, sizeof(char)*iLenth);
int re=recv(m_ClientSock, bData, iLenth, NULL);
if (re!= 0)
{
int len= strlen(bData);//无意义,有透明通道时候这个全是0,
for (int i = 0; i < re; i++)
{
//data[recvLen + i] = bData[i];//这种赋值方法有点问题
bStr +=DevideHexChar(bData[i]);//这个不要在意是把单个char转成16进制string
}
recvLen += re;//长度累加
}
delete[]bData;
}
整体图片接收的代码如下(这个使用Opencv做个辅助,看一下图片对不对)
//特别提醒:不能直接拿来用,要自己配一下环境
bool CTCPFunction::TCP_RecvImg(Mat &SrcImg, int i)
{
int iLenth = SrcImg.rows* SrcImg.cols * 4;
char *data = new char[iLenth];
memset(data, NULL, sizeof(char)*iLenth);
int recvLen = 0;
//接收图片
while (recvLen < iLenth-1)
{
char *bData = new char[iLenth];
memset(bData, NULL, sizeof(char)*iLenth);
int re=recv(m_ClientSock, bData, iLenth, NULL);
if (re!= 0)
{
int m = 0;
while (m < re)
{
data[m+recvLen]= bData[m];
m++;
}
recvLen += re;
}
delete[]bData;
}
//创建图片
for (int i = 0; i < SrcImg.rows; i++)
{
for (int j = 0; j < SrcImg.cols; j++)
{
SrcImg.ptr<Vec4b>(i)[j][0] = data[j * 4 + i * 4 *SrcImg.cols+0] & 0xFF;
SrcImg.ptr<Vec4b>(i)[j][1] = data[j * 4 + i * 4 * SrcImg.cols + 1] & 0xFF;
SrcImg.ptr<Vec4b>(i)[j][2] = data[j * 4 + i * 4 * SrcImg.cols + 2] & 0xFF;
SrcImg.ptr<Vec4b>(i)[j][3] = data[j * 4 + i * 4 * SrcImg.cols + 3] & 0xFF;
}
}
delete[]data;
return true;
}
最后说一个大坑,UTexture2D在更新的时候会崩溃,解决方案如下
https://blog.csdn.net/luofeixiongsix/article/details/80136467
1.给UTexture2D加关键字
2.把UpdateResource放在Tick里调用(下面函数也是放在Tick里使用的)
最最最后为了保留点隐私,只给一下更新代码