1, Project requirements
Don't write it first. We'll add it when we're finished
2, Design ideas
It's late today. Just make a code record. It's all on paper and will be added later
3, Day 1 project diary
1. Today's summary:
I wrote half a server today,
Main functions
1) You can create a server using Tcp protocol, define the port yourself, and click the button to open the server
2) When a server is connected, the connected user can be displayed. Here is the random id number
3) When the client is disconnected, the list is refreshed. Only the online id and the number of online clients are displayed
4) After the client sends data, the message content broadcast is sent to all clients
Test: any network tool can be used. Here, you only need to act as a client.
2. Server interface
explain:
After starting the operation, you can enter the port number. After clicking start service, the button will be grayed out and port cannot be entered. After clicking close service, you will exit. The number of online clients will be displayed in real time. The login log is used to view the login records and is temporarily unavailable.
When a client is connected, the connection id is displayed. After disconnection, it is refreshed in real time.
3. Code structure
Note: tcpsocket is a class inherited from QTcpSocket
tcpsocket is a class inherited from QTcpServer
mymessage is a custom message sending class
1,mymessage.h
There's nothing to say, just encapsulate a message
#ifndef MYMESSAGE_H #define MYMESSAGE_H #include <QString> enum MsgId{ MSG_CLITEN_CONNECT = 0, //Connection message MSG_READ_BYTES, //Read received messages MSG_CLIENT_CLOSE, //Client shutdown message }; class MyMessage { enum MsgId msgid; QString msgbuf; int length; public: MyMessage(); MyMessage(MsgId msgid,QString msgbuf,int length); void setmsgid(MsgId msgid); void setmsgbuf(QString msgbuf); void setlength(int length); int getmsgid(); QString getmsgbuf(); int getlength(); }; #endif // MYMESSAGE_H
2,mymessage.cpp
Implementation of some message functions
#include "mymessage.h" MyMessage::MyMessage() { } MyMessage::MyMessage(MsgId msgid, QString msgbuf, int length) { this->msgid = msgid; this->msgbuf = msgbuf; this->length = length; } void MyMessage::setmsgid(MsgId msgid) { this->msgid = msgid; } void MyMessage::setmsgbuf(QString msgbuf) { this->msgbuf = msgbuf; } void MyMessage::setlength(int length) { this->length = length; } int MyMessage::getmsgid() { return msgid; } QString MyMessage::getmsgbuf() { return msgbuf; } int MyMessage::getlength() { return length; }
3,tcpsocket.h
It inherits from QTcpSocket and then rewrites some functions
#ifndef TCPSOCKET_H #define TCPSOCKET_H #include <QWidget> #include <QTcpSocket> #include <QHostAddress> #include "mymessage.h" #include <QDebug> class TcpSocket : public QTcpSocket { Q_OBJECT public: TcpSocket(QObject* parent = 0); signals: void disconnected(int); //Send offline signal void messageToServer(MyMessage); //Send message to server public slots: void datadisconnected(); //Used to process off-line signals void dataReceived(); //Used to process received client messages }; #endif // TCPSOCKET_H
4,tcpsocket.cpp
#include "tcpsocket.h" TcpSocket::TcpSocket(QObject *parent): QTcpSocket(parent) { //I originally wanted to send the connection signal to the server here, but it was found that the port number and ip address could not be read when his state changed, so I put it in the socket in the room to send the message // connect(this,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(dataconnected())); //Connect the disconnection function / read function and the custom slot function connect(this,SIGNAL(disconnected()),this,SLOT(datadisconnected())); connect(this,SIGNAL(readyRead()),this,SLOT(dataReceived())); } void TcpSocket::datadisconnected() { //- 1 will be sent after disconnection emit disconnected(this->socketDescriptor()); } void TcpSocket::dataReceived() { //Processing supervision signals while(this->bytesAvailable() > 0){ char buf[1024]; int length = bytesAvailable(); this->read(buf,length); //Read receive QString msgbuf = buf; //Convert it into a message and send it to the server MyMessage message(MSG_READ_BYTES,buf,length); emit messageToServer(message); //Transmit message signal } }
5,tcpserver.h
#ifndef TCPSERVER_H #define TCPSERVER_H #include <QObject> #include <QtNetwork> #include <QTcpServer> #include "tcpsocket.h" class TcpServer : public QTcpServer { Q_OBJECT public: explicit TcpServer(QObject* parent = 0,int port = 0); QList<TcpSocket*> tcpSocketList;//list container for storing client pointers QList<int> descriptorList;//It is used to compare the container of the client. It is used when deleting protected: void incomingConnection(int socketDescriptor);//Overridden join function signals: void msgToServer(MyMessage);//A signal used to send a message to main public slots: void msgFromSocket(MyMessage);//Slot function used to process signals received from socket void tcpDisconnected(int);//Slot function to handle client disconnection }; #endif // TCPSERVER_H
6,tcpserver.cpp
#include "tcpserver.h" TcpServer::TcpServer(QObject *parent, int port): QTcpServer(parent) { listen(QHostAddress::AnyIPv4,port); //Used to listen to ipv4 clients. port is passed in } void TcpServer::incomingConnection(int socketDescriptor) { TcpSocket *tcpSocket = new TcpSocket(this); tcpSocket->setSocketDescriptor(socketDescriptor); //Send message to server interface QString msgbuf = QString::number(socketDescriptor); //QString msgbuf = tcpSocket->peerAddress().toString()+" "+QString::number(tcpSocket->peerPort()); MyMessage message(MSG_CLITEN_CONNECT,msgbuf,msgbuf.length()); //qDebug()<<msgbuf << " "<<socketDescriptor; emit msgToServer(message);//Send connection message connect(tcpSocket, SIGNAL(messageToServer(MyMessage)), this, SLOT(msgFromSocket(MyMessage))); connect(tcpSocket, SIGNAL(disconnected(int)), this, SLOT(tcpDisconnected(int))); //Put the socket pointer in the socket list tcpSocketList.append(tcpSocket); //Put his Descriptor in another container descriptorList.append(socketDescriptor); } void TcpServer::msgFromSocket(MyMessage message) { emit msgToServer(message); //The following is to reply the same data to the client for(int i = 0; i < tcpSocketList.count(); i++) { QTcpSocket *temp = tcpSocketList.at(i); if(temp->write(message.getmsgbuf().toLatin1(), message.getlength()) != message.getlength()) { continue; } } } void TcpServer::tcpDisconnected(int descriptor) { //After disconnection, the descriptor will become - 1, so I don't know which is disconnected, so I can only judge by myself //Therefore, a qlist < int > is used to store. When it becomes - 1, it means that it is turned off for(int i = 0; i < tcpSocketList.count(); i++) { QTcpSocket *temp = tcpSocketList.at(i); if(temp->socketDescriptor() == descriptor) { temp->destroyed(); tcpSocketList.removeAt(i); break; } } int close_descriptor = 0; int j = 0; //Compare the two containers to see which client is offline for(int i = 0; i < descriptorList.count(); i++){ close_descriptor = descriptorList.value(i); for(j = 0; j < tcpSocketList.count(); j++){ QTcpSocket *temp = tcpSocketList.at(j); if(close_descriptor == temp->socketDescriptor()){ break; } } if(j == tcpSocketList.count()){ //qDebug()<<close_descriptor << "is close"; descriptorList.removeAt(i); break; } } //Send a message that the client is closed QString msgbuf = QString::number(close_descriptor); MyMessage message(MSG_CLIENT_CLOSE,msgbuf,msgbuf.length()); emit msgToServer(message); return; }
7,mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "tcpserver.h" #include <QtNetwork> #include <QMessageBox> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); void deleteclientlist(int);//Used to clear the signal client list private: Ui::MainWindow *ui; QTcpServer *tcpServer; int port; int online_num; public slots: void RecvMsg(MyMessage); private slots: void on_pushclose_clicked(); void on_pushopen_clicked(); }; #endif // MAINWINDOW_H
8,mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" #include "tcpserver.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); this->setWindowTitle("The server"); ui->lineport->setText("8010");//The default port number is 8010 ui->label_onlinenum->setText("0");//The default number of connections must be 0 } MainWindow::~MainWindow() { delete ui; } void MainWindow::deleteclientlist(int client_id) { int row = 0; QString str = QString::number(client_id); QString line; while(row < ui->listusers->count()){ line=ui->listusers->item(row)->text(); if(str==line) { //Qdebug() < < "delete succeeded"; ui->listusers->takeItem(row); break; } row++; } } void MainWindow::RecvMsg(MyMessage message) { //qDebug()<<message.getmsgbuf().left(message.getlength()); if(message.getmsgid() == MSG_CLITEN_CONNECT){ ui->listusers->addItem(message.getmsgbuf().left(message.getlength())); ui->label_onlinenum->setText(QString::number(ui->listusers->count())); }else if(message.getmsgid() == MSG_READ_BYTES){ //qDebug()<<message.getmsgbuf().left(message.getlength()); }else if(message.getmsgid() == MSG_CLIENT_CLOSE){ //After receiving the closing message, delete the id of the client. The message content is the id of the client this->deleteclientlist(message.getmsgbuf().toInt()); //Update the label of online people ui->label_onlinenum->setText(QString::number(ui->listusers->count())); } return; } void MainWindow::on_pushclose_clicked() { qApp->quit(); } void MainWindow::on_pushopen_clicked() { if(ui->lineport->text().isEmpty()){ QMessageBox::warning(this, tr("warning!!"), tr("please input you Port!")); return; } port = ui->lineport->text().toInt(); tcpServer = new TcpServer(this, port); QObject::connect(tcpServer,SIGNAL(msgToServer(MyMessage)),this,SLOT(RecvMsg(MyMessage))); //The button cannot be clicked after the service is started ui->pushopen->setEnabled(false); ui->lineport->setEnabled(false); return; }
4. Project documents
5. Effect display
1) You can create a server using Tcp protocol, define the port yourself, and click the button to open the server
2) When a server is connected, the connected user can be displayed. Here is the random id number
3) When the client is disconnected, the list is refreshed. Only the online id and the number of online clients are displayed
4) After the client sends data, the message content broadcast is sent to all clients
All have been realized, and the effects are as follows
4, End of record
Conclusion: it's a long way to go. I'll ask from top to bottom!!!