文章目录
-
- 概要
- 整体架构流程
- 服务端
- 1、创建QTcpServer 对象
- 2、设置监听端口,进行监听
- 3、等待连接
- 4、接收处理
- 5、发送处理
- 客户端
- 1、创建客户端通信套接字
- 2、与服务器进行连接
- 3、连接结果
- 4、获取接收数据
- 5、设置接收
- 技术名词解释
- 技术细节
- 小结
- 注意
- 成果展示
概要
利用Qt 封装好的QTcpServer 与 QTcpSocket 进行通信交流,实现tcp 的通信流程
整体架构流程
框架采用qt 界面 ,利用qt 和 c++代码实现逻辑界面,采用cmakelists 与 visual studio 2017 联合编译创建项目
服务端
1、创建QTcpServer 对象
m_tcpServer = new QTcpServer();
2、设置监听端口,进行监听
if (m_tcpServer->listen(QHostAddress::Any, port)) {
qInfo() << QStringLiteral("server listening …");
}
3、等待连接
connect(m_tcpServer,&QTcpServer::newConnection,this,&MainWindow::slot_newConnection);
客户端连接到服务器后,会触发newConnection 信号,再响应函数中编写连接后的操作: 1,获取连接的客户端socket 指针 2,获取连接客户端的ip 地址(ipv4)和端口 3, 建立信号连接,将获取客户端数据的信号和断开信号和 他们对应的响应进行连接
m_tcpSocket = m_tcpServer->nextPendingConnection();
m_clientName = QHostAddress(m_tcpSocket->peerAddress().toIPv4Address()).toString();
m_clientName += "::" + QString::number(m_tcpSocket->peerPort());
m_chatDataStr += QStringLiteral("有客户端:") + m_clientName + QStringLiteral(" 连接\\n");
m_readDataEdit->setText(m_chatDataStr);
connect(m_tcpSocket, &QTcpSocket::readyRead, this, &MainWindow::slot_recvClientData);
connect(m_tcpSocket, &QTcpSocket::disconnected, this, [this]() {
m_chatDataStr += QStringLiteral("有客户端:") + m_clientName + QStringLiteral(" 断开连接\\n");
m_readDataEdit->setText(m_chatDataStr);
m_tcpSocket->close();
});
4、接收处理
将客户端发送的数据转成可识别中文的字符串,显示在控件上
if (m_tcpSocket == nullptr) {
return;
}
auto data = m_tcpSocket->readAll();
QString str = QString::fromUtf8(data);
qInfo() << str;
m_chatDataStr += m_clientName + QStringLiteral("说 ")+ str + QStringLiteral("\\n");
m_readDataEdit->setText(m_chatDataStr);
5、发送处理
获取控件中的字符串信息,然后发送到客户端并显示发送记录
QString str = m_writeDataEdit->toPlainText();
m_tcpSocket->write(str.toUtf8());
m_tcpSocket->flush();
m_writeDataEdit->clear();
m_chatDataStr += QStringLiteral("服务器对") + m_clientName + QStringLiteral("说 ") + str + QStringLiteral("\\n");
m_readDataEdit->setText(m_chatDataStr);
客户端
1、创建客户端通信套接字
m_tcpSocket = new QTcpSocket();
2、与服务器进行连接
需要输入服务器的ip 地址和端口号,然后进行连接
QHostAddress address = QHostAddress(m_ipEdit->text());
int port = m_portEdit->text().toInt();
m_tcpSocket->connectToHost(address,port);
3、连接结果
连接和断开QT已经封装在QTcpSocket 类里面了,只需要获取socet 的 连接和断开信号,就能知道是否成功了
connect(m_tcpSocket, &QTcpSocket::connected, this, [=] {
m_chatDataStr += QStringLiteral("服务器连接成功!\\n");
m_readDataEdit->setText(m_chatDataStr);
});
connect(m_disConnectBtn, &QPushButton::clicked, this, &MainWindow::slot_disConnect);
connect(m_tcpSocket, &QTcpSocket::disconnected, this, [=] {
m_chatDataStr += QStringLiteral("服务器连接断开!\\n");
m_readDataEdit->setText(m_chatDataStr);
});
4、获取接收数据
先创建接收的信号与信号槽连接
connect(m_tcpSocket, &QTcpSocket::readyRead, this, &MainWindow::slot_recvData);
然后接收套接字socket 传回的数据
if (m_tcpSocket == nullptr) {
return;
}
auto data = m_tcpSocket->readAll();
QString str = QStringLiteral("服务器说: ") + QString::fromUtf8(data);
m_chatDataStr += str + "\\n";
m_readDataEdit->setText(m_chatDataStr);
5、设置接收
接收服务器发送给客户端的数据
QString str = m_writeDataEdit->toPlainText();
m_tcpSocket->write(str.toUtf8());
m_chatDataStr += QStringLiteral("客户端(自己)说:") + str + "\\n";
m_readDataEdit->setText(m_chatDataStr);
m_writeDataEdit->clear();
技术名词解释
socket: 网络通信中 的套接字,是网络协议中的通信接口 tcp: 面向连接的,可靠的,以字节流方式进行网络通信的通信协议
技术细节
服务端使用 flush 函数作用:立即发送 发送的函数: socket 中的write 函数 接收的函数:socket 中的readall 函数 就可以全部接收了
小结
利用QT 封装好的QTcpServer 和 QTcpSocket 可以方便的进行两者的通信,其中连接断开都会有相应的响应,这是因为tcp 的通信协议原因,连接会双方确认,断开也是同理,使用时候要注意信号是否装载以及是否和槽建立的连接等问题。
注意
这一篇介绍的服务器与客户端一对一的连接,多个客户端连接时不会报错,但是最新的客户端套接字会把之前的客户端套接字覆盖,只有最新连接的客户端才能通信,下一篇会介绍服务器与客户端一对多的情况,实现多个客户端和服务器通信
成果展示
这是代码运行结果 先设置服务器端口号,启用监听 设置客户端界面的服务器地址和端口(我都在本地,所以地址时 localhost 或者 127.0.0.1) 然后进行连接,连接成功服务器和客户端界面都有提示 然后双方互发消息,也会与对应的所属 最后客户端断开连接,两个界面都断开,但是服务器仍然在监听,可以再次连接
评论前必须登录!
注册