天天看點

qt tcpserver linux,Qt下應用QTcpServer與QTcpSocket實作Tcp控制

很多情形下,我們在應用程式的最外層都使用TCP作為可靠控制,下面,我就總結一下我在項目中使用QTcpServer與QTcpSocket的一些心得和體會。

服務端TCP程式可以利用QTcpServer,首先我們聲名QTcpServer *對象(注意:QTcpServer占用的網絡資源需要我們手動釋放,任何我們程式可能異常退出或正常結束的地方QTcpServer *最後都要close())

注意我們的服務端要一直監聽用戶端

tcpPort=8888;

tcpServer=new QTcpServer();

if(!tcpServer->listen(QHostAddress::Any,tcpPort))

{

tcpServer->close();

emit MSG(QString("listen erro"));

}

connect(tcpServer,&QTcpServer::newConnection,this,&TcpServer::onNewConnection);

在新連接配接對應的槽裡我們把

QTcpSocket *newpeer=tcpServer->nextPendingConnection();

這個新連接配接的socket指針取下來,進行操作,當執行newpeer->write(QByterArray &MSG)即伺服器向此peer發送資料;當執行QByterArray MSG=newpeer->write()即伺服器讀此peer的資料,所有資訊的傳遞均是對QTcpSocket的操作,并要要對每一個socket的disconnected連接配接deleteLater槽防止記憶體洩漏。

說到此處,就牽涉到了QString 與QByterArray的轉換,因為我們平時處理消息大多是對QSring進行處理:

QString->QByterArray(隻有英文(Latin)時):

newpeer->write(QString("Server").toLatin1());

QByterArray-> QString:

QTextCodec *tc= QTextCodec::codecForName("UTF-8");

QString str=tc->toUnicode((QByteArray)

rawreply)

下面的代碼抽取自 我的服務端程式

#ifndef TCPSERVER_H

#define TCPSERVER_H

#include

#include

#include

class TcpServer : public QObject

{

Q_OBJECT

public:

explicit TcpServer(QObject *parent = 0);

~TcpServer();

private:

int nb_peer;//總共的小夥伴數目,用于确定client->index的取值

QTcpServer *tcpServer;

public slots:

void ReadDataFromSocket();

void onNewConnection();

void onDisConnection();

void processMSG(QString &MSG);

// void processAddedClient(QTcpSocket *client);

};

#include "tcpserver.h"

TcpServer::TcpServer(QObject *parent) :

QObject(parent),nb_peer(0)

{

tcpPort=8888;

tcpServer=new QTcpServer();

if(!tcpServer->listen(QHostAddress::Any,tcpPort))

{

tcpServer->close();

emit MSG(QString("listen erro"));

}

peerList = QList();

connect(tcpServer,&QTcpServer::newConnection,this,&TcpServer::onNewConnection);

}

void TcpServer::onNewConnection()

{

QTcpSocket *newpeer=tcpServer->nextPendingConnection();

//寫入驗證

connect(newpeer,SIGNAL(readyRead()),this,SLOT(ReadDataFromSocket()));

connect(newpeer,SIGNAL(disconnected()),newpeer,SLOT(deleteLater()));

connect(newpeer,SIGNAL(disconnected()),this,SLOT(onDisConnection()));

newpeer->write(QString("Server").toLatin1());

newpeer->flush();

}

#include

#include

void TcpServer::ReadDataFromSocket()

{

QByteArray rawreply= static_cast(sender())->readAll();

QTextCodec *tc= QTextCodec::codecForName("UTF-8");

client beingCheckedClient;

beingCheckedClient.index=nb_peer;

beingCheckedClient.socket=static_cast(sender());

if(tc->toUnicode(rawreply)!=QString("Client")&& !peerList.contains(beingCheckedClient

))

{

//寫入資訊

//emit ChangeLabel(QString(rawreply));

static_cast(sender())->write(

QString("connect time out! disconnecting...").toLatin1());

static_cast(sender())->flush();

static_cast(sender())->disconnectFromHost();

return ;

}

}

TcpServer::~TcpServer()

{

tcpServer->close();

}

用戶端就沒什麼好說的了,也是對QTcpSocket的一些操作,但是注意要在程式開始時對伺服器發起連接配接:

tcpsocket=new QTcpSocket();

tcpsocket->abort();

tcpsocket->connectToHost(("127.0.0.1"),8888);

一些問題:很多大牛可能會說,我直接使用write read接受字元串指令可能并不安全,在實際應用中我發現,低頻率的收發資料這種方法非常可靠,但是在很多用戶端同時連接配接時,進行回調消息驗證時,會出現資訊殘缺,我的解決方案是使用延時政策,但是這并不是長久之計。

按照官方給的例子:

服務端發送資料:

void Server::sendFortune()

{

QByteArray block;

QDataStream out(&block, QIODevice::WriteOnly);

out.setVersion(QDataStream::Qt_4_0);

out << (quint16)0;

out << fortunes.at(qrand() % fortunes.size());

out.device()->seek(0);

out << (quint16)(block.size() - sizeof(quint16));

QTcpSocket *clientConnection = tcpServer->nextPendingConnection();

connect(clientConnection, SIGNAL(disconnected()),

clientConnection, SLOT(deleteLater()));

clientConnection->write(block);

clientConnection->disconnectFromHost();

}

用戶端接受資料:

void Client::readFortune()

{

QDataStream in(tcpSocket);

in.setVersion(QDataStream::Qt_4_0);

if (blockSize == 0) {

if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))

return;

in >> blockSize;

}

if (tcpSocket->bytesAvailable() < blockSize)

return;

QString nextFortune;

in >> nextFortune;

if (nextFortune == currentFortune) {

QTimer::singleShot(0, this, SLOT(requestNewFortune()));

return;

}

currentFortune = nextFortune;

statusLabel->setText(currentFortune);

getFortuneButton->setEnabled(true);

}

缺點是每收發一回合資訊,都要重連一次。

Qt 的詳細介紹:請點這裡

Qt 的下載下傳位址:請點這裡

qt tcpserver linux,Qt下應用QTcpServer與QTcpSocket實作Tcp控制