QTcpServer

来源:互联网 发布:萝莉捏脸数据百度云 编辑:程序博客网 时间:2024/06/06 10:07

Qt助手如下描述:

      The QTcpServer class provides a TCP-based server.
This class makes it possible to accept incoming TCP connections. You can specify[指定] the port or have QTcpServer pick one automatically. You can listen on a specific[明确的,具体的] address or on all the machine's addresses.
      Call listen() to have the server listen for incoming connections. The newConnection() signal is then emitted each time a client connects to the server.
      Call nextPendingConnection() to accept the pending[未决的,即将发生的] connection as a connected QTcpSocket. The function returns a pointer to a QTcpSocket inQAbstractSocket::ConnectedState that you can use for communicating with the client.
      If an error occurs, serverError() returns the type of error, and errorString() can be called to get a human-readable[可读的] description of what happened.
      When listening for connections, the address and port on which the server is listening are available as serverAddress() and serverPort().
      Calling close() makes QTcpServer stop listening for incoming connections.
      Although QTcpServer is mostly designed for use with an event loop, it's possible to use it without one. In that case, you must use waitForNewConnection(), which blocks[阻塞] until either a connection is available or a timeout expires[失效].

QTcpServer类有三个虚函数,一个信号voidnewConnection ():

      virtual boolhasPendingConnections () const;                             ///public

      virtual QTcpSocket *nextPendingConnection ();                      ///public

      virtual voidincomingConnection ( int socketDescriptor );          ///protected

比如qt自带的例子FortuneServer的实现:

class FortuneServer : public QTcpServer{Q_OBJECTpublic:FortuneServer(QObject *parent=0);~FortuneServer();protected:void incomingConnection(int socketDescriptor);private:QStringList fortunes;};
实现文件:

FortuneServer::FortuneServer(QObject *parent): QTcpServer(parent){fortunes << tr("You've been leading a dog's life. Stay off the furniture.")<< tr("You've got to think about tomorrow.")<< tr("You will be surprised by a loud noise.")<< tr("You will feel hungry again in another hour.")<< tr("You might have mail.")<< tr("You cannot kill time without injuring eternity.")<< tr("Computers are not intelligent. They only think they are.");}void FortuneServer::incomingConnection( int socketDescriptor ){QString fortune = fortunes.at(qrand() % fortunes.size());FortuneThread *thread = new FortuneThread(socketDescriptor, fortune, this);connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));thread->start();}
为每一个连接启动一个新的线程。

FortuneThread如下:

class FortuneThread : public QThread{Q_OBJECTpublic:FortuneThread(int socketDescriptor,const QString &fortune,QObject *parent);void run();signals:void error(QTcpSocket::SocketError socketError);private:int socketDescriptor;QString text;};
FortuneThread::FortuneThread(int socketDescriptor,const QString &fortune,QObject *parent): QThread(parent),socketDescriptor(socketDescriptor),text(fortune){}void FortuneThread::run(){QTcpSocket tcpSocket;if(!tcpSocket.setSocketDescriptor(socketDescriptor)){emit error(tcpSocket.error());}QByteArray block;QDataStream out(&block,QIODevice::WriteOnly);out.setVersion(QDataStream::Qt_4_0);out<<(quint16)0;out<<text;out.device()->seek(0);out << (quint16)(block.size() - sizeof(quint16));tcpSocket.write(block);tcpSocket.disconnectFromHost();tcpSocket.waitForDisconnected();}
QTcpSocket间接地由QIODevice派生而来(通过QAbstractSocket),所以它可以使用QDataStream或者QTextStream来进行读取和写入。TCP是基于流的协议,在TCP之上建立的高层协议通常是基于行的或者基于块的。

      基于行的协议把数据作为一行文本进行传输,每一数据行都以一个换行符结尾。

      基于块的协议把数据作为二进制块进行传输。每一数据块都是由一个大小字段及其包含的数据组成的。

if(!server.listen()){QMessageBox::critical(this,tr("Threaded Fortune Server"),tr("Unable to start the server: %1.").arg(server.errorString()));close();return;}QString ipAddress;QList<QHostAddress> ipAddressList= QNetworkInterface::allAddresses(); // use the first non-localhost IPv4 addressfor(int i=0; i<ipAddressList.size(); ++i){if(ipAddressList.at(i)!=QHostAddress::LocalHost &&ipAddressList.at(i).toIPv4Address()){ipAddress= ipAddressList.at(i).toString();break;}}// if we did not find one, use IPv4 localhostif (ipAddress.isEmpty())ipAddress = QHostAddress(QHostAddress::LocalHost).toString();statusLabel->setText(tr("The server is running on\n\nIP: %1\nport: %2\n\n""Run the Fortune Client example now.").arg(ipAddress).arg(server.serverPort()));connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
一个简单的服务器程序。如下: