今天带来一个简单的聊天项目,项目不难,客户端和服务器端一共只有400多行代码,这个程序的缺点是无法实现广播与组播,只能连接一个客户端。
先来看程序的运行效果:
1服务器端的设计:
项目框架:
因为这个有网络部分,所以在.pro文件里添加QT+=network
dialog.h:
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostInfo>
#include <QDebug>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
private:
// QLabel *LabListen;
// QLabel *LabSocketState;
QTcpServer *tcpServer;
QTcpSocket *tcpSocket;
QString getLocalIP();
protected:
void closeEvent(QCloseEvent *);
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void onNewConnection();
void onSocketStatueChange(QAbstractSocket::SocketState socketState);
void onCilentConnected();
void onClientDisConnected();
void onSocketReadyRead();
void on_btn_start_listen_clicked();
void on_btn_stop_listen_clicked();
void on_btn_clear_clicked();
void on_btn_exit_clicked();
void on_btn_send_clicked();
private:
Ui::Dialog *ui;
};
#endif // DIALOG_H
dialog.cpp:
#include "dialog.h"
#include "ui_dialog.h"
#pragma execution_character_set("utf-8")
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
ui->label_listenstate->setText("监听状态");
ui->label_socketstate->setText("Socket状态");
QString localIP=getLocalIP();
this->setWindowTitle(this->windowTitle()+"---本机IP:"+localIP);
ui->comboBox->addItem(localIP);
tcpServer=new QTcpServer(this);
connect(tcpServer,SIGNAL(newConnection()),this,SLOT(onNewConnection()));
}
//获取本机IPv4地址
QString Dialog::getLocalIP()
{
QString hostName=QHostInfo::localHostName();
QHostInfo hostInfo=QHostInfo::fromName(hostName);
QString localIP="";
QList<QHostAddress> addlist=hostInfo.addresses();
if(!addlist.isEmpty()){
for(int i=0;i<addlist.count();i++){
QHostAddress aHost=addlist.at(i);
if(QAbstractSocket::IPv4Protocol==aHost.protocol()){
localIP=aHost.toString();
}
}
}
return localIP;
}
void Dialog::closeEvent(QCloseEvent *)
{
qDebug()<<"ok";
}
//开始监听
void Dialog::on_btn_start_listen_clicked()
{
//IP地址
QString IP=ui->comboBox->currentText();
quint16 port=ui->spinBox->value();
QHostAddress addr(IP);
tcpServer->listen(addr,port);
ui->plainTextEdit->appendPlainText("---开始监听----");
ui->plainTextEdit->appendPlainText("---服务器地址:"+tcpServer->serverAddress().toString());
ui->plainTextEdit->appendPlainText("---服务器端口"+QString::number(tcpServer->serverPort()));
ui->btn_start_listen->setEnabled(false);
ui->btn_stop_listen->setEnabled(true);
ui->label_listenstate->setText("监听状态: 正在监听");
}
void Dialog::onNewConnection()
{
//获取socket
tcpSocket=tcpServer->nextPendingConnection();
connect(tcpSocket,SIGNAL(connected()),this,SLOT(onClientConnected()));
onCilentConnected();
connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(onClientDisConnected()));
connect(tcpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(onSocketStatueChange(QAbstractSocket::SocketState)));
onSocketStatueChange(tcpSocket->state());
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead()));
}
//socket状态变化
void Dialog::onSocketStatueChange(QAbstractSocket::SocketState socketState)
{
switch (socketState) {
case QAbstractSocket::UnconnectedState:
ui->label_socketstate->setText("socket状态: UnconnectedState");
break;
case QAbstractSocket::HostLookupState:
ui->label_socketstate->setText("socket状态: HostLookupState");
case QAbstractSocket::ConnectingState:
ui->label_socketstate->setText("socket状态: ConnectingState");
case QAbstractSocket::ConnectedState:
ui->label_socketstate->setText("socket状态: ConnectedState");
case QAbstractSocket::BoundState:
ui->label_socketstate->setText("socket状态: BoundState");
case QAbstractSocket::ClosingState:
ui->label_socketstate->setText("socket状态: ClosingState");
case QAbstractSocket::ListeningState:
ui->label_socketstate->setText("socket状态: ListeningState");
}
}
//客户端接入时
void Dialog::onCilentConnected()
{
ui->plainTextEdit->appendPlainText("--client socket connected");
ui->plainTextEdit->appendPlainText("--peer address:"+tcpSocket->peerAddress().toString());
ui->plainTextEdit->appendPlainText("--peer port:"+QString::number(tcpSocket->peerPort()));;
}
//客户端断开连接时
void Dialog::onClientDisConnected()
{
ui->plainTextEdit->appendPlainText("--client socket connected");
tcpSocket->deleteLater();
}
void Dialog::on_btn_stop_listen_clicked()
{
if(tcpServer->isListening()){
tcpServer->close();
ui->btn_start_listen->setEnabled(true);
ui->btn_stop_listen->setEnabled(false);
ui->label_listenstate->setText("监听状态:已停止监听");
}
}
void Dialog::on_btn_send_clicked()
{
QString msg=ui->lineEdit->text();
ui->plainTextEdit->appendPlainText("[out]"+msg);
ui->lineEdit->clear();
ui->lineEdit->setFocus();
QByteArray str=msg.toUtf8();
str.append('\n');
tcpSocket->write(str);
}
//读取缓冲区文本
void Dialog::onSocketReadyRead()
{
while(tcpSocket->canReadLine()){
ui->plainTextEdit->appendPlainText("[in]"+tcpSocket->readLine());
}
}
void Dialog::on_btn_clear_clicked()
{
ui->plainTextEdit->clear();
}
void Dialog::on_btn_exit_clicked()
{
QApplication *app;
app->exit(0);
}
Dialog::~Dialog()
{
delete ui;
}
dialog.ui:
以上就完成了服务器端的设计
2 客户端的设计:
项目框架:
同样因为这个有网络部分,所以在.pro文件里添加QT+=network
dialog.h:
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostInfo>
#include <QDebug>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
private:
QTcpSocket *tcpClient;
QString getlocalIP_client();
protected:
void closeEvent(QCloseEvent *event);
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void onConnected();
void onDisConnected();
void onSocketStateChanged(QAbstractSocket::SocketState socketstate);
void onSocketReadyRead();
void on_btn_connect_clicked();
void on_btn_cut_clicked();
void on_btn_clear_clicked();
void on_btn_exit_clicked();
void on_btn_send_clicked();
private:
Ui::Dialog *ui;
};
#endif // DIALOG_H
dialog.cpp:
#include "dialog.h"
#include "ui_dialog.h"
#pragma execution_character_set("utf-8")
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
tcpClient=new QTcpSocket(this);
ui->label_socketstate->setText("Socket 状态:");
QString localIP=getlocalIP_client();
this->setWindowTitle(this->windowTitle()+"---本机IP:"+localIP);
ui->comboBox->addItem(localIP);
//客户端
connect(tcpClient,SIGNAL(connected()),this,SLOT(onConnected()));
connect(tcpClient,SIGNAL(disconnected()),this,SLOT(onDisConnected()));
connect(tcpClient,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,
SLOT(onSocketStateChanged(QAbstractSocket::SocketState)));
connect(tcpClient,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead()));
//按钮
connect(ui->btn_connect,SIGNAL(clicked(bool)),this,SLOT(on_btn_connect_clicked()));
connect(ui->btn_cut,SIGNAL(clicked(bool)),this,SLOT(on_btn_cut_clicked()));
connect(ui->btn_clear,SIGNAL(clicked(bool)),this,SLOT(on_btn_clear_clicked()));
connect(ui->btn_exit,SIGNAL(clicked(bool)),SLOT(on_btn_exit_clicked()));
connect(ui->btn_send,SIGNAL(clicked(bool)),this,SLOT(on_btn_send_clicked()));
}
void Dialog::closeEvent(QCloseEvent *event){
qDebug()<<"ok1";
}
QString Dialog::getlocalIP_client(){
QString hostName=QHostInfo::localHostName();
QHostInfo hostInfo=QHostInfo::fromName(hostName);
QString localIP="";
QList<QHostAddress> addlist=hostInfo.addresses();
if(!addlist.isEmpty()){
for(int i=0;i<addlist.count();i++){
QHostAddress aHost=addlist.at(i);
if(QAbstractSocket::IPv4Protocol==aHost.protocol()){
localIP=aHost.toString();
break;
}
}
}
return localIP;
}
void Dialog::onConnected()
{
ui->plainTextEdit->appendPlainText("--已连接到服务器");
ui->plainTextEdit->appendPlainText("--peer address"+tcpClient->peerAddress().toString());
ui->plainTextEdit->appendPlainText("--peer port:"+QString::number(tcpClient->peerPort()));
ui->btn_connect->setEnabled(false);
ui->btn_cut->setEnabled(true);
}
void Dialog::onDisConnected()
{
ui->plainTextEdit->appendPlainText("已断开与服务器之间的连接");
ui->btn_connect->setEnabled(true);
ui->btn_cut->setEnabled(false);
}
void Dialog::onSocketStateChanged(QAbstractSocket::SocketState socketstate)
{
switch (socketstate) {
case QAbstractSocket::UnconnectedState:
ui->label_socketstate->setText("socket状态: UnconnectedState");
break;
case QAbstractSocket::HostLookupState:
ui->label_socketstate->setText("socket状态: HostLookupState");
case QAbstractSocket::ConnectingState:
ui->label_socketstate->setText("socket状态: ConnectingState");
case QAbstractSocket::ConnectedState:
ui->label_socketstate->setText("socket状态: ConnectedState");
case QAbstractSocket::BoundState:
ui->label_socketstate->setText("socket状态: BoundState");
case QAbstractSocket::ClosingState:
ui->label_socketstate->setText("socket状态: ClosingState");
case QAbstractSocket::ListeningState:
ui->label_socketstate->setText("socket状态: ListeningState");
}
}
void Dialog::on_btn_connect_clicked()
{
QString addr=ui->comboBox->currentText();
quint16 port=ui->spinBox->value();
tcpClient->connectToHost(addr,port);
}
void Dialog::on_btn_cut_clicked()
{
if(tcpClient->state()==QAbstractSocket::ConnectedState){
tcpClient->disconnectFromHost();
}
}
void Dialog::on_btn_clear_clicked()
{
ui->plainTextEdit->clear();
}
void Dialog::on_btn_exit_clicked()
{
QApplication *app;
app->exit();
}
void Dialog::on_btn_send_clicked()
{
QString msg=ui->lineEdit->text();
ui->plainTextEdit->appendPlainText("[out]"+msg);
ui->lineEdit->clear();
ui->lineEdit->setFocus();
QByteArray str=msg.toUtf8();
str.append('\n');
tcpClient->write(str);
}
void Dialog::onSocketReadyRead()
{
while(tcpClient->canReadLine()){
ui->plainTextEdit->appendPlainText("[in]"+tcpClient->readLine());
}
}
Dialog::~Dialog()
{
delete ui;
}
以上就完成了这个项目,这个项目不难,我从昨天晚上开始写了一点,今天早上写了一点就完了,主要为了复习QT网络的知识,如果看不懂,可以百度,谷歌,或者私信我。