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 的下载地址:请点这里

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值