关于QIODevice类write函数的坑
- 问题概述
- 问题部分代码
- 问题解决
- 结论
问题概述
这两天在做TCP通信的封包解包协议操作时,不经意间被write函数坑了好久。通过内存复制进行数据封包,在写入socket的时候总是写入一个字节,不能全部写入数据,原先以为是内存复制出了问题,没想到最后是出在了write函数的使用上。
问题部分代码
//包头结构与包尾结构的初始化HEAD head;TAIL tail;head.dataHead = PACK_HEAD;head.dataType = PACK_TYPE;tail.daraTail = PACK_TAIL;strcpy(head.fileName,fileNames[sendTime].toLatin1().data());strcpy(head.filePath,paths[sendTime].toLatin1().data());head.fileSize = fileSizes[sendTime];char *buffer = new char[4*1024]; //内存缓存locFile.setFileName(paths[sendTime]);locFile.open(QIODevice::ReadOnly);do{char buf[2*1024];qint64 readLen = locFile.read(buf,sizeof(buf));head.dataLen = readLen; //包内数据长度DATA *param = (DATA *)buf;memcpy(buffer,&head,sizeof(HEAD));memcpy(buffer+sizeof(HEAD),param,readLen);memcpy(buffer+sizeof(HEAD)+readLen,&tail,sizeof(TAIL));int packLen = readLen+sizeof(HEAD)+sizeof(TAIL); //包总长度/qint64 sendLen = tcpSocket->write(buffer); //问题就出在这里tcpSocket->waitForBytesWritten();//qDebug()<<sendLen;sendSize += readLen;} while (sendSize < fileSizes[sendTime]);
问题解决
在这里就不得不说一下,QIODevice类的write()函数了,它有以下三种方法:
1、qint64 QIODevice::write(const char * data, qint64 maxSize)
2、qint64 QIODevice::write(const char * data)
3、qint64 QIODevice::write(const QByteArray & byteArray)
第三种就不说了,传入的就是一个QByteArray类型的集合就可,由上述可见,第一种比第二种多个一个参数,就是写入字节数的参数。
等等,你是不是以为第二种和第一种没什么区别呢,第二种没有参数表示写入多少字节数就是表示默认写入所有的内容吗!!不是的,请看帮助文档里的:
strlen(char*)函数求的是字符串的实际长度,它求得方法是从开始到遇到第一个’\0’,buffer是字符型数组,在这里qstrlen(buffer)=1,因此总是写入是1个字节。
结论
所以为了不出错,还是选用第一个write()函数,则上述错误代码改为:
qint64 sendLen = tcpSocket->write(buffer,buf.size()); 就可以完全写入了。