效果如图: 点击此处查看源代码-系统注册
#ifndef COMMON_H
#define COMMON_H
#include
#include "connectnet.h"
/*
设置单例模式
*/
class Common{
public:
Common();
static ConnectNet* getSocketInstance();
private:
static ConnectNet* socket;
};
#endif // COMMON_H
#ifndef CONNECT_H
#define CONNECT_H
#include
#include
#include "constant.h"
#include "connectnet.h"
namespace Ui {
class Connect;
}
class Connect : public QWidget{
Q_OBJECT
public:
explicit Connect(QWidget *parent = 0);
~Connect();
private slots:
void on_connectButton_clicked();
private:
Ui::Connect *ui;
ServerNode serverNode;
ConnectNet *socket;
};
#endif // CONNECT_H
#ifndef CONNECTNET_H
#define CONNECTNET_H
#include
#include
#include
class ConnectNet : public QTcpSocket{
Q_OBJECT
public:
ConnectNet();
void setIpPort(QString Ip, int Port);
void sendMessage(QMap<QString,QString> message);
bool testConnect();
void connectToServer();
public slots:
void readMessage();
private:
QString ip;
int port;
quint16 bufSize;
};
#endif // CONNECTNET_H
#ifndef CONNECTNET_H
#define CONNECTNET_H
#include
#include
#include
class ConnectNet : public QTcpSocket{
Q_OBJECT
public:
ConnectNet();
void setIpPort(QString Ip, int Port);
void sendMessage(QMap<QString,QString> message);
bool testConnect();
void connectToServer();
public slots:
void readMessage();
private:
QString ip;
int port;
quint16 bufSize;
};
#endif // CONNECTNET_H
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
namespace Ui {
class MainWindow;
}
class MainWindow : public QWidget{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_viewInfButton_2_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#ifndef REGISTER_H
#define REGISTER_H
#include
#include
#include "connectnet.h"
#include "common.h"
namespace Ui {
class Register;
}
class Register : public QWidget{
Q_OBJECT
public:
explicit Register(QWidget *parent = 0);
~Register();
private slots:
void on_cancelButton_clicked();
void on_okButton_clicked();
private:
Ui::Register *ui;
ConnectNet *socket;
};
#endif // REGISTER_H
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
namespace Ui {
class Widget;
}
class Widget : public QWidget{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void on_registerButton_clicked();
void on_longinButton_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
#include "common.h"
ConnectNet* Common::socket = NULL;
Common::Common(){
}
//保证对象唯一性,具有创建对象和获取对象的逻辑
ConnectNet* Common::getSocketInstance(){
if(socket == NULL){
socket = new ConnectNet;
}
return socket;
}
#include "connect.h"
#include "widget.h"
#include "ui_connect.h"
#include "common.h"
Connect::Connect(QWidget *parent) :
QWidget(parent),
ui(new Ui::Connect){
ui->setupUi(this);
socket = Common::getSocketInstance();
}
Connect::~Connect(){
delete ui;
}
void Connect::on_connectButton_clicked(){
serverNode.ipAddress = ui->ip->text(); //获取用户输入ip地址
serverNode.port = ui->port->text().toInt(); //获取用户输入端口号
//获取IPAddress和Port
socket->setIpPort(serverNode.ipAddress,serverNode.port);
//成功连接跳转登录界面,否则跳出
if(socket->testConnect()){
Widget *w = new Widget();
w->show();
this->hide();
}else{
return;
}
//连接服务器
socket->connectToServer();
}
#include "connectnet.h"
ConnectNet::ConnectNet(){
connect(this,SIGNAL(readyRead()),this,SLOT(readMessage()));
}
//获取Ip_Address 和 port
void ConnectNet::setIpPort(QString Ip, int Port){
ip = Ip;
port = Port;
}
//发送数据
void ConnectNet::sendMessage(QMap<QString,QString> message){
//字节数组类,看做存储数据的缓冲区
QByteArray buf;
//设置只写模式,将前面缓冲区和通道写操作联系到一起
QDataStream out(&buf,QIODevice::WriteOnly);
//设置数据流的版本号
out.setVersion(QDataStream::Qt_4_6);
//组合数据的格式 最简单的格式:前几位字节(存放数据的大小值) + 真实数据
//前两个字节存放数据大小值
out << (quint16)0;//前两个字节存放的是0
//将消息按照固定格式组合:消息类型:消息内容 username:root
//关联容器位于服务器和客户端中的存储的容器,不是直接数据流
//对关联容器进行遍历,取出键和值,组合成标准字符串
//第二次组合键值对
foreach(QString key,message.keys()){
//遍历键列表
QString tempMsg = key + ":" + message[key];
out << tempMsg;//将每次便利的结果消息的格式放入数据流中
}
//跳转到起始的两个字节位置
out.device()->seek(0);
//计算应该放入的大小值
out << (quint16)(buf.size() - sizeof(quint16));
//大小值 + 真实数据
this->write(buf);
}
//测试连接
bool ConnectNet::testConnect(){
disconnectFromHost();//断开连接,关闭套接字对象,内存释放
connectToHost(ip,port);//为私有部分提供访问方式 1)get,set方法 2)友元
bool ret = waitForConnected(200);//等待连接完成
disconnectFromHost();//断开连接
return ret;
}
//连接服务器
void ConnectNet::connectToServer(){
this->abort();
this->connectToHost(ip,port);
}
//读取数据
void ConnectNet::readMessage(){
bufSize = 0;
QDataStream in(this);
in.setVersion(QDataStream::Qt_4_6);//设置版本号
//如果刚开始接收数据
if(bufSize == 0){
//判断接收数据是否符合两个字节大小
//如果有信息,将其保持在变量中,没有返回,继续接收数据
if(this->bytesAvailable() < sizeof(quint16)){
return;
}
in >> bufSize;//两个字节存放到变量中
}
int initBytes = this->bytesAvailable();
//对真实数据的判断
if(initBytes < bufSize){
//数据接收不完整
return;
}
//in >> Message;
//读取信息按照消息类型:消息内容 格式解析
QMap<QString,QString> message;
int msgSize = 0;
while(bufSize > msgSize){
QString tempMsg;
in >> tempMsg;
int idxSplitor = tempMsg.indexOf(":");//: 位置
message[tempMsg.mid(0,idxSplitor)] =
tempMsg.mid(idxSplitor + 1,tempMsg.length() - idxSplitor);
msgSize = initBytes - this->bytesAvailable();
}
qDebug() <<"Read Message Successful.";
}
#include "connect.h"
#include
int main(int argc, char *argv[]){
QApplication a(argc, argv);
Connect c;
c.setWindowTitle("connect to server");
c.show();
return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainWindow){
ui->setupUi(this);
}
MainWindow::~MainWindow(){
delete ui;
}
void MainWindow::on_viewInfButton_2_clicked(){
}
#include "register.h"
#include "ui_register.h"
Register::Register(QWidget *parent) :
QWidget(parent),
ui(new Ui::Register){
ui->setupUi(this);
socket = Common::getSocketInstance();
ui->userPwd->setEchoMode(QLineEdit::Password);
ui->reuserPwd->setEchoMode(QLineEdit::Password);
}
Register::~Register(){
delete ui;
}
void Register::on_cancelButton_clicked(){
close();
}
void Register::on_okButton_clicked(){
QString text = ui->userName->text();
QString text1 = ui->userNum->text();
QString text2 = ui->userPwd->text();
QString text3 = ui->reuserPwd->text();
QString text4 = ui->email->text();
QMap<QString,QString> msg;
msg["nickName"] = text;
msg["account"] = text1;
msg["password"] = text2;
msg["repassword"] = text3;
msg["email"] = text4;
socket->sendMessage(msg);
QMessageBox::information(NULL,"GodOuO","you have finished the register!",QMessageBox::Ok);
close();
}
#include "widget.h"
#include "ui_widget.h"
#include "register.h"
#include "constant.h"
#include "mainwindow.h"
#include
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget){
ui->setupUi(this);
}
Widget::~Widget(){
delete ui;
}
void Widget::on_registerButton_clicked() {
//打开注册窗口
Register *reg = new Register();
reg->setWindowTitle("Register");
reg->show();
}
void Widget::on_longinButton_clicked(){
//单击登录按钮,判断输入信息,进入主页面
if(ui->userName->text().isEmpty()) {
//用户名的输入不能位空
QMessageBox::critical(this,tr("Error-GodOuO"),
tr("The userName line can not be empty"));
return;
}
if(ui->passWord->text().isEmpty()){
//用户密码的输入不能为空
QMessageBox::critical(this,tr("Error-GodOuO"),
tr("The passWord line can not be empty"));
return;
}
MainWindow *window = new MainWindow();
window->setWindowTitle("home page");
window->show();
this->hide();
}
#ifndef CONSTANT_H
#define CONSTANT_H
#include
#include
#include
#include
struct UserInformation {
//用户信息结构体
QString account; //帐号
QString password; //密码
QString nickName; //呢称
int avatarNumber; //头像编号
int status; //登录状态
UserInformation(){
avatarNumber = status = 0; }
//重载输入输出操作符
friend QDataStream & operator<< (QDataStream &qos, const UserInformation &pi){
qos << pi.account << pi.password << pi.nickName << pi.avatarNumber << pi.status;
return qos;
}
friend QDataStream & operator>> (QDataStream &qis, UserInformation &pi){
qis >> pi.account >> pi.password >> pi.nickName >> pi.avatarNumber >> pi.status;
return qis;
}
};
//用户登录信息
struct LoginInformation{
QString account;
QString password;
int status;
LoginInformation(){
status = 0; }
friend QDataStream & operator<< (QDataStream &qos, const LoginInformation &li){
qos << li.account << li.password << li.status;
return qos;
}
friend QDataStream & operator>> (QDataStream &qis, LoginInformation &li){
qis >> li.account >> li.password >> li.status;
return qis;
}
};
//好友信息
struct FriendInformation{
QString account;
QString name;
int avatarNumber;
int status;
int friendKind;
QString remark;
FriendInformation() {
avatarNumber = status = friendKind = 0; }
friend QDataStream & operator<< (QDataStream &qos, const FriendInformation &fi){
qos << fi.account << fi.name << fi.avatarNumber << fi.status
<< fi.friendKind << fi.remark;
return qos;
}
friend QDataStream & operator>> (QDataStream &qis, FriendInformation &fi){
qis >> fi.account >> fi.name >> fi.avatarNumber >> fi.status
>> fi.friendKind >> fi.remark;
return qis;
}
};
#endif // CONSTANT_H
#ifndef DATABASE_H
#define DATABASE_H
#include "constant.h"
#include
class Database : public QObject{
public:
Database();
~Database();
void test(QString a , QString b , QString c , QString d);
//void initiDatabase(); //初始化数据库
private:
QSqlDatabase db;
};
#endif // DATABASE_H
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
#include
#include "database.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void on_closeButton_clicked();
void getsocket();
void readMessage();
void on_pushButton_clicked();
void sendMessage(QMap<QString,QString> msg);
private:
Ui::Widget *ui;
QTcpServer *server;
QTcpSocket *socket;
quint16 bufSize;
QMap<QString,QString> message;
Database db;
};
#endif // WIDGET_H
#include "database.h"
#include
#include
Database::Database(){
//创建数据库连接对象
db = QSqlDatabase::addDatabase("QSQLITE");
//数据库连接命名
db.setDatabaseName(":memory:");
if (!db.open()){
QMessageBox::warning(NULL, tr("Error"),
tr("Can not open the sqlite database"));
}
}
Database::~Database(){
}
void Database::test(QString a , QString b , QString c , QString d){
//数据库操作对象
QSqlQuery query;
//创建用户表
query.exec("create table user(account varchar(21) primary key,"
"password varchar(21),nickname varchar(21),email varchar(30))");
//向其中插入数据
query.exec("insert into user values('"+ a + "','" + b + "','" + c + "','" + d + "')");
//查询数据
query.exec("select * from user");
//查询结果存储在query对象中,该对象也是一个容器
//next函数,指向第一条,判断是否存在,存在返回ture 否则跳到下一条
while(query.next()){
QString account = query.value(0).toString();
QString password = query.value(1).toString();
QString nickname = query.value(2).toString();
QString email = query.value(3).toString();
qDebug() << "account :"<< account ;
qDebug() << "password :" << password ;
qDebug() << "nickname : " << nickname;
qDebug() << "email : " << email;
}
}
#include "widget.h"
#include
#include "database.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "widget.h"
#include "ui_widget.h"
#include
#include
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget){
ui->setupUi(this);
server = new QTcpServer(this);
if(!server->listen(QHostAddress::Any,8888)){
close();
}
connect(server,SIGNAL(newConnection()),this,SLOT(getsocket()));
}
Widget::~Widget(){
delete ui;
}
//关闭服务器提示!!
void Widget::on_closeButton_clicked(){
//信息提示框
int result = QMessageBox::information(NULL, "GodOuO", "Do you want close the system ?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
//选择yes关闭服务器
if(result == QMessageBox::Yes){
QApplication *app;
app->exit(0);
}
}
//获取socket对象
void Widget::getsocket(){
socket = server->nextPendingConnection();
connect(socket,SIGNAL(readyRead()),this,SLOT(readMessage()));
qDebug("get the socket succeedful");
}
//读取数据
void Widget::readMessage(){
bufSize = 0;
QDataStream in(socket);
in.setVersion(QDataStream::Qt_4_6);//设置版本号
//如果刚开始接收数据
if(bufSize == 0){
//判断接收数据是否符合两个字节大小
//如果有信息,将其保持在变量中,没有返回,继续接收数据
if(socket->bytesAvailable() < sizeof(quint16)){
return ;
}
in >> bufSize;//两个字节存放到变量中
}
int initBytes = socket->bytesAvailable();
//对真实数据的判断
if(initBytes < bufSize){
//数据接收不完整
return ;
}
//读取信息按照消息类型:消息内容 格式解析
//QMap message;
int msgSize = 0;
while(bufSize > msgSize){
QString tempMsg;
in >> tempMsg;
int idxSplitor = tempMsg.indexOf(":");//: 位置
message[tempMsg.mid(0,idxSplitor)] =
tempMsg.mid(idxSplitor + 1,tempMsg.length() - idxSplitor);
msgSize = initBytes - socket->bytesAvailable();
}
ui->test->setText(message.keys().at(0) + ":" + message.values().at(0) + "\n" +
message.keys().at(1) + ":" + message.values().at(1) + "\n" +
message.keys().at(2) + ":" + message.values().at(2) + "\n" +
message.keys().at(3) + ":" + message.values().at(3) + "\n" +
message.keys().at(4) + ":" + message.values().at(4) + "\n");
db.test(message.values().at(1),message.values().at(2),message.values().at(0),message.values().at(4));
}
//点击发送数据
void Widget::on_pushButton_clicked(){
QString text = ui->lineEdit->text();
//第一次组合键值对 LOGIN(userName : root passWord : 123456)
QMap<QString,QString> msg;
msg["LOGIN"] = text;
sendMessage(msg);
}
//发送信息函数
void Widget::sendMessage(QMap<QString,QString> msg){
//发送数据
QByteArray buf;//字节数组类,看做存储数据的缓冲区
//设置只写模式,将前面缓冲区和通道写操作联系到一起
QDataStream out(&buf,QIODevice::WriteOnly);
//设置数据流的版本号
out.setVersion(QDataStream::Qt_4_6);
//组合数据的格式 最简单的格式:前几位字节(存放数据的大小值) + 真实数据
//前两个字节存放数据大小值
out << (quint16)0;//前两个字节存放的是0
out << tr("");//后续存放的是数据
0 + 123456
//将消息按照固定格式组合:消息类型:消息内容 username:root
//关联容器位于服务器和客户端中的存储的容器,不是直接数据流
//对关联容器进行遍历,取出键和值,组合成标准字符串
//第二次组合键值对
foreach(QString key,msg.keys()){
//遍历键列表
QString tempMsg = key + ":" + msg[key];
out << tempMsg;//将每次便利的结果消息的格式放入数据流中
}
//跳转到起始的两个字节位置
out.device()->seek(0);
//计算应该放入的大小值
out << (quint16)(buf.size() - sizeof(quint16));
//大小值 + 123456
//socket = server->nextPendingConnection();
socket->write(buf);
}