tcp编程中写的一个简单的单项传输数据的小例子,和上一节一样,分为客户端和服务端程序,下面看一下界面的效果。
创建的方法和之前一样,上面上代码:
客户端
Client.h
#ifndef CLIENT_H
#define CLIENT_H#include <QDialog>
#include <QAbstractSocket>QT_BEGIN_NAMESPACE
namespace Ui { class Client; }
QT_END_NAMESPACE
class QTcpSocket;
class Client : public QDialog
{Q_OBJECTpublic:Client(QWidget *parent = nullptr);~Client();private slots:void displayTip();void errorTip(QAbstractSocket::SocketError);void on_sendButton_clicked();void on_connectButton_clicked(bool checked);void on_textEdit_cursorPositionChanged();private:Ui::Client *ui;QTcpSocket *tcpClient;qint8 flag;
};
#endif // CLIENT_H
Client.cpp
#include "client.h"
#include "ui_client.h"
#include <QtNetwork>
#include <QMessageBox>
#include <QDebug>
/*问题描述
@1 再次输入要发送的文本时,上次发送成功的提示依旧存在;
@2 断开连接后,上次发送成功的提示依旧存在;*/
Client::Client(QWidget *parent): QDialog(parent), ui(new Ui::Client),flag(0)
{ui->setupUi(this);setWindowTitle(tr("客户端"));tcpClient = new QTcpSocket(this);connect(tcpClient,&QTcpSocket::connected,this,&Client::displayTip);void (QTcpSocket:: *errorSign)(QAbstractSocket::SocketError) = &QTcpSocket::error;connect(tcpClient,errorSign,this,&Client::errorTip);ui->connectButton->setText(tr("连接"));ui->statusLabel->setText(tr("未连接"));ui->tipLabel->setText(tr(" "));ui->sendButton->setEnabled(false);
}Client::~Client()
{delete ui;
}void Client::displayTip()
{ui->statusLabel->setText(tr("连接成功"));ui->sendButton->setEnabled(true);
}void Client::errorTip(QAbstractSocket::SocketError)
{qDebug()<<"发生错误:"<<tcpClient->errorString();tcpClient->abort();ui->statusLabel->setText(tr("连接已断开"));ui->tipLabel->setText(tr(" "));ui->connectButton->setText(tr("连接"));flag = 1;// qDebug()<<"flag = 1";
}void Client::on_sendButton_clicked()
{QString str = ui->textEdit->toPlainText();QByteArray text = str.toUtf8();//返回一个字符串的utf-8形式,可以表示所有字符
// QByteArray text = str.toLatin1();//只能输出英文和数字,即拉丁文,汉字会被?代替
// QByteArray text = str.toLocal8Bit();//只能输出英文和数字,汉字会被乱码qint64 bytes = tcpClient->write(text);if(bytes > 0){
// qDebug()<<"发送成功!";ui->textEdit->clear();ui->tipLabel->setText(tr("数据发送成功!"));}
}void Client::on_connectButton_clicked(bool checked)
{if(ui->IPLineEdit->text().isEmpty() || ui->portLineEdit->text().isEmpty()){QMessageBox::information(this,tr("警告"),tr("请查看主机名或端口是否已输入"));return ;}if(checked || flag == 1){ui->connectButton->setText(tr("断开连接"));ui->statusLabel->setText(tr("连接中......"));ui->tipLabel->setText(tr(" "));tcpClient->connectToHost(ui->IPLineEdit->text(),ui->portLineEdit->text().toInt());}else{ui->connectButton->setText(tr("连接"));ui->statusLabel->setText(tr("未连接"));ui->tipLabel->setText(tr(" "));
// tcpClient->disconnectFromHost();//等待所有数据传输完成后,关闭套接字
// tcpClient->close();//不会立即关闭套接字tcpClient->abort();//立即关闭套接字}
}void Client::on_textEdit_cursorPositionChanged()
{ui->tipLabel->setText(tr(" "));
}
服务端的程序:
Server.h
#ifndef SERVER_H
#define SERVER_H#include <QDialog>
#include <QAbstractSocket>QT_BEGIN_NAMESPACE
namespace Ui { class Server; }
QT_END_NAMESPACEclass QTcpServer;
class QTcpSocket;class Server : public QDialog
{Q_OBJECTpublic:Server(QWidget *parent = nullptr);~Server();private slots:void dataDisplayTip();void recevieData();void dealData();void errorTip(QAbstractSocket::SocketError);void on_listenButton_clicked();void on_disconnectButton_clicked();private:Ui::Server *ui;QTcpServer * myServer;QTcpSocket *socketConnected;
};
#endif // SERVER_H
Server.cpp
#include "server.h"
#include "ui_server.h"
#include <QtNetwork>
#include <QTimer>
#include <QDebug>/*问题描述
@1 客户端单一方面断开与服务器的连接时,服务器不应该显示为连接异常;
@2 服务器在与客户端连接的过程中,可以选择单方面断开与客户端的连接;
@3 客户端发送中文时,服务端显示乱码;*/Server::Server(QWidget *parent): QDialog(parent), ui(new Ui::Server)
{ui->setupUi(this);myServer = new QTcpServer(this);connect(myServer,&QTcpServer::newConnection,this,&Server::recevieData);
// connect(myServer,&QTcpServer::connected,this,&Server::tipInfo);ui->statusLabel->setText(tr("未建立连接"));ui->RecevieDataLabel->setText(tr(" "));}Server::~Server()
{delete ui;
}void Server::dataDisplayTip()
{ui->RecevieDataLabel->setText(tr(" "));
}void Server::recevieData()
{ui->statusLabel->setText(tr("连接成功"));socketConnected = myServer->nextPendingConnection();connect(socketConnected,&QTcpSocket::readyRead,this,&Server::dealData);void (QTcpSocket:: *errorSign)(QAbstractSocket::SocketError) = &QTcpSocket::error;connect(socketConnected,errorSign,this,&Server::errorTip);myServer->close();
}void Server::dealData()
{if(socketConnected->bytesAvailable()>0){QString str = socketConnected->readAll();//QByteArray dataui->textEdit->append(str);ui->RecevieDataLabel->setText(tr("消息接收完成!"));QTimer *timer = new QTimer(this);connect(timer,SIGNAL(timeout()),this,SLOT(dataDisplayTip()));timer->start(2000);}
}void Server::errorTip(QAbstractSocket::SocketError)
{qDebug()<<socketConnected->errorString();ui->listenButton->setEnabled(true);socketConnected->close();myServer->close();ui->statusLabel->setText(tr("连接中断"));ui->RecevieDataLabel->setText(tr(" "));
}void Server::on_listenButton_clicked()
{if(!myServer->listen(QHostAddress::LocalHost,6787)){qDebug()<<"监听失败!";ui->statusLabel->setText(tr("监听失败!"));myServer->close();}ui->statusLabel->setText(tr("监听成功"));ui->RecevieDataLabel->setText(tr(" "));ui->listenButton->setEnabled(false);
}void Server::on_disconnectButton_clicked()
{ui->statusLabel->setText(tr("连接中断"));ui->RecevieDataLabel->setText(tr(" "));ui->listenButton->setEnabled(true);socketConnected->disconnectFromHost();myServer->close();
}
先运行服务端程序,点击监听按钮,再运行客户端程序,输入IP和端口,同样程序之间实现的是本地地址通信,端口6787,主机名或ip都可以,点击连接,若主机名和IP没有填写,直接点击连接,会弹出提示窗口,提示查看IP和端口的填写情况,对话框下面会显示连接状态,连接成功后,输入要发送的内容,点击发送按钮可以发送信息,会有相应的发送和接收数据成功与否的显示。
效果图如下:
该注意的点:
在数据传输的过程中,编码格式的一致,否则会导致乱码,代码中含有我对与一些函数的理解,加以记录,以备后用。