QT tcp Socket 通信开发

 

转自:http://blog.csdn.net/demowolf/archive/2010/05/17/5598879.aspx

 

折腾了很久TCP IP通信机制。

 

以前虽然看过bsd tcp/ip的so called 基础通信代码。什么bind, listen ,accept , receive, write, read,但是一直没真正理解。

 

这次由于公司需求,我狠狠地读了代码,并且搬出QT老本行,开始了QT For windows的编程。

 

这个大体构架是做一个聊天室软件。

 

每个client都可以给服务器TCP发消息,服务器通过TCP给各个客户端转发消息。

 

服务器端代码:

 

Server.cpp   继承 QTcpServer  主要用来listen to some port , 侦听到端口后, 继承重写了incomingConnection函数,来new 如下的一个

 

代码

 

tcpClientSocket.cpp 这个继承QTcpSocket ,用来 server.cpp里被 New 出来,接受各种请求

 

它重写了函数dataReceived , 即各种客户端发来的请求数据,(注意,这个不是第一步的connect状态,这个是业务逻辑上得请求,比如我给

 

server发送了“你好” ) 。

 

这一步处理好后,便开始给各个客户端分发同样的消息“你好” 。使用方法,很简单,QTcpSocket的write方法即可。

 

这里的细节重点是,在server.cpp里,每个new出来的TcpClientSocket的指针,我放到一个QLIST< TcpClientSocket * >模板里。这样,只要

 

你不删去这个节点,这个TCP链接就一直存在,嘿嘿,神奇吧。

 

刚开始我看QT自带example ,fortuneclient and threaded fortune server;我试图着在example的基础上修改代码,一步步达到目的。结果

 

发现他的业务逻辑,总是write后就自动disconnected, 我以为不disconnected,就能长链接,结果总是出错。

 

我一直纳闷,这是为什么呢?我用了个List保存了socket的descriptor,以为留着套接字的描述符,就可以下次再调出来用用。实际呢,必须

 

创建链路的时刻,就保存指针。TCP链接,指针在,链路在。指针亡,链路亡。

 

这也验证了我的想法,所谓一个真正的通信链路SOCKET的创建,是这样执行下去的。在APP层,我们调用了connect,实际OS对网卡发送了连接

 

对方的信号,这个电子,一路走过去,直到accept , 这一个链路创建了,在网卡开辟了区域了,在系统OS也开辟了内存,两方都为此一直保持

 

着这段数据的存在,指针即维系一个网络TCP链路的关键。

 

这就意味着,客户端无需写什么侦听代码来接受服务器端的消息,直接保持那个链路,消息自然就可以发过来,触发dataReceived信号。

 

写完代码后,我测试了一下,3个客户端同时链接TCP服务器端的5566端口,全部成功。

 

曾经很纠结我的所谓端口只能被一个占用。看来,理论远不如实际来的直接。

 

最后,我还是贴个代码吧。我知道,当一个人寻找各类消息的时候,代码总是最先看得,谁喜欢看人家博客唠叨半天,不讲大道理啊!

 

服务器端:

 

 

Qt TCP套接字通信实例通常用于客户端和服务器之间的双向数据传输,例如聊天应用、游戏服务器等。以下是使用Qt C++的一个简单示例: 首先,你需要包含必要的头文件并设置基本的TCP服务器: ```cpp #include <QObject> #include <QTcpServer> #include <QTcpSocket> class Server : public QObject { Q_OBJECT public slots: void startServer() { QTcpServer *server = new QTcpServer(this); if (server->listen(QHostAddress::Any, 8080)) { // 监听所有地址的8080端口 while (!server->isListening()) { // 当服务器开始监听时 qApp->processEvents(); // 保持应用程序活跃 } connect(server, &QTcpServer::newConnection, this, &Server::handleNewConnection); // 连接到新连接事件 qDebug() << "Server is listening on port 8080"; } else { qDebug() << "Failed to listen on port 8080"; } } private slots: void handleNewConnection() { QTcpSocket *socket = server->nextPendingConnection(); connect(socket, &QTcpSocket::readyRead, this, &Server::handleDataReceived); connect(socket, &QObject::destroyed, this, &Server::removeSocket); } void handleDataReceived() { QByteArray data = socket->readAll(); emit sendDataToClient(data); // 发送给处理数据的部分 } void removeSocket(QObject *sender) { delete sender; // 删除已断开的连接 } }; ``` 然后,你可以创建一个`Client`类,进行相应的TCP连接请求: ```cpp class Client : public QObject { Q_OBJECT public: explicit Client(QObject *parent = nullptr) : QObject(parent), socket(new QTcpSocket(this)) {} public slots: void connectToServer(const QString &host, quint16 port) { socket->connectToHost(host, port); connect(socket, &QTcpSocket::connected, this, &Client::sendHelloMessage); connect(socket, &QTcpSocket::error, this, &Client::connectionError); } private slots: void sendHelloMessage() { socket->write("Hello from client!"); // 发送一条消息到服务器 } void connectionError() { qDebug() << "Connection error"; } signals: void receiveDataFromServer(const QByteArray &data); // 信号发射接收的数据 protected: QTcpSocket *socket; }; ``` 要在客户端和服务器之间传递数据,需要在`Server`类中添加信号处理器,并在`Client`类中对接收的信号作出响应: ```cpp void Server::sendDataToClient(const QByteArray &data) { emit sendDataToClient(data); // 发送给客户端的信号 } void Client::receiveDataFromServer(const QByteArray &data) { qDebug() << "Received message: " << data.toUtf8().constData(); } ``` 最后,在主程序中初始化服务器和客户端: ```cpp int main(int argc, char *argv[]) { QApplication app(argc, argv); Server server; connect(&app, &QApplication::aboutToQuit, &server, &Server::quit); // 关闭服务器时关闭应用 server.startServer(); Client client; client.connectToServer("localhost", 8080); // 如果是本地测试,主机名通常为"localhost" return app.exec(); } ```
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值