一、局域网聊天工具
有FeiQ大佬坐镇,也只是写着玩玩
软件运行截图:
文件:服务端运行时会在D盘产生一个数据库文件:D:\\user_info_server.db
二、源码:
sqlite部分源码:
cpp文件内容:
/*--------------------------------------------------------
* Author : Firdin
* E-mail : firdin@yeah.net
* File Name : server_sqlite.c
* Created Time: 2017年10月12日 星期四 15时27分11秒
* Introduction:
*
*-------------------------------------------------------*/
#include "server_sqlite.h"
#include<QDebug>
#include<QString>
bool server_sqlite::sqlite_init()
{
if(QSqlDatabase::contains("qt_sql_default_connection"))
my_db=QSqlDatabase::database("qt_sql_default_connection");
else
my_db=QSqlDatabase::addDatabase("QSQLITE");//创建sqlite数据库文件
if(!my_db.isValid())
{
qDebug()<<"数据库创建失败"<<endl;
return false;
}
my_db.setDatabaseName("D:\\user_info_server.db");//将数据库文件存放在C盘,且名字为user_info.db
if(!my_db.open())//判断数据库打开是否正常
{
qDebug()<<"数据库文件打开失败";
return false;
}
else
{
qDebug()<<"数据库文件已打开";
}
QSqlQuery search;//数据库语句执行
temp="create table user(id INT,name VARCHAR(15),IP VARCHAR(15),state VARCHAR(8))";//数据库表单:ID、用户名、IP地址、在线与否
//qDebug()<<"创建表单:"<<temp;
if(!search.exec(temp))//判断数据库语句执行是否正常
{
qDebug()<<"表单创建失败,原因:已存在数据库表单或文件读取错误,请检查!!";
}
sqlite_delete_all();
return true;
}
bool server_sqlite::sqlite_insert(int id_s,QString name_t,QString IP_t)//插入新的用户信息到数据库表单,格式:用户名、用户IP地址(字符串形式)
{
if(!sqlite_is_Exist(name_t,IP_t))//返回值为false,需要对其进行修改
{
name_t+="1";//修改用户名,避免转发消息出错(识别方面需要进一步debug)
}
temp.clear();
temp.sprintf("insert into user values(%d,'%s','%s','online')",id_s,name_t.toStdString().data(),IP_t.toStdString().data());
QSqlQuery search;//数据库语句执行
if(!search.exec(temp))
{
qDebug()<<"插入数值失败,请检查!!";
return false;
}
count++;
return true;
}
bool server_sqlite::sqlite_delete(QString name_m)//删除表单中某一个元素
{
temp.clear();
temp.sprintf("delete from user where name = '%s'",name_m.toStdString().data());
QSqlQuery search;//数据库语句执行
if(!search.exec(temp))
{
qDebug()<<"删除数值失败,请检查!!";
return false;
}
return true;
}
bool server_sqlite::sqlite_delete_all()//删除表单中所有元素
{
temp.clear();
temp="delete from user";
QSqlQuery search;//数据库语句执行
if(!search.exec(temp))
{
qDebug()<<"删除所有数值失败,请检查!!";
return false;
}
return true;
}
QString* server_sqlite::sqlite_search(QString name_s)//依据用户名查找对应的信息
{
QString *des=new QString;
temp.clear();
temp.sprintf("select id,name,IP,state from user where name = '%s' ",name_s.toStdString().data());
QSqlQuery search;//数据库语句执行
if(!search.exec(temp))
{
qDebug()<<"查找指定数值失败,请检查!!";
return NULL;
}
while(search.next())
{
*des+=search.value(1).toString()+" "+search.value(2).toString()+" "+search.value(3).toString()+"\n";
}
return des;
}
bool server_sqlite::sqlite_update(QString name_u,QString state_u)//修改用户在线信息
{
temp.clear();
temp.sprintf("update user set state = '%s' where name = '%s'",state_u.toStdString().data(),name_u.toStdString().data());
QSqlQuery search;//数据库语句执行
if(!search.exec(temp))
{
qDebug()<<"修改指定用户状态失败,请检查!!";
return false;
}
return true;
}
QString* server_sqlite::sqlite_online_server()//显示当前在线用户信息
{
QString *temp=new QString;
QSqlQuery search;//数据库语句执行
search.exec("select * from user");
while(search.next())
{
if( "offline" != search.value(3))
{
//qDebug()<<"用户名:"<<search.value(1).toString()<<"IP地址:"<<search.value(2).toString()<<endl;
*temp+=search.value(1).toString()+":"+search.value(2).toString()+"\n";
}
}
//qDebug()<<"原始信息拼接:"<<*temp;
return temp;
}
QString* server_sqlite::sqlite_offline_server()//显示当前不在线用户信息
{
QString *temp=new QString;
QSqlQuery search;//数据库语句执行
search.exec("select * from user");
while(search.next())
{
if("online" != search.value(3))
*temp+=search.value(1).toString()+" "+search.value(2).toString()+"\n";
}
// qDebug()<<"不在线用户信息:"<<*temp;
return temp;
}
bool server_sqlite::sqlite_delete_table()//删除表单(表单为临时配置文件,因此可以删除)
{
temp.clear();
temp.sprintf("drop table user");
QSqlQuery search;//数据库语句执行
if(!search.exec(temp))
{
qDebug()<<"删除表单失败,请检查!!";
return false;
}
return true;
}
int server_sqlite::sqlite_search_id(QString name_src)
{
temp.clear();
temp.sprintf("select id from user where name = '%s'",name_src.toStdString().data());
QSqlQuery search;
//qDebug()<<temp;
if(!search.exec(temp))
{
qDebug()<<"表单查询失败,请检查!!";
return -1;
}
if(search.first())
{
//qDebug()<<"所查ID为:"<<search.value(0).toInt();
return search.value(0).toInt();//返回当前用户的ID号
}
return -1;
}
bool server_sqlite::sqlite_is_Empty()//判断数据库是否为空
{
QString temp="";
QSqlQuery search;//数据库语句执行
search.exec("select * from user");
while(search.next())
{
if( "offline" != search.value(3))
{
//qDebug()<<"用户名:"<<search.value(1).toString()<<"IP地址:"<<search.value(2).toString()<<endl;
temp+=search.value(1).toString()+":"+search.value(2).toString()+"\n";
}
}
//qDebug()<<"原始信息拼接:"<<*temp;
if("" != temp)
{
return false;
}
else
{
return true;
}
}
bool server_sqlite::sqlite_is_Exist(QString name_se,QString IP_se)
{
int ID=sqlite_search_id(name_se);//查找名字对应的ID号,如果返回值不为-1则代表该用户存在
if(-1 == ID)//该用户名称不存在
{
return true;//直接将该用户信息插入,实现同一主机多个用户
}
else//用该用户名存在
{
//查找用户名对应的IP地址
temp.clear();
temp.sprintf("select IP from user where id = '%d'",ID);//SQL语句查找IP地址
QSqlQuery search;
if(!search.exec(temp))
{
qDebug()<<"表单查询IP失败,请检查!!";
return false;
}
if(search.first())
{
if(IP_se==search.value(0).toString())
{
qDebug()<<"用户名已存在,且IP地址相同";
sqlite_update(name_se,"online");//设置该用户在线
return true;
}
else
{
qDebug()<<"用户名存在,但是IP地址不同,将重新设置名称!!";
return false;//表示需要修改用户名后再进行插入
}
}
}
return false;
}
H文件内容如下:
#ifndef server_sqlite_H
#define server_sqlite_H
#include <QSqlDatabase>
#include <QSqlRecord>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
class server_sqlite //无继承的类(独立数据库操作类)
{
private:
QSqlDatabase my_db;//用户数据表单建立
int count;//用户在线人数
QString temp;//用于拼接字符用的临时变量
QString output;//用于输出用户信息
public:
explicit server_sqlite()
{
count=0;
temp.clear();
}
bool sqlite_init();//初始化数据库用成员函数
bool sqlite_insert(int id_s,QString name_t,QString IP_t);//插入数据
bool sqlite_delete(QString name_m);//删除一条数据
bool sqlite_delete_all();//删除所有的数据
QString* sqlite_search(QString name_s);//查找指定用户数据
bool sqlite_update(QString name_u,QString state_u);//修改指定用户的在线与否信息
QString* sqlite_online_server();//输出在线用户信息,通过判断state是否是online
QString* sqlite_offline_server();//输出历史用户(不在线但是有其信息)
bool sqlite_delete_table();//删除表单(表单为临时配置文件,因此可以删除)
int sqlite_search_id(QString name_src);//依据名字查询ID号,ID号在转发数据时需要用于查找QList中的socket对象,以达到准确转发消息
bool sqlite_is_Empty();//判断当前数据库是否为空
bool sqlite_is_Exist(QString name_se, QString IP_se);//判断当前用户是否已经存在,存在则仅修改其在线状态,否则将插入到数据库中,作为新加成员
~server_sqlite()
{
my_db.close();
}
};
#endif
图形界面代码实现:
cpp代码:
#include "widget.h"
#include "ui_widget.h"
#include"server_sqlite.h"//自定义sqlite服务
#include <QPainter>
#include <QPixmap>
#include<QTime>//时间
#include<QDate>//日期
#include<QDataStream>//数据流
#include<QByteArray>//字节数组
#include<QMap>//将字符串和整型匹配
server_sqlite server;//定义一个服务数据库对象(主函数中也用这个对象)
Widget::Widget(QWidget *parent) :QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//显示时间:
QString temp1=QTime::currentTime().toString();
QString temp2=QDate::currentDate().toString("yyyy年MM月dd日 ");
QString show=temp2+" "+temp1;
ui->local_Time->setText(show);
//定时器
this->startTimer(1000);//用于刷新时间的定时器,ID=1
this->startTimer(3000);//间隔3秒刷新用户在线信息,ID=2
//固定窗体大小
this->setFixedSize(523,454);//窗口大小固定
state=true;//标识服务状态,true表明服务已打开
countor=0;//数据库用户数量计数
ui->textEdit_showuseringo->setReadOnly(true);//设为只读
ui->textEdit_showuser_cominication->setReadOnly(true);//设为只读
connect(ui->pushButton,SIGNAL(clicked(bool)),this,SLOT(slot_net_server()));//打开、关闭按钮动作连接
}
Widget::~Widget()
{
server.sqlite_delete_all();
server.sqlite_delete_table();//退出时删除所有数据库文件
qDebug()<<"退出服务器程序!!";
delete ui;
}
//设置背景图案
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter (this);
painter.drawPixmap(0,0,this->width(), this->height(),QPixmap(":/blue.jpg"));
}
void Widget::slot_net_server()//按钮响应函数,用于打开网络或关闭网络
{
if(state)//按钮切换及功能实现
{
state=false;
ui->pushButton->setText("关闭服务");
get_IP_Address();//获取本机IP地址并显示在label控件中
Server_t=new QTcpServer(this);//创建服务器
Socket_t=new QTcpSocket(this);//创建socket
Socket_List=new QList<QTcpSocket*>;//创建socket文件描述符集合
Server_t->listen(QHostAddress::Any,8080);//接收来自任意网卡的信息
connect(Server_t,SIGNAL(newConnection()),this,SLOT(slot_new_connect()));//将新链接连接到槽函数响应
ui->label_show_message->setText("服务已打开!");
}
else
{
state=true;
ui->pushButton->setText("打开服务");
Server_t->close();
for(int i=0;i<Socket_List->length();i++)//关闭服务,关闭所有Socket
{
Socket_List->at(i)->close();
}
ui->label_show_message->setText("服务已关闭!!");
ui->local_IP_2->clear();
ui->textEdit_showuser_cominication->clear();
ui->textEdit_showuseringo->clear();
}
}
void Widget::get_IP_Address()//获取本机IP地址并解析IPV4地址(源自网络)
{
QString temp;
QHostInfo info = QHostInfo::fromName(QHostInfo::localHostName());//首先获取本机名称,其次依据本机名称获的本机IP地址
info.addresses();//QHostInfo的address函数获取本机ip地址
//存在多条ip地址ipv4和ipv6:
foreach(QHostAddress address,info.addresses())//该语句为从集合中每个成员中进行筛选:for each member进行遍历
{
if(address.protocol()==QAbstractSocket::IPv4Protocol)//只取ipv4协议的地址
{
ui->local_IP_2->setText("IP:"+address.toString()+" Port: 8080");
temp=address.toString();
}
}
qDebug()<<"IPv4地址:"<<temp;
}
void Widget::timerEvent(QTimerEvent *event)
{
//qDebug()<<"当前定时器ID:"<<event->timerId();
if(1 == event->timerId())//定时器ID为1时(1s溢出),刷新时间
{
QString temp1=QTime::currentTime().toString();
QString temp2=QDate::currentDate().toString("yyyy年MM月dd日 ");
QString show=temp2+" "+temp1;
ui->local_Time->setText(show);
display_userinfo();
}
else if(2 == event->timerId() && 0 != countor)//如果刷新用户列表的定时器溢出,则发送用户列表给所有的用户
{
ui->label_show_message->clear();
if(0 == Socket_List->length())
{
qDebug()<<"当前没有用户,不需要刷新用户列表";
}
else
{
QString user_info;
QString user_name;
QString user_IP;
user_info=*server.sqlite_online_server();//获取在线用户信息
if(""!=user_info)//有在线用户信息则进行分发
{
QStringList analysis=user_info.split("\n");//分解字符串
for(int i=0;i<countor;i++)//所有用户数量,包含不在线,以此为界限拼接在线用户信息并发送,刷新用户列表
{
if(""!=analysis.at(i))
{
user_info.clear();//清楚缓存
user_info=analysis.at(i);//取得单一用户的所有信息
QStringList analy_temp=user_info.split(":");//分解字符串
user_name+=analy_temp.at(0)+";";//将用户名都合并到user_name
user_IP+=analy_temp.at(1)+";";//将用户IP地址合并到user_IP
}
}
user_info.clear();//清除缓存
user_info="user:"+user_name+":"+user_IP;//拼接用户信息为格式:user:user1;user2;user3;:IP1;IP2;IP3;
for(int i=0;i<Socket_List->length();i++)//遍历发送数据(每个用户都要刷新在线列表)
{
QByteArray message;
QDataStream out(&message,QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_7);
out<<user_info;
Socket_List->at(i)->write(message);//从网络发送用户列表(所有在线用户都会接收到消息)
}
}
}
}
else
ui->label_show_message->setText("等待用户连接!");
}
void Widget::slot_new_connect()
{
Socket_t=Server_t->nextPendingConnection();//建立套接字
Socket_List->append(Socket_t);//加入到描述符集合
id_src=Socket_List->length();//取得当前描述符集合最大数值,作为数据库插入的ID (最大数值依据连接用户改变)
connect(Socket_t,SIGNAL(readyRead()),this,SLOT(slot_readMesssage()));//将所有的socket都连接到slot_readMessage(),而后再遍历取出数据
}
void Widget::slot_readMesssage()//该函数在任意一个描述符出现readyread信号后均能进入,因此需要遍历描述符集合
{
QString recv;
qDebug()<<"接收到信息,正在遍历服务器文件描述符集合查找信息";
for(int i=0;i<Socket_List->length();i++)//遍历Socket_List中所有的描述符,若其没有数据,则跳过,直到找到数据
{
QDataStream in(Socket_List->at(i));
in.setVersion(QDataStream::Qt_5_7);//定义版本,以免出错
in>>recv;
if(!(recv.isEmpty()))//若取得的数据不为空,说明是该描述符发出的readyread信号
{
String_Splitor(recv);//将接收到的字符串进行解析并进入下一步操作
}
}
}
void Widget::send_Message(QString user_src,QString message_src)//该成员函数仅用于发送消息
{
QByteArray message;//临时byte数组
QDataStream out(&message,QIODevice::WriteOnly);//数据流向
out.setVersion(QDataStream::Qt_5_7);//指定QT版本,以免网络传输出错
out<<message_src;//将要发送的消息导入流
int des=server.sqlite_search_id(user_src);//依据用户表单查找接收方注册ID号
Socket_List->at(des-1)->write(message);//发送信息,Socket_List列表中位置与其长度相差1,从0开始,des为数据库查询得到的ID号,其为Socket_List的length()返回值
}
void Widget::String_Splitor(QString src)
{
QStringList analysis=src.split(":");
qDebug()<<"字符解析结果:"<<analysis;
//分析客户端发送来的字符串第一个单词:message->发送消息,user->注册服务,file->发送文件,video->发送视频(switch不支持字符分支)
QMap<QString,int> map;//利用Map容器将字符串与整形数字对应,可以高效使用switch语句
//匹配字符与整型,等价于 if("user"==analysis.at(0))
//int index=0;
map.insert("user",0);
map.insert("message",1);//接收到消息<互相发送消息>
map.insert("file",2);//接收到除音乐、图片、视频外的文件
//由于多媒体文件可以预览,因此将其与其他文件分开,同时压缩文件也应该与其他的分开,以下功能以后再实现
map.insert("video",3);//接收到视频文件
map.insert("picture",4);//接收到图片文件
map.insert("music",5);//接收到音乐文件
map.insert("zip",6);//接收到压缩包文件
map.insert("dir",7);//接收到带有目录的文件
map.insert("exit",666);//退出客户端发送的下线消息
map.insert("",888);
switch(map[analysis.at(0)])//查找键值取出对应的整型数
{
case 0://user:username:192.168.1.168
{
qDebug()<<"进入分支user";
QString name_m=analysis.at(1);
QString IP_m=analysis.at(2);//取出新加入用户的名字和IP地址
QString show_in;//用于在UI上显示某人加入聊天队列的信息
show_in.sprintf("用户%s加入聊天队列,IP为:%s",name_m.toStdString().data(),IP_m.toStdString().data());
ui->textEdit_showuser_cominication->append(show_in);//将新连接的用户追加显示在左侧textEdit上
ui->label_show_message->setText("有新用户连接!");//提示有新用户连接进来
qDebug()<<"正在插入数据库";
server.sqlite_insert(id_src,name_m,IP_m);//新用户的信息插入到数据库文件中
qDebug()<<"插入数据库完成";
countor++;
qDebug()<<show_in;
break;
}
case 1://message:user1|user2:"hello there!!"
{
QString name_m=analysis.at(1);//取出双方姓名user1|user2:user1给user2发送消息
QStringList name_send_recv=name_m.split("|");//分离发送接收方信息
QString message_m=analysis.at(2);//取出所发送的信息
QString *state_line=server.sqlite_search(name_send_recv.at(1));
if("offline" == *state_line)
send_Message(name_send_recv.at(1),"message:"+name_send_recv.at(0)+"|"+name_send_recv.at(1)+":对方不在线,请稍后重试!");
else
send_Message(name_send_recv.at(1),"message:"+name_send_recv.at(0)+"|"+name_send_recv.at(1)+":"+message_m);//发送数据到指定的socketID接收方
//qDebug()<<"消息已发出,接收方名字:"<<name_m;
ui->textEdit_showuser_cominication->append(name_m+message_m);
break;
}
case 2://file:user1|user2:filename.size
break;
case 3://video:user1|user2:filename.size
break;
case 4://picture:user1|user2:filename.size
break;
case 5://music:user1|user2:filename.size
break;
case 6://zip:user1|user2:filename.size
break;
case 7://dir:user1|user2:filename.size
break;
case 666://exit:username:192.168.1.168
{
QString name_m=analysis.at(1);//取出退出用户名
server.sqlite_update(name_m,"offline");//更新在线状态
QString show_in;//用于在UI上显示某人加入聊天队列的信息
show_in.sprintf("用户%s下线",name_m.toStdString().data());//拼接字符串
ui->textEdit_showuser_cominication->append(show_in);//将下线的用户追加显示在左侧textEdit上
}
break;
case 888://内部错误
qDebug()<<"字符串解析出错!!";
break;
default:
qDebug()<<"指令解析出错,检查网络接收数据!!";
break;
}
}
void Widget::display_userinfo()
{
QString *user_online=server.sqlite_online_server();
QString *user_offline=server.sqlite_offline_server();
if(0!=countor&&state)
{
ui->textEdit_showuseringo->clear();
ui->textEdit_showuseringo->append("当前在线用户:\n");
ui->textEdit_showuseringo->append(*user_online);
ui->textEdit_showuseringo->append("离线用户:\n");
ui->textEdit_showuseringo->append(*user_offline);
}
}
H文件:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
//添加网络类
#include <QHostAddress>
#include <QHostInfo>
#include <QNetworkInterface>
#include <QProcess>
#include <QMainWindow>
#include<QTcpServer>
#include<QTcpSocket>
#include<QList>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
void timerEvent(QTimerEvent *event);//重写定时器虚函数,依据ID号区分功能
void get_IP_Address();//获取本机IP地址
void send_Message(QString user_src,QString message_src);//发送消息到客户端
void String_Splitor(QString src);//分解字符串实现不同的功能
void paintEvent(QPaintEvent *event);
void display_userinfo();
~Widget();
private slots:
void slot_new_connect();//新的连接
void slot_readMesssage();//接收消息
void slot_net_server();//网络服务函数
private:
Ui::Widget *ui;
QTcpSocket *Socket_t;//用于发送接收数据
QTcpServer *Server_t;//用于连接
QList<QTcpSocket*> *Socket_List;//用于将socket集合
bool state;//当前状态
int id_src;//数据库ID号索引(有bug)
int countor;//记录用户数量
};
#endif // WIDGET_H
main.c文件
#include "widget.h"
#include <QApplication>
#include "server_sqlite.h" //自定义数据库操作文件
extern server_sqlite server;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
if(!server.sqlite_init())//初始化一个数据对象
{
qDebug()<<"数据表单已存在,请检查!!"<<endl;
}
w.show();
return a.exec();
}
UI界面的xml代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>523</width>
<height>454</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<widget class="QLabel" name="local_Time">
<property name="geometry">
<rect>
<x>270</x>
<y>410</y>
<width>241</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<family>楷体</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QLabel" name="local_IP_2">
<property name="geometry">
<rect>
<x>270</x>
<y>60</y>
<width>241</width>
<height>31</height>
</rect>
</property>
<property name="font">
<font>
<family>楷体</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>410</x>
<y>10</y>
<width>101</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<family>楷体</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>打开服务</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>50</x>
<y>30</y>
<width>171</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<family>楷体</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>用户交互信息详情</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>320</x>
<y>120</y>
<width>171</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<family>楷体</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>用户连接情况</string>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>270</x>
<y>30</y>
<width>131</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<family>楷体</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>服务IP地址</string>
</property>
</widget>
<widget class="QLabel" name="label_show_message">
<property name="geometry">
<rect>
<x>10</x>
<y>420</y>
<width>251</width>
<height>21</height>
</rect>
</property>
<property name="font">
<font>
<family>楷体</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QTextEdit" name="textEdit_showuseringo">
<property name="geometry">
<rect>
<x>270</x>
<y>150</y>
<width>241</width>
<height>251</height>
</rect>
</property>
<property name="font">
<font>
<family>楷体</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:pad, x1:0.523, y1:0.00586364, x2:0.471, y2:1, stop:0 rgba(155, 250, 205, 75), stop:1 rgba(255, 255, 255, 255));</string>
</property>
</widget>
<widget class="QTextEdit" name="textEdit_showuser_cominication">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>241</width>
<height>341</height>
</rect>
</property>
<property name="font">
<font>
<family>楷体</family>
<pointsize>11</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:pad, x1:0.523, y1:0.00586364, x2:0.471, y2:1, stop:0 rgba(155, 250, 205, 75), stop:1 rgba(255, 255, 255, 255));</string>
</property>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
以上代码没有完成文件传输等功能,由于涉及到压缩算法和网络优化,暂时没有算法能力实现,故搁置了,后面算法能力提升后将对该部分进行补充升级。
不足之处多多指点,多谢。