本文实验测试部分可参考基于QT的一款P2P共享文件系统
源码包下载地址基于QT的一款P2P共享文件系统下载,想要免费获取可以私信我
自己动手完成一款简易P2P共享文件软件的制作(一)
4. 客户机设计
客户机设计相较于服务器设计相对繁琐,因为除了需要设计一个GUI界面以及与服务器通信代码外,还需要增加客户端之间对等传输(P2P)相关代码。
4.1 GUI界面与功能设计
我们要为客户机设计的功能如下:
- 登陆
- 注册
- 获取我的共享文件信息
- 删除我的共享文件
- 上传我的共享文件
- 在P2P网络中搜索某个文件
- 从P2P网络中下载某个文件
我们将这些功能集成到一个界面中,我们设计的界面如下:

界面设计代码如下:
新建tcp_client.h文件,添加如下代码:
#ifndef TCP_CLIENT_H
#define TCP_CLIENT_H
#include <QMainWindow>
#include <QWidget>
#include <QListWidget>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QProgressBar>
#include <QGridLayout>
#include <QString>
#include <QTableWidget>
#include <QList>
#include <QTimer>
#include <QtNetwork/QHostAddress>
#include <QtNetwork/QTcpSocket>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
QWidget *myWidget;
QListWidget *ContentListWidget;
QLabel *UserNameLabel;
QLineEdit *UserNameLineEdit;
QLabel *UserPasswdLabel;
QLineEdit *UserPasswdLineEdit;
QLabel *ServerIPLabel;
QLineEdit *ServerIPLineEdit;
QLabel *PortLabel;
QLineEdit *PortLineEdit;
QPushButton *EnterBtn;
QPushButton *SignBtn;
QTableWidget *ResultTableWidget;
QLineEdit *SearchLineEdit;
QPushButton *SearchBtn;
QProgressBar *ProgressBar;
QPushButton *DownloadBtn;
QTimer *timer;
QTableWidget *ShareTableWidget;
QPushButton *FlushBtn;
QPushButton *DisableBtn;
QPushButton *ShareBtn;
QLineEdit *DirLineEdit;
QPushButton *SelectDirBtn;
QGridLayout *layout1;
QGridLayout *layout2;
QGridLayout *layout3;
QGridLayout *mainLayout;
bool status;
int port;
QHostAddress *ServerIP;
QString UserName;
};
#endif // TCP_CLIENT_H
新建tcp_client.cpp文件,添加如下代码:
#include "tcp_client.h"
#include "tcp_meta.h"
#include <QMessageBox>
#include <QHostInfo>
#include <QByteArray>
#include <QFileDialog>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle("P2P Client");
setGeometry(250,200,850,500);
ContentListWidget = new QListWidget;
myWidget = new QWidget;
UserNameLabel = new QLabel("用户名:");
UserNameLineEdit = new QLineEdit;
UserPasswdLabel = new QLabel("密码:");
UserPasswdLineEdit = new QLineEdit;
ServerIPLabel = new QLabel("服务器IP:");
ServerIPLineEdit = new QLineEdit("192.168.43.98");
PortLabel = new QLabel("端口:");
PortLineEdit = new QLineEdit;
EnterBtn = new QPushButton("登陆");
SignBtn = new QPushButton("注册");
ShareTableWidget = new QTableWidget;
ShareTableWidget->setColumnCount(6);
QStringList tableHead;
tableHead << "文件名" << "大小" << "文件路径" << "IP" << "端口" << "选择";
ShareTableWidget->setHorizontalHeaderLabels(tableHead);
FlushBtn = new QPushButton("我的共享文件");
DisableBtn = new QPushButton("取消选中项共享");
ShareBtn = new QPushButton("上传我的文件");
ResultTableWidget = new QTableWidget;
ResultTableWidget->setColumnCount(7);
tableHead.clear();
tableHead << "文件名" << "大小" << "文件路径" << "拥有者" << "状态" << "IP" << "选择";
ResultTableWidget->setHorizontalHeaderLabels(tableHead);
SearchBtn = new QPushButton("搜索");
SearchLineEdit = new QLineEdit;
ProgressBar = new QProgressBar;
ProgressBar->setRange(0,100);
DownloadBtn = new QPushButton("下载选中项");
timer = new QTimer();
DirLineEdit = new QLineEdit;
SelectDirBtn = new QPushButton("选择保存位置");
layout1 = new QGridLayout();
layout2 = new QGridLayout();
layout3 = new QGridLayout();
mainLayout = new QGridLayout();
layout1->addWidget(ContentListWidget,0,0,1,2);
layout1->addWidget(UserNameLabel,1,0);
layout1->addWidget(UserNameLineEdit,1,1);
layout1->addWidget(UserPasswdLabel,2,0);
layout1->addWidget(UserPasswdLineEdit,2,1);
layout1->addWidget(ServerIPLabel,3,0);
layout1->addWidget(ServerIPLineEdit,3,1);
layout1->addWidget(PortLabel,4,0);
layout1->addWidget(PortLineEdit,4,1);
layout1->addWidget(EnterBtn,5,0,1,2);
layout1->addWidget(SignBtn,6,0,1,2);
layout2->addWidget(ShareTableWidget,0,0,1,3);
layout2->addWidget(FlushBtn,1,0);
layout2->addWidget(DisableBtn,1,1);
layout2->addWidget(ShareBtn,1,2);
layout3->addWidget(ResultTableWidget,0,0,1,2);
layout3->addWidget(SearchLineEdit,1,0);
layout3->addWidget(SearchBtn,1,1);
layout3->addWidget(ProgressBar,2,0,1,2);
layout3->addWidget(DirLineEdit,3,0);
layout3->addWidget(SelectDirBtn,3,1);
layout3->addWidget(DownloadBtn,4,0,1,2);
mainLayout->addLayout(layout1,0,0,2,2);
mainLayout->addLayout(layout2,0,2,1,1);
mainLayout->addLayout(layout3,1,2,1,1);
myWidget->setLayout(mainLayout);
setCentralWidget(myWidget);
status = false;
port = 8010;
PortLineEdit->setText(QString::number(port));
ServerIP = new QHostAddress;
ShareBtn->setEnabled(false);
FlushBtn->setEnabled(false);
DisableBtn->setEnabled(false);
SearchBtn->setEnabled(false);
DownloadBtn->setEnabled(false);
}
MainWindow::~MainWindow()
{
delete PortLabel;
delete PortLineEdit;
delete EnterBtn;
delete SignBtn;
delete UserNameLabel;
delete UserNameLineEdit;
delete UserPasswdLabel;
delete UserPasswdLineEdit;
delete ServerIPLabel;
delete ServerIPLineEdit;
delete ContentListWidget;
delete ShareTableWidget;
delete DisableBtn;
delete FlushBtn;
delete ResultTableWidget;
delete SearchLineEdit;
delete SearchBtn;
delete DownloadBtn;
delete timer;
delete ProgressBar;
delete SelectDirBtn;
delete DirLineEdit;
delete layout1;
delete layout2;
delete layout3;
delete mainLayout;
delete myWidget;
delete ServerIP;
}
在客户机中,所有要实现的功能都必须建立在客户机与服务器之间已经建立起tcp连接。而要建立连接,一种是无用户名式的请求注册连接,另一种是带用户名和密码的请求登陆连接,我们先介绍注册连接。在注册流程中,我们设定的方案是,用户先输入注册名与密码,确认服务器IP地址与端口号无误后点击注册按钮,然后等待服务器的注册回复消息,并且断开与服务器的tcp连接以便下次重新申请注册。添加的代码如下:
tcp_client.h文件:
class MainWindow : public QMainWindow
{
enum MsgKind{
NAMEMSG = 0,//登陆消息
METAMSG = 1,//上传共享文件元数据消息
DISCONNECT = 2,//断连消息
SHAREMSG = 3,//获取我的共享文件消息
DELETEMSG = 4,//删除共享文件元数据消息
SEARCHMSG = 5,//搜索消息
SIGNMSG = 6,//注册消息
OTHERMSG = 7//普通消息
};
private:
...
QTcpSocket *tcpSocket;
void FormatMsg(QString &msg, MsgKind kind);
public slots:
void slotSignUp();//注册按钮对应的槽函数
void SignConnected();//注册的tcp建立连接后进入该函数
void SignDisconnected();//注册的tcp断开连接后进入该函数
void SignDataReceived();//注册过程中,服务器发送来消息会进入该函数
...
};
tcp_client.cpp文件:
void MainWindow::SignConnected(){
SignBtn->setEnabled(false);
int length = 0;
QString passwd = UserPasswdLineEdit->text();
//分号用于隔开两个字符串
QString msg = UserName + ";" + passwd + ";";
FormatMsg(msg, SIGNMSG);//格式化注册消息
if((length = tcpSocket->write(msg.toLatin1(),msg.length())) != msg.length()){
return;
}
}
void MainWindow::

398

被折叠的 条评论
为什么被折叠?



