功能:
1.用户注册登录功能
2.群聊功能
3.私聊功能
客户端代码:
//tcpclient.h
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include <QMainWindow>
#include <QtNetwork>
#include <QMessageBox>
//#include "userinterface.h"
namespace Ui {
class TcpClient;
}
class TcpClient : public QMainWindow
{
Q_OBJECT
public:
explicit TcpClient(QWidget *parent = 0);
~TcpClient();
protected:
void init();
void connectServer();
private slots:
void on_sendBtn_clicked();
void displayError(QAbstractSocket::SocketError);
void on_signBtn_clicked();
void readMessages();
private:
Ui::TcpClient *ui;
QTcpSocket *tcpSocket;
int readFlag;
//UserInterface *user;
};
#endif // TCPCLIENT_H
//tcpclient.cpp
#include "tcpclient.h"
#include "ui_tcpclient.h"
#include "userinterface.h"
#define ip "192.168.1.165"
//#define ip "127.0.0.1"
#define port 8000
TcpClient::TcpClient(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::TcpClient)
{
readFlag=1;
ui->setupUi(this);
ui->passwardLineEdit->setEchoMode(QLineEdit::Password); //密码方式显示文本
init();
connectServer();
}
TcpClient::~TcpClient()
{
delete ui;
}
void TcpClient::init()
{
tcpSocket=new QTcpSocket(this);
connect(tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),
this,SLOT(displayError(QAbstractSocket::SocketError))); //发生错误时执行displayError函数
}
void TcpClient::connectServer()
{
tcpSocket->abort(); //取消已有的连接
tcpSocket->connectToHost(ip,port);
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readMessages()));
}
void TcpClient::on_sendBtn_clicked()
{
QString userName=ui->userLineEdit->text();
QString passward=ui->passwardLineEdit->text();
if(userName=="" || passward=="")
QMessageBox::information(this,"警告","输入不能为空",QMessageBox::Ok);
QString bs="b";
QString data=bs+"#"+userName+"#"+passward;
tcpSocket->write(data.toLatin1());
}
void TcpClient::on_signBtn_clicked()
{
QString userName=ui->userLineEdit->text();
QString passward=ui->passwardLineEdit->text();
if(userName=="" || passward=="")
QMessageBox::information(this,"警告","输入不能为空",QMessageBox::Ok);
QString as="a";
QString data=as+"#"+userName+"#"+passward;
tcpSocket->write(data.toLatin1());
}
void TcpClient::displayError(QAbstractSocket::SocketError)
{
qDebug()<<tcpSocket->errorString(); //输出出错信息
}
void TcpClient::readMessages()
{
if(readFlag==0)
return;
QString data=tcpSocket->readAll();
QStringList list=data.split("#");
if(list[0]=="a" && list[2]=="true")
QMessageBox::information(this,"信息提示","注册成功!",QMessageBox::Ok);
else if(list[0]=="a" && list[2]=="false")
QMessageBox::information(this,"信息提示","注册失败,用户名已经被注册!",QMessageBox::Ok);
else if(list[0]=="b" && list[2]=="true")
//QMessageBox::information(this,"信息提示","登录成功!",QMessageBox::Ok);
{
UserInterface *user=new UserInterface(this,tcpSocket,list[1]);
this->close();
user->show();
readFlag=0;
}
else if(list[0]=="b" && list[2]=="false")
QMessageBox::information(this,"信息提示","登录失败,用户名或密码错误!",QMessageBox::Ok);
else
return;
}
//userinterface.h
#ifndef USERINTERFACE_H
#define USERINTERFACE_H
#include <QMainWindow>
#include <QTcpSocket>
#include "personaldialog.h"
#include <QMap>
namespace Ui {
class UserInterface;
}
class UserInterface : public QMainWindow
{
Q_OBJECT
public:
explicit UserInterface(QWidget *parent = 0,QTcpSocket *pTcpSocket=0,QString _name="");
~UserInterface();
private slots:
void readMessages();
void on_pushButton_clicked();
void on_refreshBtn_clicked();
void on_listWidget_doubleClicked(const QModelIndex &index);
private:
Ui::UserInterface *ui;
QTcpSocket *tcpSocket;
QString name;
QStringList onlineUser;
//PersonalDialog *PD;
QMap<QString,PersonalDialog*> pdList;
};
#endif // USERINTERFACE_H
//userinterface.cpp
#include "userinterface.h"
#include "ui_userinterface.h"
UserInterface::UserInterface(QWidget *parent,QTcpSocket *pTcpSocket,QString _name) :
QMainWindow(parent),tcpSocket(pTcpSocket),name(_name),
ui(new Ui::UserInterface)
{
ui->setupUi(this);
this->setWindowTitle("Chat Room");
ui->textEdit->setReadOnly(true);
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readMessages()));
}
UserInterface::~UserInterface()
{
delete ui;
}
void UserInterface::readMessages()
{
QByteArray temp=tcpSocket->readAll();
QString data=QString::fromLocal8Bit(temp);
//QString data=tcpSocket->readAll();
QStringList list=data.split("#");
if(list[0]=="c")
{
QString str1=list[1]+":";
ui->textEdit->append("<font color=red>"+str1+"</font>");
ui->textEdit->append(list[2]);
}
else if(list[0]=="d")
{
ui->listWidget->clear();
onlineUser.clear();
for(int i=1;i<list.size();i++)
{
if(list[i]==name)
continue;
ui->listWidget->addItem(list[i]);
onlineUser.append(list[i]);
}
}
else if(list[0]=="e")
{
//判断发送消息用户名是否在pdList里面,如果不在,新建一个PersonalDialog对象
if(!pdList.contains(list[1]))
{
qDebug()<<list[1]<<name;
PersonalDialog *temp=new PersonalDialog(this,tcpSocket,list[1],name);
pdList.insert(list[1],temp);
temp->show();
}
pdList[list[1]]->getMessage(list[1],list[3]);
}
else
return;
}
void UserInterface::on_pushButton_clicked()
{
QString str=ui->lineEdit->text();
ui->textEdit->append("<font color=blue> 自己: </font>");
ui->textEdit->append(str);
QString message="c#"+name+"#"+str;
QByteArray data=message.toLocal8Bit();/*******/
tcpSocket->write(data);
//tcpSocket->write(message.toLatin1());
ui->lineEdit->clear();
}
void UserInterface::on_refreshBtn_clicked()
{
QString message="e#getUserList";
tcpSocket->write(message.toLatin1());
}
void UserInterface::on_listWidget_doubleClicked(const QModelIndex &index)
{
QString str=onlineUser.at(index.row()); //获得用户名
//QString message="f#"+str;
//tcpSocket->write(message.toLatin1());
PersonalDialog *temp=new PersonalDialog(this,tcpSocket,str,name);
pdList.insert(str,temp);
pdList[str]->show();
pdList[str]->setNameText(str);
}
//personaldialog.h
#ifndef PERSONALDIALOG_H
#define PERSONALDIALOG_H
#include <QDialog>
#include <QTcpSocket>
#include <QUdpSocket>
#include <QNetworkInterface>
namespace Ui {
class PersonalDialog;
}
class PersonalDialog : public QDialog
{
Q_OBJECT
public:
explicit PersonalDialog(QWidget *parent = 0,QTcpSocket *_tcp=0,QString _oppositeName=0,QString _selfName=0);
~PersonalDialog();
QString oppositeName;
void setNameText(QString name);
void getMessage(QString name,QString message);
private slots:
void on_pushButton_send_clicked();
void on_pushButton_sendFile_clicked();
private:
Ui::PersonalDialog *ui;
QTcpSocket *tcp;
QUdpSocket *udp;
QString selfName;
};
#endif // PERSONALDIALOG_H
//personaldialog.cpp
#include "personaldialog.h"
#include "ui_personaldialog.h"
PersonalDialog::PersonalDialog(QWidget *parent,QTcpSocket *_tcp,QString _oppositeName,QString _selfName) :
QDialog(parent),tcp(_tcp),oppositeName(_oppositeName),selfName(_selfName),
ui(new Ui::PersonalDialog)
{
ui->setupUi(this);
this->setWindowTitle(tr("私人聊天..."));
ui->textEdit->setReadOnly(true);
}
PersonalDialog::~PersonalDialog()
{
delete ui;
}
void PersonalDialog::on_pushButton_send_clicked()
{
QString data1=ui->lineEdit->text();
ui->lineEdit->clear();
ui->textEdit->append(selfName);
ui->textEdit->append(data1);
QString data2="d#"+selfName+"#"+oppositeName+"#"+data1;
tcp->write(data2.toLatin1());
}
void PersonalDialog::on_pushButton_sendFile_clicked()
{
}
void PersonalDialog::getMessage(QString name, QString message)
{
setNameText(name);
ui->textEdit->append(name);
ui->textEdit->append(message);
}
void PersonalDialog::setNameText(QString name)
{
ui->lineEdit_name->setText(name);
}
服务端代码:
//mysql.h
#ifndef MYSQL_H
#define MYSQL_H
#include <QSql>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QDebug>
class MySql
{
public:
MySql();
void initsql();
void createtable();
bool loguser(QString name,QString passward);
bool signup(QString name,QString passward);
private:
QSqlQuery *query;
};
#endif // MYSQL_H
//mysql.cpp
#include "mysql.h"
MySql::MySql()
{
}
void MySql::initsql()
{
QSqlDatabase db=QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("127.0.0.1");
db.setUserName("root");
db.setPassword("******");
db.setDatabaseName("User");
if(db.open())
{
qDebug()<<"Database connected successfully!";
createtable();
return;
}
else
{
qDebug()<<"Database connected failed!";
return;
}
}
void MySql::createtable()
{
query=new QSqlQuery;
query->exec("create table user(name VARCHAR(30) PRIMARY KEY UNIQUE NOT NULL,passward VARCHAR(30))");
/*创建root用户*/
query->exec("insert into user value('root', 'root')");
}
bool MySql::loguser(QString name, QString passward)
{
QString str=QString("select * from user where name='%1' and passward='%2'").arg(name).arg(passward);
query=new QSqlQuery;
query->exec(str);
query->last();
int record=query->at()+1;
if(record==0)
return false;
return true;
}
bool MySql::signup(QString name,QString passward)
{
QString str=QString("select * from user where name='%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')").arg(name).arg(passward);
bool ret=query->exec(str);
return ret;
}
//tcpserver.h
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <QMainWindow>
#include <QtNetwork>
#include <QTimer>
#include <QMap>
namespace Ui {
class TcpServer;
}
class TcpServer : public QMainWindow
{
Q_OBJECT
public:
explicit TcpServer(QWidget *parent = 0);
~TcpServer();
bool checkSignIn(QString name,QString passward);
bool checkSignUp(QString name,QString passward);
signals:
void userNumChange();
private slots:
void on_startBtn_clicked();
void acceptConnection();
void receiveData();
void removeUserFormList();
void sendUserList();
private:
Ui::TcpServer *ui;
//QTcpSocket *tcpSocket;
QTcpServer *tcpServer;
QTimer *timer;
//QList<QTcpSocket *> userList;
QMap<QTcpSocket *,QString> userMessage;
};
#endif // TCPSERVER_H
//tcpserver.cpp
#include "tcpserver.h"
#include "ui_tcpserver.h"
#include "mysql.h"
TcpServer::TcpServer(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::TcpServer)
{
ui->setupUi(this);
this->tcpServer=new QTcpServer(this);
connect(tcpServer,SIGNAL(newConnection()),this,SLOT(acceptConnection()));
connect(this,SIGNAL(userNumChange()),this,SLOT(sendUserList()));
}
TcpServer::~TcpServer()
{
delete ui;
}
void TcpServer::receiveData()
{
QTcpSocket *tempTcp=static_cast<QTcpSocket*>(sender());
QString data=tempTcp->readAll();
qDebug()<<data;
QStringList list=data.split("#");
bool ret=0;
if(list[0]=="a") //注册
ret=checkSignUp(list[1],list[2]);
else if(list[0]=="b") //登录
{
ret=checkSignIn(list[1],list[2]);
if (ret)
{
userMessage.insert(tempTcp,list[1]);
connect(tempTcp,SIGNAL(disconnected()),this,SLOT(removeUserFormList()));
}
}
else if(list[0]=="c")
{
QMap<QTcpSocket*,QString>::iterator it=userMessage.begin();
QString message="c#"+list[1]+"#"+list[2];
while(it!=userMessage.end())
{
QTcpSocket *tcp=it.key();
if(tcp!=tempTcp)
tcp->write(message.toLatin1());
++it;
}
return;
}
else if(list[0]=="d")
{
//userMessage[list[2]]->write(list[1]+"#"+list[3]);
QMap<QTcpSocket*,QString>::iterator it=userMessage.begin();
QTcpSocket *tcp=NULL;
while(it!=userMessage.end())
{
if(it.value()==list[2])
{
tcp=it.key();
break;
}
++it;
}
if(tcp==NULL)
return;
QString mes="e#"+list[1]+"#"+list[2]+"#"+list[3];
tcp->write(mes.toLatin1());
return;
}
else if(list[0]=="e")
{
emit sendUserList();
return;
}
else
return;
QString sendData=list[0];
if(ret)
sendData+="#"+list[1]+"#true";
else
sendData+="#"+list[1]+"#false";
tempTcp->write(sendData.toLatin1());
}
void TcpServer::on_startBtn_clicked()
{
ui->startBtn->setEnabled(false);
if(!tcpServer->listen(QHostAddress::Any,8000))
{
qDebug()<<tcpServer->errorString();
close();
return;
}
}
void TcpServer::acceptConnection()
{
QTcpSocket *tcp=tcpServer->nextPendingConnection();
//QString ip=tcp->peerAddress().toString();
//qDebug()<<ip;
connect(tcp,SIGNAL(readyRead()),this,SLOT(receiveData())); //**********
}
/*
void TcpServer::displayError(QAbstractSocket::SocketError)
{
qDebug()<<tcpSocket->errorString();
tcpSocket->close();
}*/
bool TcpServer::checkSignIn(QString name,QString passward)
{
MySql *mysql=new MySql();
bool ret=mysql->loguser(name,passward);
if(ret)
{
ui->listWidget->addItem(name);
}
return ret;
}
bool TcpServer::checkSignUp(QString name, QString passward)
{
MySql *mysql=new MySql();
bool ret=mysql->signup(name,passward);
return ret;
}
void TcpServer::removeUserFormList()
{
QTcpSocket* socket = static_cast<QTcpSocket*>(sender());
QString name=userMessage[socket];
QList<QListWidgetItem*> list;
list=ui->listWidget->findItems(name,Qt::MatchCaseSensitive);
QListWidgetItem *sel=list[0];
int r=ui->listWidget->row(sel);
QListWidgetItem *item=ui->listWidget->takeItem(r);
ui->listWidget->removeItemWidget(item);
delete item;
userMessage.remove(socket);
emit userNumChange();
}
void TcpServer::sendUserList()
{
QString message="d";
QMap<QTcpSocket*,QString>::iterator it=userMessage.begin();
while(it!=userMessage.end())
{
message+="#";
message+=it.value();
++it;
}
if(message=="d")
return;
it=userMessage.begin();
while(it!=userMessage.end())
{
it.key()->write(message.toLatin1());
++it;
}
//qDebug()<<message;
}
运行截图:
消息格式:
客户端->服务器端:
注册:a#注册名#注册密码
登录:b#登录名#登录密码
群消息:c#发送者#消息
私人消息:d#发送者#接受者用户名#消息
获得在线用户名单:e#getUserList
服务器端->客户端
注册成功:a#注册名#true
注册失败:a#注册名#false
登录成功:b#登录名#true
登录失败:b#登录名#false
群消息/私人消息:c#发送者#消息
发送在线名单:d#用户名1#用户名2#...
转发私人消息:e#发送者#接收者#消息