而对于服务器来讲,多线程的这个特性太有用了,由于多线程使得服务器可能同时响应多个客户端的请求,因此如今服务器大多采用多线程,因此才会形成我开始的误解。html
不论是多线程,仍是服务器,QT中已经封装好了特定的类,因此使用起来也很方便。服务器
下面创建一个支持多线程、TCP的服务器。数据结构
首先创建一个服务器。新建一个类(Server)继承QT中的QTcpServer类便可。服务器的职责是监听端口。当监听到有客户端试图与服务器创建链接的时候,分配socket与客户端链接,再进行数据通讯。QTcpServer的listen()方法执行监听过程,能够指定监听的地址和端口。若给定了QHostAddress类型的监听地址,则监听该地址,不然,监听全部地址;若给定了quint16类型的监听端口,则监听该端口,不然,随机选定一个监听端口。多线程
QTcpServer有一个虚函数incomingConnection(int socketDescriptor),服务器每当监听到一个客户端试图创建链接的时候,会自动调用这个函数,所以,处理这个请求的过程就能够在这个函数中定义,即在子类Server的定义阶段,从新定义incomingConnection()这个函数。对于一个多线程的服务器,每当客户端试图链接的时候,服务器应该启动一个线程,负责对这个客户端进行服务,因此,incomingConnection()这个函数所要作的就是创建一个线程,而所创建的线程的做用就是对客户端进行服务,而这其中创建socket链接是基础。服务器在监听到客户端试图创建socket链接时,会为此socket分配一个惟一的标识socketDescriptor,这个标识将在服务器端创建socket链接时使用,因此应提供给每个线程。socket
在QT中使用多线程,创建一个类(Thread)继承QThread类便可。QThread类也有一个虚函数,这个函数是run(),线程创建并启动(QThread::start())后,就会执行这里面的代码,所以,线程的逻辑过程就应该在run()里面定义。服务器的线程要根据socketDescriptor标识的socket创建链接,而后进行数据通讯,因此要将socketDescriptor传入到Thread中,前面说过,线程是在incomingConnection()里面创建,用构造函数将socketDescriptor传入Thread类,再用socketDescriptor创建socket链接。tcp
定义incomingConnection()函数
定义run()工具
自此,一个简单的多线程服务器创建完毕。学习
写的很差,望请指教。ui
============================
QT4中socket通讯
近的软件工程课程设计让我从新开始使用QT,上次数据结构的课程设计也是用QT,虽然是作出来了,可是如今想一想,那个时候对QT的理解,或者说得更广一点,对OO的理解,简直太差劲了,固然,人的知识是进步的,因此如今有这样的感觉是很正常的。虽然总体的开发工做尚未彻底结束,可是已经有了不少心得体会,因此特来记录分享一下。
咱们的系统采用的是C/S结构,因此客户端与服务器通讯是最关键,不幸的是,虽然咱们没有用过QT的socket类,咱们也没有估计好通讯的难度,等到意识到第一次使用的困难时,已是第5天了,始终没有进展,我临危受命。如今是第6天,刚刚把通讯模块封装好,算是对这两天的突击的一个回报。
咱们遇到的问题socket已经创建,而且发送端已经将消息发送,可是接收端始终收不到消息。(我用的socket类型是TCP,也就是QTcpSocket类)
发送端(发送端一直不存在问题)代码以下:
有问题的接收端代码以下:
以上是最原始的接收和发送端工做过程,调试过程当中,分别讲两端的socket的状态打印出来,结果是发送端为A connection is established. 而接收端为The socket has started establishing a connection. 也就是说发送端正确的创建了链接,并将数据写入,而接收端只是正在创建链接,而并无创建好,因此是根本不会受到数据的。因此先要确保接收端的链接创建好。waitForConnected()方法就能够解决这个问题,它将一直等待直到链接已经创建。
改进后的接收端代码:
此时,接收端输出的socket状态为A connection is established,链接成功创建。
可是仍是收不到信息,参考了一下别人的程序,再比对一下参考手册,原来QTcpSocket的爷爷类(实际上是父类QAbstractSocket的父类)QIODevice有一个readyRead的信号(signal),当信息准备好并能够读的时候,这个信号就将发出,也就是说,只有当这个信号发出的时候,才能够读消息。因此要把读消息的动做read做为一个槽(slot),并将其与readyRead信号链接。
可是直接触发socket信号,而不用图形界面的动做来触发一个动做并由这个动做来触发socket信号一直也触发不了read这个动做。可是我要封装成一个接口类提供给上层使用,用图形界面天然是不现实的,因而翻阅了手册,发现了一个QAbstractSocket类的一个方法——waitForReadyRead(),这个方法将一直等待到数据能够读时结束,此时就能够读数据了。方法也很简单:
这样,数据成功读取出来,实现数据的通讯。
单向的数据传输问题解决了,而后再利用单向的数据通讯组装成双向的数据通讯,这过程当中也会遇到很多问题,将在另外一篇日志介绍。
转自:https://blog.csdn.net/dongfangyu/article/details/5919789
jerry在我本身编写qt4.8 多线程tcp服务端的时候未参考,后来看到的,还不错,供你们参考,重要的我标红了,其实原理都是相同的,就是多线程我习惯用movetothread。