博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Qt NetWork即时通讯网络聊天室(基于TCP)
阅读量:4981 次
发布时间:2019-06-12

本文共 10203 字,大约阅读时间需要 34 分钟。

本文使用QT的网络模块来创建一个网络聊天室程序,主要包括以下功能:

1、基于TCP的可靠连接(QTcpServer、QTcpSocket)

2、一个服务器,多个客户端

3、服务器接收到某个客户端的请求以及发送信息,经该信息重定向发给其它客户端

最终实现一个共享聊天内容的聊天室!

开发测试环境:QT5.12.0 + Qt Creator 4.8.0 + MinGW7.3

 

代码如下:

1、服务器 QtInstantMessagingServer

基于Console的应用程序,因为这里不需要界面。

QT += core network

QT -= gui

 Server.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 
#ifndef
 SERVER_H
#define
 SERVER_H
#include
 <QObject>
#include
 <QTcpServer>
#include
 <QTcpSocket>
#include
 <QDebug>
#include
 <QVector>
class
 Server : 
public
 QObject
{
    Q_OBJECT
public
:
    
explicit
 Server(QObject *parent = nullptr);
    
void
 startServer();
    
void
 sendMessageToClients(QString message);
signals:
public
 slots:
    
void
 newClientConnection();
    
void
 socketDisconnected();
    
void
 socketReadyRead();
    
void
 socketStateChanged(QAbstractSocket::SocketState state);
private
:
    QTcpServer*             chatServer;
    QVector<QTcpSocket*>*   allClients;
};
#endif
 
// SERVER_H
 Server.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
 
#include
 
"Server.h"
Server::Server(QObject *parent) : QObject(parent)
{
}
void
 Server::startServer()
{
    
// store all the connected clients
    allClients = 
new
 QVector<QTcpSocket*>;
    
// created a QTcpServer object called chatServer
    chatServer = 
new
 QTcpServer();
    
// limit the maximum pending connections to 10 clients.
    chatServer->setMaxPendingConnections(
10
);
    
// The chatServer will trigger the newConnection() signal whenever a client has connected to the server.
    connect(chatServer, SIGNAL(newConnection()), 
this
, SLOT(newClientConnection()));
    
// made it constantly listen to port 8001.
    
if
 (chatServer->listen(QHostAddress::Any, 
8001
))
    {
        qDebug() << 
"Server has started. Listening to port 8001."
;
    }
    
else
    {
        qDebug() << 
"Server failed to start. Error: "
 + chatServer->errorString();
    }
}
void
 Server::sendMessageToClients(QString message)
{
    
if
 (allClients->size() > 
0
)
    {
        
// we simply loop through the allClients array and pass the message data to all the connected clients.
        
for
 (
int
 i = 
0
; i < allClients->size(); i++)
        {
            
if
 (allClients->at(i)->isOpen() && allClients->at(i)->isWritable())
            {
                allClients->at(i)->write(message.toUtf8());
            }
        }
    }
}
void
 Server::newClientConnection()
{
    
// Every new client connected to the server is a QTcpSocket object,
    
// which can be obtained from the QTcpServer object by calling nextPendingConnection().
    QTcpSocket* client = chatServer->nextPendingConnection();
    
// You can obtain information about the client
    
// such as its IP address and port number by calling peerAddress() and peerPort(), respectively.
    QString ipAddress = client->peerAddress().toString();
    
int
 port = client->peerPort();
    
// connect the client's disconnected(),readyRead() and stateChanged() signals to its respective slot function.
    
// 1、When a client is disconnected from the server, the disconnected() signal will be triggered
    connect(client, &QTcpSocket::disconnected, 
this
, &Server::socketDisconnected);
    
// 2、whenever a client is sending in a message to the server, the readyRead() signal will be triggered.
    connect(client, &QTcpSocket::readyRead, 
this
, &Server::socketReadyRead);
    
// 3、 connected another signal called stateChanged() to the socketStateChanged() slot function.
    connect(client, &QTcpSocket::stateChanged, 
this
, &Server::socketStateChanged);
    
// store each new client into the allClients array for future use.
    allClients->push_back(client);
    qDebug() << 
"Socket connected from "
 + ipAddress + 
":"
 + QString::number(port);
}
// When a client is disconnected from the server, the disconnected() signal will be triggered
void
 Server::socketDisconnected()
{
    
// displaying the message on the server console whenever it happens, and nothing more.
    QTcpSocket* client = qobject_cast<QTcpSocket*>(QObject::sender());
    QString socketIpAddress = client->peerAddress().toString();
    
int
 port = client->peerPort();
    qDebug() << 
"Socket disconnected from "
 + socketIpAddress + 
":"
 + QString::number(port);
}
// whenever a client is sending in a message to the server, the readyRead() signal will be triggered.
void
 Server::socketReadyRead()
{
    
// use QObject::sender() to get the pointer of the object that emitted the readyRead signal
    
// and convert it to the QTcpSocket class so that we can access its readAll() function.
    QTcpSocket* client = qobject_cast<QTcpSocket*>(QObject::sender());
    QString socketIpAddress = client->peerAddress().toString();
    
int
 port = client->peerPort();
    QString data = QString(client->readAll());
    qDebug() << 
"Message: "
 + data + 
" ("
 + socketIpAddress + 
":"
 + QString::number(port) + 
")"
;
    
// redirect the message, just passing the message to all connected clients.
    sendMessageToClients(data);
}
// This function gets triggered whenever a client's network state has changed,
// such as connected, disconnected, listening, and so on.
void
 Server::socketStateChanged(QAbstractSocket::SocketState state)
{
    QTcpSocket* client = qobject_cast<QTcpSocket*>(QObject::sender());
    QString socketIpAddress = client->peerAddress().toString();
    
int
 port = client->peerPort();
    QString desc;
    
// simply print out a relevant message according to its new state
    
if
 (state == QAbstractSocket::UnconnectedState)
        desc = 
"The socket is not connected."
;
    
else
 
if
 (state == QAbstractSocket::HostLookupState)
        desc = 
"The socket is performing a host name lookup."
;
    
else
 
if
 (state == QAbstractSocket::ConnectingState)
        desc = 
"The socket has started establishing a connection."
;
    
else
 
if
 (state == QAbstractSocket::ConnectedState)
        desc = 
"A connection is established."
;
    
else
 
if
 (state == QAbstractSocket::BoundState)
        desc = 
"The socket is bound to an address and port."
;
    
else
 
if
 (state == QAbstractSocket::ClosingState)
        desc = 
"The socket is about to close (data may still be waiting to be written)."
;
    
else
 
if
 (state == QAbstractSocket::ListeningState)
        desc = 
"For internal use only."
;
    qDebug() << 
"Socket state changed ("
 + socketIpAddress + 
":"
 + QString::number(port) + 
"): "
 + desc;
}
Main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
 
