遇到不会用的函数前,最好还是看看手册QAQ,今天居然吃了这个大亏!!!
先交代一下背景:
在做TCP客户端的发送数据功能,要和服务器程序进行TCP/IP通信,且根据通信协议要发送数组或者结构体,并且数组的每一个位都是有效数据位。因此不能像大多数人一样加blockSize篡改协议内容。。
网上大多数的例子都是
//用于暂存要发送的数据
QByteArray block;
//使用数据流写入数据
QDataStream out(&block,QIODevice::ReadWrite);
//设置数据流的版本,客户端和服务器端使用的版本要相同
out.setVersion(QDataStream::Qt_4_6);
//设置发送长度初始值为0
out << (quint16) 0;
//设置发送内容
out<<hash;
//回到字节流起始位置
out.device()->seek(0);
//重置字节流长度
out << (quint16) (block.size()-sizeof(quint16));
//往套接字缓存中写入数据,并发送
tcpSocket->write(block);
数据流在这次并不能排上用场,因为处开字节流长度 被包含在发送内容不说,字节流还会修改char数组里的值!!!(调试了很久都没办法)
但是如果往字节流里添加int类型就不会被修改,因为是字节流,所以可以忽视数据类型传输,这反而也是一个小优点。
首先先要知道,一个char有八个字节,unsign int有32个字节(去掉第一位的正负判断)
such as:
char数组 char[6]=”\0x00\0x00\0x00\0x01\0x01\0x00”
从qDebug block 得出内容变成了 “\0x00\0x00\0x00\0x01\0x00” (已经是去掉了blockSize)
内容明显变动了,0x00是用十六进制来表示一个8位字节。
如果是unsign int = “\0x00\0x00\0x01\0x01”输入到字节流打印block内容还是一样,但是可惜的是一个int 有4个字节,并不能发送自己想要的6个字节的效果,所以就放弃掉这个方法了。
然后我还尝试了调用sys/socket.h sys/tyopes.h试图使用C底层的socket函数来实现TCP通信的时候(感觉放着汽车不用用单车。。) 客户端连接函数connect()已经被QT用掉了,用来实现信号槽。。。。。(无语啊。。)
最后从网上看到了一个大神的博客QTcpSocket 发送和接收数据的几种方法
主要就是放弃字节流直接使用socket->Write()函数,但是一开始我用的时候频频报错,我以为这种方法并不可取,最后把char数组转成字符串也没用。。
1、char型数组或字符串指针转换成QString
char str_data[512];
QString qs_data;
…………
qs_data = QString::fromLocal8Bit(str_data,512); //当然也可以用强制类型转换QString(str_data)
2、QString类型转换为 char指针类型
const char * str_data; //这里一定要加上const,否则会报错!
QString qs_data;
………..
str_data = qs_data.ascii();
然后又从一个试图发结构体类型的问题的帖子里看到了这句话,
this->client->write((char *)&stu,sizeof(stu));
因为我的char是数组,所以我这样写(new的名字不一样,原理是一样的)
SMUTcpSocket->write(mc_sendBuf,sizeof(mc_sendBuf));
SMUTcpSocket->flush();
成功了!!!!!!!!!!!!
诶,主要自我检讨问题是Write函数的使用上面没有清晰去了解,瞎折腾不少时间。所以下次遇到问题先查查手册,看看Write()函数有几个重载。
感谢感谢前人的努力,让我们少走了弯路。
1、QTcpSocket 继承于QAbstractSocket继承于QIODevice
2、QTcpSocket 提供的几种接收和发送数据方法
write ( const char *, qint64 ) : qint64
write ( const char * ) : qint64
write ( const QByteArray & ) : qint64
writeData ( const char *, qint64 ) : qint64
read ( char * data, qint64 maxSize ): qint64
read ( qint64 maxSize ):QByteArray
readAll ():QByteArray
readLine ( char * data, qint64 maxSize ):qint64
readLine ( qint64 maxSize = 0 ):QByteArray
3、例子1 write ( const QByteArray & ) : qint64
//用于暂存要发送的数据
QByteArray block;
//使用数据流写入数据
QDataStream out(&block,QIODevice::ReadWrite);
//设置数据流的版本,客户端和服务器端使用的版本要相同
out.setVersion(QDataStream::Qt_4_6);
//设置发送长度初始值为0
out << (quint16) 0;
//设置发送内容
out<<hash;
//回到字节流起始位置
out.device()->seek(0);
//重置字节流长度
out << (quint16) (block.size()-sizeof(quint16));
//往套接字缓存中写入数据,并发送
tcpSocket->write(block);
3、例子2 write ( const char *, qint64 ) : qint64
QString *a=new QString;
tcpSocket->write(a,a->length());
4、例子3 数据流直接使用QIODevice
QDataStream in(tcpSocket);
in<< quint16(0xFFFF); //此时QIODevice加载了此数据,而且直接发送出去
quint16 length = 0;
QDataStream out(tcpSocket);//如果此时tcpSocket直接有数据发送过来
out >> length;//length获得第一个整型值,并在tcpSocket中清空该数据
PS:最新更新
通过我司某位大神,问题已经找出来了。
之前的问题是为什么把char数组放入字节流里会修改存入字节的内容。
因为指针不是从零开始的(不排除之前有缓存占用了),所以在放入char数组前先
out.device()->seek(0);
这样子内容就正确了。