首先声明此文章为学习Qt的网络通讯找的例子,仅供学习用,以下为自己总结,原作者的连接如下:GitHub - manfredipist/QTcpSocket: A simple Qt client-server TCP architecture to transfer data between peersA simple Qt client-server TCP architecture to transfer data between peers - GitHub - manfredipist/QTcpSocket: A simple Qt client-server TCP architecture to transfer data between peers
https://github.com/manfredipist/QTcpSocket
在学习网络通讯时,Qt给你封装好了QTcpSocket类,来进行网络套接字通讯,经常会有需求进行一对多的功能,一台服务器,对多台客户端的开发,应用到实践中
实现分为:1、客户端 Client
2、服务器端 Server
约定的数据格式头
fileType:attachment 、 message
QString("fileType:message,fileName:null,fileSize:%1;").arg(str.size()).toUtf8()
客户端 Client
.h文件
- //1:读数据
- void readSocket();
- //2:断开连接
- void discardSocket();
- //3:错误连接
- void displayError(QAbstractSocket::SocketError socketError);
- //4:发送数据
- void sendMessage();
.cpp文件
- //1:连接
- socket->connectToHost(QHostAddress::LocalHost,8080);
-
- //2:读取数据在readyRead槽下
- void MainWindow::readSocket()
- {
- QByteArray buffer;
-
- QDataStream socketStream(socket);
- socketStream.setVersion(QDataStream::Qt_5_7);
-
- socketStream.startTransaction();
- socketStream >> buffer;
-
- QString header = buffer.mid(0,128);
- QString fileType = header.split(",")[0].split(":")[1];
-
- buffer = buffer.mid(128);
- if(fileType=="attachment"){
- //TODO
- }else if(fileType=="message"){
- //TODO
- QString message = QString("%1 :: %2").arg(socket->socketDescriptor()).arg(QString::fromStdString(buffer.toStdString()));
- }
- }
-
- //3:发送数据
- void Mainindow::sendMessage()
- {
- //1:组装数据
- QString str = ui->lineEdit_message->text();
-
- QDataStream socketStream(socket);
- socketStream.setVersion(QDataStream::Qt_5_7);
-
- QByteArray header;
- header.prepend(QString("fileType:message,fileName:null,fileSize:%1;").arg(str.size()).toUtf8());
- header.resize(128);
- //2:发送数据的包封装方式
- QByteArray byteArray = str.toUtf8();
- byteArray.prepend(header);
- //3:数据发送
- socketStream << byteArray;
- }
服务器端 Server
1:监听端口
- m_server = new QTcpServer();
- m_server->listen(QHostAddress::Any, 8080)
2:当有客户端client连接时,发出newConnection 信号,由于要进行多客户端功能,得把客户端给存起来
- void MainWindow::appendToSocketList(QTcpSocket* socket)
- {
- connection_set.insert(socket);
- connect(socket, &QTcpSocket::readyRead, this, &MainWindow::readSocket);
- connect(socket, &QTcpSocket::disconnected, this, &MainWindow::discardSocket);
- connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError)));
- ui->comboBox_receiver->addItem(QString::number(socket->socketDescriptor()));
- displayMessage(QString("INFO :: Client with sockd:%1 has just entered the room").arg(socket->socketDescriptor()));
- }
-
- void MainWindow::newConnection()
- {
- while (m_server->hasPendingConnections())
- appendToSocketList(m_server->nextPendingConnection());
- }
3:readSocket()功能与客户端client一致,唯一区别,打印的时候,带上了客户端连接的唯一标识:socket->socketDescriptor
4:reinterpret_cast<>用法将sender()转换成socket对象
reinterpret_cast与static_cast_云之舟_的博客-CSDN博客_reinterpret_cast
5:分发消息的机制
- void MainWindow::sendMessage(QTcpSocket* socket)
- {
- if(socket)
- {
- if(socket->isOpen())
- {
- QString str = ui->lineEdit_message->text();
-
- QDataStream socketStream(socket);
- socketStream.setVersion(QDataStream::Qt_5_7);
-
- QByteArray header;
- header.prepend(QString("fileType:message,fileName:null,fileSize:%1;").arg(str.size()).toUtf8());
- header.resize(128);
-
- QByteArray byteArray = str.toUtf8();
- byteArray.prepend(header);
-
- socketStream.setVersion(QDataStream::Qt_5_7);
- socketStream << byteArray;
- }
- else
- QMessageBox::critical(this,"QTCPServer","Socket doesn't seem to be opened");
- }
- else
- QMessageBox::critical(this,"QTCPServer","Not connected");
- }
-
-
- void MainWindow::on_pushButton_sendMessage_clicked()
- {
- QString receiver = ui->comboBox_receiver->currentText();
-
- if(receiver=="Broadcast")
- {
- foreach (QTcpSocket* socket,connection_set)
- {
- sendMessage(socket);
- }
- }
- else
- {
- foreach (QTcpSocket* socket,connection_set)
- {
- if(socket->socketDescriptor() == receiver.toLongLong())
- {
- sendMessage(socket);
- break;
- }
- }
- }
- ui->lineEdit_message->clear();
- }