QT的TCP协议
程序员文章站
2022-07-10 13:54:34
...
客户端:
设置服务器主机地址:QHostAddress::setAddress(IP地址)
与主机连接: QTcpSocket::connectToHost(服务器主机地址,端口号)
与主机连接成功: [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();
服务端:
1. TARGET = TcpServer
2. TEMPLATE = app
提供一个基于TCP的服务,可以 指定端口或让自动选择一个端口:QTcpServer
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
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. }
下一篇: 剑指offer之反转链表(java)