关闭

QTcpSocket 发送数据心得

标签: QT通信qt开发socket
38人阅读 评论(0) 收藏 举报
分类:

遇到不会用的函数前,最好还是看看手册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);

这样子内容就正确了。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:667次
    • 积分:99
    • 等级:
    • 排名:千里之外
    • 原创:9篇
    • 转载:4篇
    • 译文:0篇
    • 评论:0条
    文章分类
    文章存档