QT的TCP协议

tech2026-01-18  3

客户端:

IP地址 :QString 

端口号:int

设置服务器主机地址:QHostAddress::setAddress(IP地址)

TCP套接字 用来接收和发送数据的 QTcpSocket

与主机连接: QTcpSocket::connectToHost(服务器主机地址,端口号)

QTcpSocket

与主机连接成功:  [signal] void connected()

QString msg=userName+":"+sendLineEdit->text(); //格式转换 QByteArray data = msg.toUtf8(); //传给服务端 QTcpSocket::write(data,data.length());

与主机断开连接才会调用触发: [signal] void disconnected()

当收到消息时发送该信号触发: [signal] void readyRead()

1. //bytesAvailable返回接收到的数据的长度 2. while(QTcpSocket::bytesAvailable()>0) 3. { 4. //有数据可读取 5. QByteArray datagram; 6. 7. //设置字节大小 8. datagram.resize(QTcpSocket::bytesAvailable()); 9. //套接字读取 10. QTcpSocket::read(datagram.data(),datagram.size()); 11. 12. //格式转换 13. QString msg=QString::fromUtf8(datagram); 14. }

连接出错触发:  [signal] error(QAbstractSocket::SgocketError)

1. //槽函数接收错误信息 2. void TcpClient::onError(QAbstractSocket::SocketError socketError) 3. { 4. QString str; 5. 6. switch(socketError){ 7. case QAbstractSocket::ConnectionRefusedError: 8. str = tr("服务器连接被拒绝或者连接超时。错误代码:%1").arg(socketError); 9. break; 10. case QAbstractSocket::RemoteHostClosedError: 11. str = tr("远程主机关闭。错误代码:%1").arg(socketError); 12. break; 13. case QAbstractSocket::HostNotFoundError: 14. str = tr("远程主机未找到。错误代码:%1").arg(socketError); 15. break; 16. default: 17. str = tr("未知错误。错误代码:%1").arg(socketError); 18. break; 19. } 20. status = false; 21. QMessageBox::information(this,tr("错误提示"),str); 22. }

断开主机连接

23. //断开连接 24. int length=0; 25. QString msg=userName+tr(":离开聊天室"); 26. 27. QByteArray data = msg.toUtf8(); 28. 29. if((length=tcpSocket->write(data,data.length()))!=data. length()) 30. { 31. return; 32. } 33. //当前连接的主机断开 34. tcpSocket->disconnectFromHost();

服务端:

pro配置文件中引入

1. TARGET = TcpServer 2. TEMPLATE = app

提供一个基于TCP的服务,可以 指定端口或让自动选择一个端口:QTcpServer

Server  .h文件

3. #include <QTcpServer> 4. #include <QObject> 5. #include "tcpclientsocket.h" 6. 7. /** 8. * @brief The TcpServer class 9. * 10. * 1.监听端口,等待连接 11. * 2.创建连接 12. * 3.消息的分发 13. * 4.客户端断开连接操作 14. * 15. */ 16. class Server : public QTcpServer 17. { 18. Q_OBJECT 19. public: 20. Server(QObject *parent=0,int port=0); 21. 22. //已连接套接字的容器,消息转发 23. QList<TcpClientSocket*> tcpClientSocketList; 24. signals: 25. //自定义信号,当有效性收到的时候,更新服务器显示 26. void updateServer(QString,int); 27. public slots: 28. //收到消息之后转发给所有的客户端 29. void updateClients(QString,int); 30. //客户端断开连接时,触发的槽 31. void slotDisconnected(int); 32. protected: 33. //有新的消息进来时,执行 34. void incomingConnection(qintptr socketDescriptor) override; 35. };

Server  .cpp文件  

重点(有新消息都会执行)重写方法:void incomingConnection(qintptr socketDescriptor) override;