#include
 <QCoreApplication>
#include
 
"Server.h"
int
 main(
int
 argc, 
char
 *argv[])
{
    QCoreApplication a(argc, argv);
    Server* myServer = 
new
 Server();
    myServer->startServer();
    
return
 a.exec();
}

2、客户端QtInstantMessagingClient

 基于Widget的应用程序,客户端需要一个友好的界面,父类QMainWindow,MainWindow.ui定义界面如下:

可以给不同的客户端取个名字,如“Michael”、“James”等等,点击“Connect”按钮连接服务端,此时Label变为“Disconnect”。

QT       += core gui network

 MainWindow.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 
#ifndef
 MAINWINDOW_H
#define
 MAINWINDOW_H
#include
 <QMainWindow>
#include
 <QDebug>
#include
 <QTcpSocket>
namespace
 Ui {
class
 MainWindow;
}
class
 MainWindow : 
public
 QMainWindow
{
    Q_OBJECT
public
:
    
explicit
 MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private
 slots:
    
void
 on_connectButton_clicked();
    
void
 socketConnected();
    
void
 socketDisconnected();
    
void
 socketReadyRead();
    
void
 on_sendButton_clicked();
private
:
    Ui::MainWindow* ui;
    
bool
            connectedToHost;
    QTcpSocket*     socket;
    
void
 printMessage(QString message);
};
#endif
 
// MAINWINDOW_H
 MainWindow.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
 
#include
 
"MainWindow.h"
#include
 
