client
mainwindow.h
#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 = 0);
~MainWindow();
void printMessage(QString message);
private slots:
void on_connectButton_clicked();
void on_sendButton_clicked();
void socketConnected();
void socketDisconnected();
void socketReadyRead();
private:
Ui::MainWindow *ui;
//是否被连接
bool connectedToHost;
//连接的套接子
QTcpSocket* socket;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#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::printMessage(QString message)
{
//打印消息
ui->chatDisplay->append(message);
}
void MainWindow::on_connectButton_clicked()
{
if (!connectedToHost)
{
//创建套接子
socket = new QTcpSocket();
//连接信号槽
connect(socket, SIGNAL(connected()), this, SLOT(socketConnected()));
connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
connect(socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead()));
//连接服务器
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::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();
}
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()
{
printMessage(socket->readAll());
}
server.h
#ifndef SERVER_H
#define SERVER_H
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QVector>
#include <QDebug>
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 socketReadReady();
void socketStateChanged(QAbstractSocket::SocketState state);
private:
//服务器指针
QTcpServer* chatServer;
//客户端
QVector<QTcpSocket*>* allClients;
};
#endif // SERVER_H
server.cpp
#include "server.h"
server::server(QObject *parent) : QObject(parent)
{
}
//启动服务器
void server::startServer()
{
allClients = new QVector<QTcpSocket*>;
chatServer = new QTcpServer();
//设置最大连接数
chatServer->setMaxPendingConnections(10);
connect(chatServer, SIGNAL(newConnection()), this, SLOT(newClientConnection()));
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)
{
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()
{
QTcpSocket* client = chatServer->nextPendingConnection();
QString ipAddress = client->peerAddress().toString();
int port = client->peerPort();
connect(client, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
connect(client, SIGNAL(readyRead()),this, SLOT(socketReadReady()));
connect(client, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));
allClients->push_back(client);
qDebug() << "Socket connected from " + ipAddress + ":" + QString::number(port);
}
void server::socketDisconnected()
{
QTcpSocket* client = qobject_cast<QTcpSocket*>(QObject::sender());
QString socketIpAddress = client->peerAddress().toString();
int port = client->peerPort();
qDebug() << "Socket disconnected from " + socketIpAddress + ":" + QString::number(port);
}
void server::socketReadReady()
{
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) + ")";
sendMessageToClients(data);
}
void server::socketStateChanged(QAbstractSocket::SocketState state)
{
QTcpSocket* client = qobject_cast<QTcpSocket*>(QObject::sender());
QString socketIpAddress = client->peerAddress().toString();
int port = client->peerPort();
QString desc;
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
#include <QCoreApplication>
#include "server.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
server* myServer = new server();
myServer->startServer();
return a.exec();
}