36. #include "server.h" 37. 38. Server::Server(QObject *parent,int port) 39. :QTcpServer(parent) 40. { 41. //监听端口,QHostAddress::Any 任意主机 ,port端口号 42. listen(QHostAddress::Any,port); 43. } 44. //socketDescriptor 套接字标识符 45. void Server::incomingConnection(qintptr socketDescriptor) 46. { 47. //有新的连接 48. //初始化服务器端的套接字 49. TcpClientSocket *tcpClientSocket=new TcpClientSocket(this); 50. //消息分发 51. connect(tcpClientSocket,SIGNAL(updateClients(QString,int)),this,SLOT(updateClients(QString,int))); 52. //断开连接 53. connect(tcpClientSocket,SIGNAL(disconnected(int)),this,SLOT(slotDisconnected(int))); 54. 55. //设置当前套接字的唯一标识 56. tcpClientSocket->setSocketDescriptor(socketDescriptor); 57. //添加到容器 58. tcpClientSocketList.append(tcpClientSocket); 59. } 60. 61. void Server::updateClients(QString msg,int length) 62. { 63. //消息分发 64. //将信息显示在客户端 65. emit updateServer(msg,length); 66. 67. //遍历所有的客户端套接字 68. for(int i=0;i<tcpClientSocketList.count();i++) 69. { 70. QTcpSocket *item = tcpClientSocketList.at(i); 71. QByteArray data = msg.toUtf8(); 72. 73. if(item->write(data,data.length())!=data.length()) 74. { 75. continue; 76. } 77. } 78. } 79. 80. void Server::slotDisconnected(int descriptor) 81. { 82. //移除断开连接的套接字 83. for(int i=0;i<tcpClientSocketList.count();i++) 84. { 85. QTcpSocket *item = tcpClientSocketList.at(i); 86. 87. //根据套接字标识进行唯一确定 88. if(item->socketDescriptor()==descriptor) 89. { 90. tcpClientSocketList.removeAt(i); 91. break; 92. } 93. } 94. }

TCP套接字 用来接收和发送数据的: QTcpSocket

TcpClientSocket  .h文件

95. #include <QTcpSocket> 96. #include <QObject> 97. 98. /** 99. * @brief The TcpClientSocket class 100. * 101. * 将消息的处理放置在自定义套接字中,达到封装的效果 102. * 103. */ 104. 105. class TcpClientSocket : public QTcpSocket 106. { 107. Q_OBJECT 108. public: 109. TcpClientSocket(QObject *parent=0); 110. signals: 111. //接收到消息发送更新客户端的信号,告诉TCPServer去更新所有的客户端 112. void updateClients(QString,int); 113. //断开连接,参数:套接字的唯一标识符 114. void disconnected(int); 115. protected slots: 116. //数据处理 117. void dataReceived(); 118. //断开连接 119. void slotDisconnected(); 120. };

TcpClientSocket .cpp文件

121. #include "tcpclientsocket.h" 122. 123. TcpClientSocket::TcpClientSocket(QObject *parent) 124. { 125. //readyRead,有消息时的处理 126. connect(this,SIGNAL(readyRead()),this,SLOT(dataReceived())); 127. //当客户端和服务器断开连接时 128. connect(this,SIGNAL(disconnected()),this,SLOT(slotDisconnected())); 129. } 130. 131. void TcpClientSocket::dataReceived() 132. { 133. //返回接收到的数据的长度 134. while(bytesAvailable()>0) 135. { 136. int length = bytesAvailable(); 137. QByteArray data = read(length); 138. QString msg=QString::fromUtf8(data); 139. //发射updateClients信号 140. emit updateClients(msg,msg.length()); 141. } 142. } 143. 144. void TcpClientSocket::slotDisconnected() 145. { 146. //发送连接断开的信号 147. //socketDescriptor 每一个连接的套接字都会有一个唯一标识 148. emit disconnected(this->socketDescriptor()); 149. }

主要触发的.cpp文件

150. void TcpServer::slotCreateServer() 151. { 152. //创建一个Server对象 153. server = new Server(this,port); 154. //更新服务器消息 155. connect(server,SIGNAL(updateServer(QString,int)),this,SLOT(updateServer(QString,int))); 156. //按钮不可点 157. CreateBtn->setEnabled(false); 158. ContentListWidget->addItem(tr("聊天室创建成功。。。")); 159. } 160. 161. void TcpServer::updateServer(QString msg,int length) 162. { 163. //显示从客户端传来的消息 164. ContentListWidget->addItem(msg.left(length)); 165. }

 

最新回复(0)