"ui_MainWindow.h"
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(
new
 Ui::MainWindow)
{
    ui->setupUi(
this
);
    connectedToHost = 
false
;
}
MainWindow::~MainWindow()
{
    
delete
 ui;
}
void
 MainWindow::on_connectButton_clicked()
{
    
if
 (!connectedToHost)
    {
        
// create a QTcpSocket object called socket and make it connect to a host at 127.0.0.1 on port 8801.
        socket = 
new
 QTcpSocket();
        
// connected the socket object to its respective slot functions when connected(),disconnected(), and readReady() signals were triggered.
        
// This is exactly the same as the server code
        connect(socket, SIGNAL(connected()), 
this
, SLOT(socketConnected()));
        connect(socket, SIGNAL(disconnected()), 
this
, SLOT(socketDisconnected()));
        connect(socket, SIGNAL(readyRead()), 
this
, SLOT(socketReadyRead()));
        
// Since this is only for testing purposes, we will connect the client to our test server,
        
// which is located on the same computer.
        
// If you're running the server on another computer,
        
// you may change the IP address to a LAN or WAN address, depending on your need.
        socket->connectToHost(
"127.0.0.1"
8001
);
    }
    
else
    {
        QString name = ui->nameInput->text();
        socket->write(
"<font color=\"
Orange\
">"
 + name.toUtf8() + 
" has left the chat room.</font>"
);
        socket->disconnectFromHost();
    }
}
void
 MainWindow::socketConnected()
{
    qDebug() << 
"Connected to server."
;
    printMessage(
"<font color=\"
Green\
">Connected to server.</font>"
);
    QString name = ui->nameInput->text();
    socket->write(
"<font color=\"
Purple\
">"
 + name.toUtf8() + 
" has joined the chat room.</font>"
);
    ui->connectButton->setText(
"Disconnect"
);
    connectedToHost = 
true
;
}
void
 MainWindow::socketDisconnected()
{
    qDebug() << 
"Disconnected from server."
;
    printMessage(
"<font color=\"
Red\
">Disconnected from server.</font>"
);
    ui->connectButton->setText(
"Connect"
);
    connectedToHost = 
false
;
}
void
 MainWindow::socketReadyRead()
{
    ui->chatDisplay->append(socket->readAll());
}
void
 MainWindow::printMessage(QString message)
{
    ui->chatDisplay->append(message);
}
void
 MainWindow::on_sendButton_clicked()
{
    QString name = ui->nameInput->text();
    QString message = ui->messageInput->text();
    socket->write(
"<font color=\"
Blue\
">"
 + name.toUtf8() + 
"</font>: "
 + message.toUtf8());
    ui->messageInput->clear();
}
 Main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
 
#include
 
"MainWindow.h"
#include
 <QApplication>
int
 main(
int
 argc, 
char
 *argv[])
{
    QApplication a(argc, argv);
    
    MainWindow w;
    w.show();
    
return
 a.exec();
}

构建成功后,将生成的QtInstantMessagingServer.exe以及QtInstantMessagingClient.exe置于.\Qt\Qt5.12.0\5.12.0\mingw73_64\bin目录下(该目录下可以双击exe直接运行!)

 

 

转载于:https://www.cnblogs.com/MakeView660/p/10825439.html

你可能感兴趣的文章
定义一些常亮
查看>>
怎么准确的判断当前页面是否有虚拟导航栏
查看>>
客户端(浏览器端)数据存储技术概览
查看>>
redis发布(pub)、订阅(sub)模式
查看>>
Python数据分析-知识宝藏
查看>>
安装libwxsmithlib-dev时提示“正试图覆盖...”的错误
查看>>
logback日志丢失的情况之一
查看>>
Style Transfer for Headshot Portraits
查看>>
[Windows Phone 7璀璨]北漂1.0在线歌词播放器一.项目搭建及版权声明
查看>>
ios 添加多个target 管理 多个版本文件
查看>>
二阶段之四
查看>>
masonry框架的使用之-多个视图的均匀等间距分布
查看>>
平面最近点对(分治)
查看>>
如何将centos7自带的firewall防火墙更换为iptables防火墙
查看>>
Intent 的两种主要使用方法
查看>>
5239-回忆京都-洛谷3月赛gg祭
查看>>
c# API接受图片文件以Base64格式上传图片
查看>>
ZTE U880 查看内部版本号
查看>>
电池设计
查看>>
PHP 底层的运行机制与原理
查看>>