一、界面设计
在做软件之前使用“软件界面设计工具”先设计并绘制出软件界面,方便在写代码之前确认“功能需求”以及“交互流程”。
这里使用的软件是:“Axure RP”
二、新建工程与绘制界面
- 创建工程
使用Qt Creater 新建一个“Qt Widgets Application”。填好工程名字后,然后点击下一步,直到类信息页面选择Base class为:“QDialog”并修改类名字为“NetDialog”,然后一直下一步,直到进入代码编辑页面就完成了工程创建。完整的工程目录入下图所示:
- 绘制界面
双击工程文件中的“dialog.ui”文件,在弹出的界面绘制页面绘制章节一种所设计的界面,结果如下图所示:
三、用到的库函数说明
- Tcp client
QTcpSocket { //用的的qt提供的类
void connectToHost(const QHostAddress &address, quint16 port);//连接到指定地址和端口的Tcp服务器
void disconnectFromHost();//断开与服务器的连接
void close();//关闭资源
bool isOpen();//通信是否建立
qint64 write(const char \*data, qint64 len);//向服务器端发送数据
QByteArray readAll();//当收到“接收数据消息”之后,使用此函数读取收到的数据
Q_SIGNALS: //用到的信号
void readyRead(); //收到数据
void disconnected(); //通信断开
}
- Tcp server
QTcpServer { //用的的qt提供的类
bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);//开启tcp服务端,并监听指定端口
void close();//关闭资源
bool isOpen();//是否打开
qint64 write(const char \*data, qint64 len);//向客户端写数据
QByteArray readAll();//当收到“接收数据消息”之后,使用此函数读取收到的数据
QTcpSocket \*nextPendingConnection();//使用此函数,应答一个客户端的建立通信请求,并返回QTcpSocket,用于与客户端完成收发数据等
quint16 localPort();//与客户端建立通信所对应的连接的 本地端口
QHostAddress localAddress();//与客户端建立通信所对应的连接的 本地ip地址
quint16 peerPort();//与客户端建立通信所对应的连接的 客户端的端口
QHostAddress peerAddress();//与客户端建立通信所对应的连接的 客户端的ip地址
Q_SIGNALS: //用到的信号
void readyRead(); //收到数据
void disconnected(); //通信断开
void newConnection(); //有新的客户端请求连接到本服务端
}
- Udp client | server | broadcast (三个端共用同样的系统函数)
QUdpSocket { //用的的qt提供的类
bool open(OpenMode mode); //打开通信端口
void close(); //关闭通信
bool isOpen();//是否打开
bool bind(quint16 port = 0);//绑定本地的一个端口作为UDP服务端监听端口
qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port);//发送数据
qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *host = nullptr, quint16 *port = nullptr);//收到读取信号后,使用此函数读取数据
Q_SIGNALS: //用到的信号
void readyRead(); //收到数据
void disconnected(); //通信断开
}
四、编写逻辑代码
- 打开与关闭的逻辑
//经过简化的代码
void KcpDialog::on_pushButtonOpen_clicked()
{
if(netmanager_p->IsOpen()) { //do close
netmanager_p->Close(); //关闭
} else { //do open
QString des_ip = ui->lineEditDesIp->text();//读取地址
QString des_port = ui->lineEditDesPort->text();//读取端口
int net_type_index = ui->comboBoxNetType->currentIndex();//读取打开类型
//ip, port
des_ip_ = des_ip;
des_port_ = static_cast<quint16>(des_port.toInt());
netmanager_p->Open(net_type_index, des_ip_, des_port_);//打开
}
}
- 发送数据逻辑
//经过简化的代码
void KcpDialog::on_pushButtonSend_clicked()
{
QString send_str = ui->textEditSend->toPlainText();//读取待发送数据
QByteArray send_ba;
send_ba = send_str.toUtf8();
if(ui->checkBoxSendHex->isChecked()) {//是否启用Hex
send_ba = send_ba.toHex();
}
netmanager_p->Send(send_ba.data(), send_ba.size());//发送数据
}
- 接收数据逻辑
void KcpDialog::OnRecv(QByteArray *data, const QString ip, const quint16 port) {
QString str;
if(ui->checkBoxRecvHex->isChecked()) { //是否启用Hex
QByteArray ba;
QString temp(*data);
StringUtil::StringToHex(temp, ba);
str += ba;
} else {
str += *data;
}
str += "\n";
AddRecvMsg(str);//现实数据到接收编辑框
}
五、获取源代码
六、效果图
- 在windows系统下效果
- 在MacOS系统下效果