QtNetwork中的QTcpSocket和QTcpServer类可用來编写基于TCP的client和server
QTcpSocket提供client端的TCP功能,能够发出TCP的请求至服务器,其实它也是具有服务端发送数据到客户端的功能
QTcpServer则提供服务器的功能,并接受TCP连接请求,以及指定port或IP位址
一、客户端的请求与接收数据
基于Http的客户端可以用QHttp来编写。关于如何使用QHttp编写客户端请求和响应处理函数的例子很多,QHttp类也提供了多种请求方式,如get、post、head、request,下面是一个get方法发送请求的例子:
HttpGet.h
这个HttpGet可以按照url地址进行Http请求,完成请求后会发出finished()的Signal,当QHttp所指定的全部请求完成时,会发出done()的Signal,HTTPGet类中自定义的Slot就是用来接收QHttp的done() Signal以进行相关处理的,这可以在HttpGet的实现中看到:
HttpGet.cpp
HttpGet类实现了Http请求,并通过响应消息的槽httpRequestFinished函数对接收到的数据流进行解析,实现网络通信。
注意事项:
(1)书上和网上很多的例子都是直接根据url.path()来请求服务端的一个文件,但是url.path()函数得到的字符串不包含"?"及"?"号之后的字符串,所以不能只用url.path(),而应该还要加上查询字符串QString requestPath = url.path() + queryString;
譬如:
QString queryString("?a=china&b=dazhi");
QUrl url("http://localhost:8081/" + queryString); //创建URL地址
QHttp http;
http.setHost(url.host(), url.port());
(2)//注意:一定要将m_httpGetId 保存,因为在通讯过程中,处理requestFinished消息的槽会判断m_httpGetId与当前状态下requestId是否相等,只有在相等时,才能正确进行解析客户端接收到的数据流,否则可能数据不完整。
二、服务端的响应与发送数据
使用QTcpServer进行了服务器的创建,这里就不多说了,例子很多,但是QT的文档里和网上几乎没有关于如何使用QTcpSocket将数据传输到客户端的例子,我在使用QTcpSocket进行数据发送时,采用了如下方法:
譬如使用的QTcpSocket对象是tcpServerConnection,在响应请求消息并进行处理后,将数据发送到客户端,可以使用:
tcpServerConnection->write(ba),其中ba是要输出到客户端的字节流QByteArray对象。
有趣并折磨我很久的事情发生了!使用IE浏览器请求该服务器时,能够正确获取并解析数据,但我使用QHttp编写的客户端程序却死活也不能正确解析出接收到的字节流数据,跟踪后发现得到的数据流长度小于服务端的数据流长度,但为什么IE浏览器能正常解析呢???
后来终于发现QT的服务端的response默认情况下不包括response header信息,而使用QHttp编写的客户端接收数据时又会默认认为接收到的数据包含了response header,导致它在解析数据流时,会把前面一部分数据作为header信息,而后面的才为作为传输的数据,这样解析出来数据流长度就会减少了,从而不能正确解析数据。因此我们需要在服务端发送数据时输出header信息,再输出我们所要传输的数据。
下面是将影像数据流传输到客户端的示例:
三、总结
QT的例子程序不够丰富全面,深度也不够,甚至网络编程中服务端和客户端的消息模式都有区别,导致不知道内部机制的情况下,无法正确编写程序,真希望QT在快速发展的同时能为我们开发人员提供更加全面的示例程序。