项目要求是要达到即时通讯,群聊和私聊都可以,可以发文件,登陆,注册。可以理解为超级简易的QQ(好像有点皮了,我怎么敢和QQ比呢,哈哈)。
客户端界面(这个就看看用户的在线情况,顺便监听聊天室的情况)
这个是基础了吧,不会的自行百度
bool MySql::initsql() { //初始化并建立一个数据库连接
//连接数据库
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
db.setHostName("localhost");
db.setDatabaseName("qq");
db.setUserName("root");
db.setPort(3306);
db.setPassword("123456789");
if (db.open()) {
qDebug() << "数据库连接成功,666666!" << endl;
} else {
qDebug() << "数据库连接失败,伞兵!" << endl;
QMessageBox::warning(NULL, "error", "数据库连接失败");
return 0;
}
}
也就是把数据传到服务器中,再和数据库里面的数据进行比较,再将信息反馈回去,简单
int MySql::Login(QString Name, QString Password) {
QString str1, str2;
query = new QSqlQuery;
query->exec(QString("select Password,status from user where userName='%1'").arg(Name));
while (query->next()) {
str1 = query->value(0).toString(); //密码
str2 = query->value(1).toString(); //在线状态
}
qDebug() << str1 << str2 << endl;
// qDebug()<<"数据库连接成功,666666!"<
if (str2 == NULL) return 3; //用户不存在
else if (str2 == '1') return 2; //用户已经在线
else if ((str2 == '0') && (str1 == Password)) return 1; //用户名和密码都正确
else if ((str2 == '0') && (str1 != Password)) return 0; //密码错误
}
原理同上
bool MySql::Regist(QString Name, QString Password, QString Mail) {
char status = '0', Mail2 = '0', Mail3 = '0';
QString str = QString("select * from user where userName='%1'").arg(Name);
query = new QSqlQuery;
query->exec(str);
query->last();
int record = query->at() + 1;
if (record != 0)
return false;
str = QString("insert into user value('%1','%2','%3','%4','%5','%6')").arg(Name).arg(status).arg(Password).arg(Mail).arg(Mail2).arg(Mail3);
bool ret = query->exec(str);//数据模型重新查询数据,更新tableView显示
qDebug() << "到达数据库注册!" << str << endl;
return ret;
}
同上
int MySql::findpwd(QString Name, QString Mail) { //找回密码
QString str1, str2, str3;
query = new QSqlQuery;
query->exec(QString("select Mail from user where userName='%1'").arg(Name));
while (query->next()) {
str1 = query->value(0).toString(); //邮件
}
if ((str1 == Mail) /*&& (str2 == question) && (str3 == answer)*/) return 3; //信息正确
else if (str1 == NULL) return 4; //用户不存在
else return 2; //邮件错误
}
接收从客户端传输过来的数据,通过前缀将它们分类,处理后发送回客户端或者服务器,这段代码可以说是服务器的重中之重,处理各种数据。
void Server::ReadMSG() { //读取来自客户端的数据
qDebug() << "读取客户端数据" << endl;
QString data = socket->readAll(); //读取客户端发送的数据
qDebug() << data;
QStringList list = data.split("#");
bool ret = 0;
int temp = 0;
QString sendData = list[0];
QString password, str1, str2, str3, str4;
if (list[0] == "a") { //注册
qDebug() << "到达注册" << endl;
ret = checkSignUp(list[1], list[2], list[3]);
if (ret)
sendData = sendData + "#true";
else
sendData = sendData + "#false";
socket->write(sendData.toLatin1());
} else if (list[0] == "b") { //登录
temp = checkLogIn(list[1], list[2]);
if (temp == 1) {
query = new QSqlQuery;
query->exec(QString("update user set status='%1' where userName='%2'").arg(1).arg(list[1])); //设置数据库中的status为1
sendData = sendData + "#" + list[1] + "#true";
} else if (temp == 0) sendData = sendData + "#false" + "#0";
else if (temp == 2) sendData = sendData + "#false" + "#2";
else if (temp == 3) sendData = sendData + "#false" + "#3";
socket->write(sendData.toUtf8());
} else if (list[0] == "c") { //找回密码
temp = findpwd(list[1], list[2]);
if (temp == 0) sendData = sendData + "#false" + "#0";
else if (temp == 1) sendData = sendData + "#false" + "#1";
else if (temp == 2) sendData = sendData + "#false" + "#2";
else if (temp == 4) sendData = sendData + "#false" + "#4";
else {
QString str = QString("select Password from user where userName='%1'").arg(list[1]);
query = new QSqlQuery;
query->exec(str);
while (query->next()) {
password = query->value(0).toString();
}
sendData = sendData + "#true" + "#" + password;
}
socket->write(sendData.toUtf8());
} else if (list[0] == "d") { //退出登录
query = new QSqlQuery;
query->exec(QString("update user set status='%1' where userName='%2'").arg(0).arg(list[1])); //设置数据库中的status为0
} else if (list[0] == "e") { //返回用户列表
// query->exec(QString("update user set status='%1' where userName='%2'").arg(1).arg(list[1])); //设置数据库中的status为1
query = new QSqlQuery;
query->exec(QString("update user set CIP='%1' , CPort='%2' where userName='%3'").arg(list[2]).arg(list[3]).arg(list[1]));
qDebug() << list[2] << list[3] << list[1] << "6666666666666666666666666" << endl;
query = new QSqlQuery;
query->exec("select userName from user");
QString str6 = NULL;
while (query->next()) {
str1 = query->value(0).toString();
str6 = str6 + "#" + str1;
}
query = new QSqlQuery;
query->exec(QString("select name1,MSG from msg where name2='%1'").arg(list[1]));
while (query->next()) {
str3 = query->value(0).toString();
str4 = query->value(1).toString();
}
if (str4 != NULL) {
str3 = str3 + ":" + str4;
}
sendData = sendData + str6 + "#" + "end" + "#" + str3;
socket->write(sendData.toUtf8());
} else if (list[0] == "f") { //群聊消息
qDebug() << "群聊";
//获取系统时间
QDateTime time = QDateTime::currentDateTime();
QString Time = time.toString("yyyy-MM-dd ddd hh:mm:ss");
ui->textBrowser->append(Time);
ui->textBrowser->append(list[1] + ":" + list[2]);
sendData = sendData + "#" + list[1] + "#" + list[2];
query = new QSqlQuery;
int str5;
qDebug() << "群聊 1";
query->exec(QString("select CIP, CPort from user where status = '%1'").arg(1));
while (query->next()) {
qDebug() << "群聊 2";
QString str1 = query->value(0).toString();
str5 = query->value(1).toInt();
socket = new QTcpSocket();
socket->abort(); //取消已有的连接
socket->connectToHost(str1, str5); //连接到客户端
socket->waitForConnected();
socket->write(sendData.toUtf8());
}
} else if (list[0] == "g") { //私聊
qDebug() << "到达服务器的私聊";
QString Status;
query = new QSqlQuery;
query->exec(QString("select status from user where userName='%1'").arg(list[1]));
while (query->next()) {
Status = query->value(0).toString();
}
if (Status == "1") {
query->exec(QString("select CIP, CPort from user where userName = '%1'").arg(list[1]));
while (query->next()) {
str1 = query->value(0).toString();
str2 = query->value(1).toString();
}
sendData = sendData + "#" + list[1] + "#" + "1" + "#" + str1 + "#" + str2;
} else {
sendData = sendData + "#" + list[1] + "#" + "0";
}
socket->write(sendData.toUtf8());
} else if (list[0] == "s") { //获取信息以发送文件
query->exec(QString("select CIP, CPort from user where userName = '%1'").arg(list[1]));
while (query->next()) {
str1 = query->value(0).toString();
str2 = query->value(1).toString();
}
sendData = sendData + "#" + list[1] + "#" + "1" + "#" + str1 + "#" + str2;
socket->write(sendData.toUtf8());
} else if (list[0] == "i") { //离线消息
query = new QSqlQuery;
query->exec(QString("insert into msg (name1, name2, MSG) values('%1','%2','%3')").arg(list[1]).arg(list[2]).arg(list[3]));
} else if (list[0] == "y") { //获取信息以发送私聊信息
query->exec(QString("select CIP, CPort from user where userName = '%1'").arg(list[1]));
while (query->next()) {
str1 = query->value(0).toString();
str2 = query->value(1).toString();
}
sendData = sendData + "#" + list[1] + "#" + "1" + "#" + str1 + "#" + str2;
socket->write(sendData.toUtf8());
} else
return;
}
接受数据处理的调配,跳转到数据库处理
int Server::checkLogIn(QString Name, QString Password) {//检查登陆
MySql *sql = new MySql();
int ret = sql->Login(Name, Password);
return ret;
}
bool Server::checkSignUp(QString Name, QString Password, QString Mail) {//检查注册
MySql *sql = new MySql();
bool ret = sql->Regist(Name, Password, Mail);
return ret;
}
int Server::findpwd(QString Name, QString Mail) {//找回密码
MySql *sql = new MySql();
int temp = sql->findpwd(Name, Mail);
return temp;
}
开始的源头,登陆完成之后跳转到主界面,注意,这里有一个全局IP和全局端口(port),除了文件传输和私人聊天是要重新连接的,其他的都是通过这个去连接数据库的
#include "login.h"
#include "ui_login.h"
#include "register.h"
#include "findpsd.h"
#include "mainwindow.h"
#include
#include
Login::Login(QWidget *parent) :
QDialog(parent),
ui(new Ui::Login) {
ui->setupUi(this);
qDebug() << IP << endl;
QMovie *movie = new QMovie("F:/1.gif");
socket = new QTcpSocket(this);
connect(socket, SIGNAL(readyRead()), this, SLOT(readMsg()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(displayError(QAbstractSocket::SocketError))); //发生错误时执行displayError函数
}
QString Login::IP = "192.168.80.66";
//192.168.80.66
int Login::Port = 6666;
Login::~Login() {
delete this->socket;
delete ui;
}
void Login::readMsg() {//读取信息
QString data = socket->readAll();
QStringList list = data.split("#");
qDebug() << data;
if (list[0] == "b" && list[2] == "true") {
Mainwindow *w = new Mainwindow;
w->setWindowTitle(list[1]);
w->show();
} else if (list[0] == "b" && list[1] == "false" && list[2] == '0')
QMessageBox::information(this, "信息提示", "登录失败,密码错误!", QMessageBox::Ok);
else if (list[0] == "b" && list[1] == "false" && list[2] == '2')
QMessageBox::information(this, "信息提示", "用户已在线,拒绝重复登录!", QMessageBox::Ok);
else if (list[0] == "b" && list[1] == "false" && list[2] == '3')
QMessageBox::information(this, "信息提示", "用户不存在,请先注册!", QMessageBox::Ok);
else
return;
}
void Login::on_pushButton_Register_clicked() {
Register *m = new Register;
m->setWindowTitle("Regist");
m->show(); //当点击注册账户时,弹出注册窗口
}
void Login::on_pushButton_Forget_clicked() {
FindPsd *n = new FindPsd;
n->setWindowTitle("FindPsd");
n->show();//当点击忘记密码时,显示找回密码界面
}
void Login::on_pushButton_Login_clicked() {
socket->abort(); //取消已有的连接
socket->connectToHost(IP, Port); //连接服务器
qDebug() << IP << endl;
if (!socket->waitForConnected(30000)) {
qDebug() << "Connection failed!";
QMessageBox::information(this, tr("错误"), tr("服务器未开启,请先开启服务器!"));
ui->lineEdit_Name->clear(); //清空账号栏
ui->lineEdit_Password->clear(); //清空密码栏
ui->lineEdit_Name->setFocus(); //将鼠标重新定位到账号栏
return;
}
qDebug() << "Connect successfully!666666!";
QString userName = ui->lineEdit_Name->text();
QString passward = ui->lineEdit_Password->text();
QString bs = "b";
QString data = bs + "#" + userName + "#" + passward;
socket->write(data.toUtf8());
if (userName == NULL) { // 输入为空的提示
QMessageBox::information(this, tr("错误"), tr("账号不能为空!"));
ui->lineEdit_Name->setFocus(); //将鼠标重新定位到账号栏
} else if (passward == NULL) {
QMessageBox::information(this, tr("错误"), tr("密码不能为空!"));
ui->lineEdit_Name->setFocus();
}
ui->lineEdit_Name->clear(); //清空账号栏
ui->lineEdit_Password->clear(); //清空密码栏
ui->lineEdit_Name->setFocus(); //将鼠标重新定位到账号栏
}
这个可以理解为是主界面,很多处理都是在这里实现的,这里有发送也有接收,还可以打开P2P的聊天界面。具体的还得看代码
#include "mainwindow.h"
#include
#include "ui_mainwindow.h"
#include
#include "sendfile.h"
#include "p2p.h"
Mainwindow::Mainwindow(QWidget *parent) :
QDialog(parent),
ui(new Ui::Mainwindow) {
ui->setupUi(this);
socket = new QTcpSocket();
server = new QTcpServer();
CIP = getIP();
QTime current_time = QTime::currentTime();
int second = current_time.second(); //系统当前秒数
qsrand(second);
Cport = QString::number(qrand() % 1024 + 6000);
CPort = Cport.toInt();//通过即时的秒来确定Port
server->listen(QHostAddress::Any, CPort); //监听本机的某个端口
qDebug() << CPort;
connect(server, SIGNAL(newConnection()), this, SLOT(Connect())); //接受来自其他客户端的信号并连
connect(socket, SIGNAL(readyRead()), this, SLOT(Read_Data())); //接受来自服务器的数据
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(displayError(QAbstractSocket::SocketError))); //发生错误时执行displayError函数
}
int Mainwindow::CPort = CPort;
Mainwindow::~Mainwindow() {
delete ui;
delete this->socket;
}
void Mainwindow::Connect() { //连接客户端
socket = server->nextPendingConnection();
connect(socket, SIGNAL(readyRead()), this, SLOT(Read_Data())); //获取来自服务器的数据
}
QString Mainwindow::getIP() {
QString localHostName = QHostInfo::localHostName();//本机用户名
QString IP;
QHostInfo info = QHostInfo::fromName(localHostName);
foreach (QHostAddress address, info.addresses()) {
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
// if (address.toString().contains("192.168.")){
// continue;
// }
IP = address.toString();//本机ip地址
return IP;
}
}
return NULL;
}
void Mainwindow::closeEvent(QCloseEvent *event) {//在关闭的时候自动退出登陆
QString title = windowTitle();
socket->abort(); //取消已有的连接
socket->connectToHost(IP, port); //连接服务器
socket->waitForConnected();
QString ds = "d";
QString data = ds + "#" + title;
socket->write(data.toUtf8());
close();
}
void Mainwindow::Read_Data() {
qDebug() << "到达读取数据";
QString data = socket->readAll(); //读取服务器发送的数据
QStringList list = data.split("#");
QString title = windowTitle();
qDebug() << data;
if (list[0] == "e") { //加载用户列表
ui->listWidget->clear();
for (int i = 1; i < list.length(); i++) {
if (list[i] != "end") {
QString str = list[i];
QListWidgetItem *item = new QListWidgetItem;
item->setText(str);
ui->listWidget->addItem(item);
} else ui->textBrowser->append(list[++i]);
}
} else if (list[0] == "f") { //群发消息功能实现
qDebug() << "群聊 回到客户端";
if (list[1] != title) {
QDateTime time = QDateTime::currentDateTime();
QString Time = time.toString("yyyy-MM-dd ddd hh:mm:ss ");
ui->textBrowser->append(Time);
ui->textBrowser->append(list[1] + " : " + list[2]);
}
} else if (list[0] == "g") { //私聊
qDebug() << "私聊 客户端";
if (list[2] == "1") {
P2P *p2 = new P2P();
p2->setWindowTitle(Name);
p2->show();
socket->abort(); //取消已有的连接
YIP = list[3];
cport = list[4].toInt();
socket->connectToHost(YIP, cport); //连接到客户端B
socket->waitForConnected();//等待连接
p = 1;
QString ms = "z";
QString data = ms + "#" + title ;
socket->write(data.toUtf8());
} else if (list[2] == "0") {
p = 2;
QMessageBox::information(this, "信息提示", "该用户不在线,您在输入框中直接输入就可以向他发送离线消息!", QMessageBox::Ok);
}
} else if (list[0] == 'z') {//开启P2P
qDebug() << "到达开启P2P";
P2P *p3 = new P2P();
p3->setWindowTitle(list[1]);
p3->show();
} else return;
}
void Mainwindow::on_listWidget_itemDoubleClicked(QListWidgetItem *item) {//双击开启P2P
qDebug() << "双击666";
Name = item->text();
socket->abort();
//连接服务器
socket->connectToHost(IP, port);
socket->waitForConnected();
QString gs = "g";
QString data = gs + "#" + Name;
socket->write(data.toUtf8());
}
//void Mainwindow::Connect_for_userlist() {//得到用户列表,点击左上角,稍微偏右一些,多点几次就点到了
// qDebug() << this->windowTitle();
// QString title = windowTitle();
// socket->abort(); //取消已有的连接
// //连接服务器
// socket->connectToHost(IP, port);
// //等待连接成功
// if (!socket->waitForConnected(30000)) {
// qDebug() << "Connection failed!";
// return;
// } else {
// qDebug() << "Connect successfully!";
// }
// QString es = "e";
// QString data = es + "#" + title + "#" + CIP + "#" + Cport;
// socket->write(data.toUtf8());
//}
void Mainwindow::on_pushButton_Send_clicked() {
QString title = windowTitle();
QString fs;
QString msg = ui->textEdit->toPlainText();
if (p != 2) { //群聊
socket->abort(); //取消已有的连接
//连接服务器
socket->connectToHost(IP, port);
//等待连接成功
if (!socket->waitForConnected(30000)) {
qDebug() << "Connection failed!";
return;
} else
qDebug() << "Connect successfully! 连接服务器";
fs = "f"; //群聊
QString data = fs + "#" + title + "#" + msg;
socket->write(data.toUtf8());
} else { //离线消息
socket->abort(); //取消已有的连接
//连接服务器
socket->connectToHost(IP, port);
//等待连接成功
if (!socket->waitForConnected(30000)) {
qDebug() << "Connection failed!";
return;
} else
qDebug() << "Connect successfully!";
fs = "i"; //离线消息
QString data = fs + "#" + title + "#" + Name + "#" + msg;
socket->write(data.toUtf8());
}
QDateTime time = QDateTime::currentDateTime();
QString Time = time.toString("yyyy-MM-dd ddd hh:mm:ss ");
ui->textBrowser->append(Time);
ui->textBrowser->append(title + " : " + msg);
ui->textEdit->clear();
}
void Mainwindow::on_pushButton_Connect_clicked() {//得到用户列表,点击左上角,稍微偏右一些,多点几次就点到了
qDebug() << this->windowTitle();
QString title = windowTitle();
socket->abort(); //取消已有的连接
//连接服务器
socket->connectToHost(IP, port);
//等待连接成功
if (!socket->waitForConnected(30000)) {
qDebug() << "Connection failed!";
return;
} else {
qDebug() << "Connect successfully!";
}
QString es = "e";
QString data = es + "#" + title + "#" + CIP + "#" + Cport;
socket->write(data.toUtf8());
}
通过之前登陆成功后连接是存储在数据库的客户端IP和Port去连接另外一个客户端,实现P2P交流。port是聊天室界面的port + 1。还可以打开文件传输,原理和P2P私聊差不多,重新建立连接,不过用的是UDP。
#include "p2p.h"
#include "ui_p2p.h"
#include "sendfile.h"
P2P::P2P(QWidget *parent) :
QDialog(parent),
ui(new Ui::P2P) {
qDebug() << "打开P2P";
ui->setupUi(this);
map.load(":/icon/0C89F7B185A1EA66CE5B1148061C5622.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
socket = new QTcpSocket();
server = new QTcpServer();
server->listen(QHostAddress::Any, CPort);
qDebug() << CPort;
connect(server, SIGNAL(newConnection()), this, SLOT(Connect())); //接受来自其他客户端的信号并连
connect(socket, SIGNAL(readyRead()), this, SLOT(Read_Data())); //接受来自服务器的数据
}
P2P::~P2P() {
delete ui;
}
void P2P::Port(int number) {
this->CPort = number;
}
void P2P::Connect() { //连接客户端
qDebug() << "连接客户端";
socket = server->nextPendingConnection();
connect(socket, SIGNAL(readyRead()), this, SLOT(Read_Data())); //获取来自服务器的数据
}
void P2P::Read_Data() {
QString data = socket->readAll(); //读取服务器发送的数据
QStringList list = data.split("#");
QString title = windowTitle();
qDebug() << data << "到达P2P的读数据";
if (list[0] == "h") { //点对点消息功能实现
qDebug() << "发消息 P2P";
QDateTime time = QDateTime::currentDateTime();
QString Time = time.toString("yyyy-MM-dd ddd hh:mm:ss ");
ui->textBrowser_show->append(Time);
ui->textBrowser_show->append(list[1] + " : " + list[2]);
} else if (list[0] == "s") { //发送文件获取ip和端口
YIP = list[3];
cport = (list[4]).toInt();
socket->abort(); //取消已有的连接
socket->connectToHost(YIP, cport + 1); //连接到客户端B
socket->waitForConnected();
QString ms = "m";
QString data = ms + "#" + title;
socket->write(data.toUtf8());
} else if (list[0] == "y") { //获取ip和端口
YIP = list[3];
cport = (list[4]).toInt();
qDebug() << cport << " " << YIP;
socket->abort(); //取消已有的连接
socket->connectToHost(YIP, cport + 1); //连接到客户端B
socket->waitForConnected();
socket->write("66666666");
qDebug() << "success!'''''''''''''";
} else if (list[0] == "m") { //发文件
qDebug() << "发文件";
Sendfile *m1 = new Sendfile();
m1->show();
m1->setWindowTitle(title);
}
}
void P2P::on_pushButton_Send_clicked() {
QString title = windowTitle();
QString fs;
QString msg = ui->textEdit_write->toPlainText();
//点对点私聊
fs = "h"; //私聊
QString data = fs + "#" + title + "#" + msg;
socket->write(data.toUtf8());
qDebug() << data;
QDateTime time = QDateTime::currentDateTime();
QString Time = time.toString("yyyy-MM-dd ddd hh:mm:ss ");
ui->textBrowser_show->append(Time);
ui->textBrowser_show->append(title + " : " + msg);
ui->textEdit_write->clear();
}
void P2P::on_pushButton_Sendfile_clicked() {
QString title = windowTitle();
socket->abort();
socket->connectToHost(IP, port); //连接到服务器
socket->waitForConnected();
qDebug() << "1";
QString ss = "s#";
QString data = ss + title;
socket->write(data.toUtf8());
Sendfile *m1 = new Sendfile();
qDebug() << "2";
m1->show();
qDebug() << "3";
m1->setWindowTitle(title);
}
void P2P::on_pushButton_Connect_clicked() {
qDebug() << this->windowTitle();
socket->abort(); //取消已有的连接
//连接服务器
socket->connectToHost(IP, port);
//等待连接成功
if (!socket->waitForConnected(30000)) {
qDebug() << "Connection failed!";
return;
} else {
qDebug() << "Connect successfully! P2P!" << windowTitle();
QString name = windowTitle();
QString ss = "y#";
QString data = ss + name;
socket->write(data.toUtf8());
}
}
void P2P::on_comboBox_currentIndexChanged(int num) {//换图片
qDebug() << num;
if (num == 0) {
map.load(":/icon/0C89F7B185A1EA66CE5B1148061C5622.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
}
if (num == 1) {
map.load(":/icon/1C0A56ED7965651A3C7252C7C8BC4CCD.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
}
if (num == 2) {
map.load(":/icon/2B589D8C0959A43101DA9A3A21CB713A.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
}
if (num == 3) {
map.load(":/icon/3E9ABF37028B166DE4B5DCF1AAE1D14F.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
}
if (num == 4) {
map.load(":/icon/3FAD45AFADED34F9854AA7289533884F.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
}
if (num == 5) {
map.load(":/icon/468B317D6178792F1728B38937B1D143.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
}
if (num == 6) {
map.load(":/icon/48C4A5DDA8AAADB312C726576B13B22E.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
}
if (num == 7) {
map.load(":/icon/723E6423CC8B247CE0D903A5D4688A55.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
}
if (num == 8) {
map.load(":/icon/865CE62027A75117E225A3104DEBF9F1.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
}
if (num == 9) {
map.load(":/icon/AEEC264012EB9C71B036E637F0678EFA.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
}
if (num == 10) {
map.load(":/icon/D3034F351F85E131D25BCDAD3A36EA8C.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
}
if (num == 11) {
map.load(":/icon/D4B38D4B97344F4FAB55F710B43E5AF1.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
}
if (num == 12) {
map.load(":/icon/D9C25CA4F04B83068A9E07548C2468B7.jpg");
map = map.scaled(QSize(221, 381));
ui->label_pic->setPixmap(map);
}
}
文件传输的原理是在文件传输里面创建了两个端口,一个是服务端,一个是客户端。在我们打开文件传输的界面的时候,文件传输的客户端通过之前,就已经写在头文件里面的IP地址,去连接另一个服务器。我们把两个用户称为A和B。若a单打开的文件不为空,则进入传输文件。不断读取文件名的大小和传输文件的数据。服务端则对传输过来的信息进行判别,如果是文件,那么就。在本地创建一个文件的缓冲区。如果是内容的话,则在缓冲区不断添加接收的内容。与客户端不断进行交互,当信息传输完毕的时候就结束传输。
#include "sendfile.h"
#include "ui_sendfile.h"
#include "mainwindow.h"
#define TIMEOUT (500)
//int flag=0;
//QString YouIP="172.20.10.4";
Sendfile::Sendfile(QWidget *parent) :
QDialog(parent),
ui(new Ui::Sendfile) {
ui->setupUi(this);
//设置窗体最大化和最小化
Qt::WindowFlags windowFlag = Qt::Dialog;
windowFlag |= Qt::WindowMinimizeButtonHint;
windowFlag |= Qt::WindowMaximizeButtonHint;
windowFlag |= Qt::WindowCloseButtonHint;
setWindowFlags(windowFlag);
send_init();
receive_init();
}
Sendfile::~Sendfile() {
delete ui;
}
//文件传输--发送文件handletimeout()
void Sendfile::send_init() {
send_loadSize = 50 * 1024;
send_totalBytes = 0;
send_bytesWritten = 0;
send_bytesToWrite = 0;
QString ip = YouIP;
send_ip.setAddress(ip);
send_udpSocket = new QUdpSocket(this);
send_udpSocket->bind(4444, QUdpSocket::ShareAddress);
m_pTimer = new QTimer(this);
connect(m_pTimer, SIGNAL(timeout()), this, SLOT(handletimeout()));
connect(send_udpSocket, SIGNAL(readyRead()), this, SLOT(send_readmessage()));
ui->pushButton_Send->setEnabled(false);
}
void Sendfile::openFile() {
send_fileName = QFileDialog::getOpenFileName(this);
if (!send_fileName.isEmpty()) {
ui->pushButton_Send->setEnabled(true);
}
}
void Sendfile::startTransfer() {
send_localFile = new QFile(send_fileName);
if (!send_localFile->open(QFile::ReadOnly)) {
qDebug() << "open file error!";
return;
}
send_totalBytes = send_localFile->size();
qDebug() << send_totalBytes;
QDataStream sendOut(&send_outBlock, QIODevice::WriteOnly);
sendOut.setVersion(QDataStream::Qt_5_6);
QString currentFileName = send_fileName.right(send_fileName.size() - send_fileName.lastIndexOf('/') - 1);
sendOut << qint64(0) << qint64(0) << currentFileName;
send_totalBytes += send_outBlock.size();
sendOut.device()->seek(0);
sendOut << send_totalBytes << qint64((send_outBlock.size() - sizeof(qint64) * 2));
m_pTimer->start(TIMEOUT);
send_bytesToWrite = send_totalBytes - send_udpSocket->writeDatagram(send_outBlock, send_outBlock.size(), send_ip, 7777);
qDebug() << send_bytesToWrite;
send_bytesWritten = send_outBlock.size();
qDebug() << send_bytesWritten;
ui->progressBar_send->setMaximum(send_totalBytes);
ui->progressBar_send->setValue(send_bytesWritten);
send_outBlock.resize(0);
}
void Sendfile::send() {
if (!send_localFile->atEnd()) {
line = send_localFile->read(qMin(send_bytesToWrite, send_loadSize));
send_bytesToWrite -= send_udpSocket->writeDatagram(line, line.size(), send_ip, 7777);
send_bytesWritten = send_bytesWritten + line.size();
ui->progressBar_send->setMaximum(send_totalBytes);
ui->progressBar_send->setValue(send_bytesWritten);
qDebug() << send_bytesWritten;
} else {
send_udpSocket->writeDatagram("over", send_ip, 7777);
m_pTimer->stop();
ui->progressBar_send->close();
send_udpSocket->close();
send_localFile->close();
}
return;
}
void Sendfile::send_readmessage() {
while (send_udpSocket->hasPendingDatagrams()) {
QByteArray res = "false";
res.resize(send_udpSocket->pendingDatagramSize());
send_udpSocket->readDatagram(res.data(), res.size());
qDebug() << res;
if (res == "true") {
flag = 1;
}
}
}
void Sendfile::handletimeout() {
qDebug() << flag;
if (flag == 1) {
send();
flag = 0;
} else {
send_udpSocket->writeDatagram(line, line.size(), send_ip, 7777);
}
}
//文件传输--接收文件
void Sendfile::receive_init() {
receive_totalBytes = 0;
receive_bytesReceived = 0;
receive_fileNameSize = 0;
QString ip = YouIP;
receive_ip.setAddress(ip);
receive_udpSocket = new QUdpSocket();
receive_udpSocket->bind(7777, QUdpSocket::ShareAddress);
connect(receive_udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagram()));
}
void Sendfile::processPendingDatagram() {
while (receive_udpSocket->hasPendingDatagrams()) {
receive_udpSocket->writeDatagram("true", receive_ip, 4444);
receive_inBlock.resize(receive_udpSocket->pendingDatagramSize());
qDebug() << receive_inBlock.size();
receive_udpSocket->readDatagram(receive_inBlock.data(), receive_inBlock.size());
if (receive_inBlock == "over") {
qDebug() << receive_inBlock;
receive_udpSocket->close();
receive_localFile->close();
ui->progressBar_receive->close();
} else {
updateServerProgress();
}
}
}
void Sendfile::updateServerProgress() {
QDataStream in(&receive_inBlock, QIODevice::ReadOnly);
in.setVersion(QDataStream::Qt_5_6);
if (receive_bytesReceived <= sizeof(qint64) * 2) {
if (((unsigned int)receive_inBlock.size() >= sizeof(qint64) * 2)
&& (receive_fileNameSize == 0)) {
in >> receive_totalBytes >> receive_fileNameSize;
qDebug() << receive_totalBytes << receive_fileNameSize;
ui->progressBar_receive->setMaximum(receive_totalBytes);
ui->progressBar_receive->setValue(receive_bytesReceived);
qDebug() << receive_bytesReceived;
}
if (((unsigned int)receive_inBlock.size() >= receive_fileNameSize)
&& (receive_fileNameSize != 0)) {
in >> receive_fileName;
qDebug() << receive_fileName;
qDebug() << receive_bytesReceived;
receive_localFile = new QFile(receive_fileName);
if (!receive_localFile->open(QFile::WriteOnly)) {
qDebug() << "open file error!";
return;
}
} else return;
}
if (receive_bytesReceived < receive_totalBytes) {
receive_bytesReceived += receive_inBlock.size();
receive_localFile->write(receive_inBlock);
qDebug() << receive_localFile->size();
receive_inBlock.resize(0);
}
qDebug() << receive_bytesReceived;
ui->progressBar_receive->setMaximum(receive_totalBytes);
ui->progressBar_receive->setValue(receive_bytesReceived);
}
void Sendfile::on_pushButton_Open_clicked() {
openFile();
}
void Sendfile::on_pushButton_Send_clicked() {
startTransfer();
}
服务器和客户端都有相应的server和socket去接收和发送消息,我在登陆模块设置乐一个全局的IP地址和端口,就是为了方便客户端与服务器建立通信。然后发送到服务器的每一条信息都用相应的字母去标记他,以便服务器分类和处理数据,服务器在将数据处理完之后,带上之前的前缀和相关的信息,将数据发送回客户端。
客户端实例代码:
if (list[0] == "e") { //加载用户列表
ui->listWidget->clear();
for (int i = 1; i < list.length(); i++) {
if (list[i] != "end") {
QString str = list[i];
QListWidgetItem *item = new QListWidgetItem;
item->setText(str);
ui->listWidget->addItem(item);
} else ui->textBrowser->append(list[++i]);
}
} else if (list[0] == "f") { //群发消息功能实
服务器实例代码:
if (list[0] == "a") { //注册
qDebug() << "到达注册" << endl;
ret = checkSignUp(list[1], list[2], list[3]);
if (ret)
sendData = sendData + "#true";
else
sendData = sendData + "#false";
socket->write(sendData.toLatin1());
} else if (list[0] == "b") { //登录
这个项目也是参考了其他的,我感觉通信是比较难的,在项目开始的那段时间一直在测试TCP通信,这里就不班门弄斧了,下面的这位博主写的很好,我当时也是看他的才对TCP有了比较好的理解。不过在写完这个项目之后感觉TCP也就那样,所以还是要多实践啊。
QT - 创建TCP Socket通信
下面是一些其他还不错的博客,对理解项目和发散学习有帮助:
QT学习——QSqlQuery基本操作
QT - 创建TCP Socket通信
C/S 和 P2P
QT5实现简单的TCP通信
项目的下载在下面的链接,欢迎评论区交流。
基于TCP的即时通信软件