关闭

QTcpSocket 发送数据心得

标签: QT通信qt开发socket
164人阅读 评论(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
查看评论

QTCpSocket文件传输

UDP由于不用建立连接,所以常用于聊天程序(点对点、群聊天等);而TCP由于其建立连接,具有可靠性强、能够保证不丢包,所以经常用于大文件的传输。但是由于TCP粘包,所以在使用TCP进行文件传输时,需要进行粘包问题的考虑。关于TCP/UDP用于聊天程序的应用可以参考:QTcpServer、QTcpSo...
  • Apollon_krj
  • Apollon_krj
  • 2017-06-06 13:09
  • 1947

使用QTcpSocket接收数据

最近,接到一个项目,是连接TCP后读取一个图片的数据,对方为了简化,直接发送数据的二进制格式,因此我必须连接后直接读取,然后在读取完成后进行保存。因为数据没有在开头加入大小信息,而TCP传输的时候并没有一次全部传输完成,只是默认传输一定量的数据,因此我必须时刻检验数据是否全部读取完毕,然后显示图片。...
  • qq_19528953
  • qq_19528953
  • 2017-04-05 10:35
  • 3348

QT tcpsocket 发送/接收数据

发送数据与接收数据中文乱码处理由于有个项目需求是要求文件传输,也要求普通数据传输,而只用一个端口的情况下,如何分开对文件的处理与对数据的处理就非常重要,用官方提供的例子只有单传输文件或者单传输数据,并且传输数据对中文的支持也不是很好,所以针对项目需要,设计了一个方案,这里只列出了单发送数据模块的核心...
  • cammyn
  • cammyn
  • 2016-09-07 11:38
  • 5943

Qt5 TcpSocket 客户端/服务器 通讯实例

Qt  Tcp   客户端 /服务端通信实例    客户端 QTcpSocket Client.pro #------------------------------------------------- # # Project created by...
  • u012997311
  • u012997311
  • 2016-03-28 11:44
  • 14756

QTcpSocket客户端、服务端互发字符串Demo

最近又遇到tcp问题,发现知识不用忘得好快!于是做了一个简单的demo。 先看下运行效果: 代码我已经上传到CSDN: http://download.csdn.net/detail/u014597198/9689618
  • u014597198
  • u014597198
  • 2016-11-22 11:32
  • 909

QTcpSocket 同步函数

目标,qt程序作为客户端,windows下winsock作为服务器端,实现两端通信。 开始时写了一个小函数测试: [cpp] view plaincopyprint? QTcpSocket tmpSock;   tcpS...
  • zhangbinsijifeng
  • zhangbinsijifeng
  • 2016-09-19 22:37
  • 1197

Qt中如何通过tcp发送结构体

前一段时间移植在想Qt如何通过TCP发送结构体,网上有人说可以通过如下方式 tcpSocket->write((char *)&objectA, sizeof(objectA)); tcpSocket->read((char *)&objectA, sizeof(...
  • zhuhouyang
  • zhuhouyang
  • 2014-12-10 16:48
  • 1990

Qt socket中怎么传结构体?

直接发送和接收结构体,例如: struct A {...}; struct A objectA; 发送的时候: tcpSocket->write((char *)&objectA, sizeof(objectA));   接收的时候: struct A ob...
  • hailmy
  • hailmy
  • 2014-04-16 19:21
  • 2072

QT TcpSocket 传送结构体

最近做个程序,测试的时候需要在tcp里面传送结构体。百度,www.gfsoso.com,www.google.com.hk,www.aol.com找了很多帖子。说的好轻松,好轻量,菜鸟级别的和大咖交流就是有困难。好比小学生看《红楼梦》。自己只能一个一个的传结构体里面的成员了。 好了,  看...
  • tadpole_java
  • tadpole_java
  • 2014-12-16 17:27
  • 2163

qt tcpsocket 传送结构体信息

  • 2014-12-08 17:24
  • 9KB
  • 下载
    个人资料
    • 访问:3630次
    • 积分:136
    • 等级:
    • 排名:千里之外
    • 原创:9篇
    • 转载:5篇
    • 译文:0篇
    • 评论:0条
    文章分类