话不多说,先一睹芳颜
一.服务端
1.界面设计
2.服务端获取主机地址
将主机地址放在了一个容器中.
3.初始化服务端
当有新的客户端请求连接时,会发出newConnection()的信号.
4.服务端开启监听
注意listen函数的参数类型,要转换一下.
5.套接字socket
当有客户端请求连接后,我们需要套接字来作为服务端和客户端的接口.
6.服务端的读写
当有信息可以读的时候,我们就可以来读信息.
发送信息用write,注意要用utf8编码.
7.socket的其他信号的槽函数
8.服务端关闭监听
9.完整代码
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QTcpServer> #include <QTcpSocket> #include <QHostInfo> #include <QHostAddress> #include <QLabel> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void on_pushButtonOpen_clicked(); void on_pushButtonClose_clicked(); void onNewConnection(); void onReadyRead(); void onConnected(); void onDisconnected(); void onStateChanged(QAbstractSocket::SocketState socketState); private: Ui::MainWindow *ui; QTcpServer *tcpServer; QTcpSocket *tcpSocket; QStringList addrs; QLabel *labelState; void initTCPServer(); void getHostAddress(); void sendMsg(const QString&str); void initLabel(); }; #endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); initTCPServer(); initLabel(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButtonOpen_clicked() { getHostAddress(); int i=rand()%addrs.count(); QString addr=addrs.at(i); ui->labelIP->setText("服务器地址:"+addr); quint16 port=rand()%9000+8000; ui->labelPort->setText("服务器端口:"+QString::number(port)); QHostAddress IP(addr); tcpServer->listen(IP,port); ui->pushButtonOpen->setEnabled(false); ui->pushButtonClose->setEnabled(true); ui->labelIP->show(); ui->labelPort->show(); } void MainWindow::on_pushButtonClose_clicked() { if(tcpServer->isListening()) { tcpServer->close(); ui->pushButtonOpen->setEnabled(true); ui->pushButtonClose->setEnabled(false); ui->labelIP->hide(); ui->labelPort->hide(); } } void MainWindow::onNewConnection() { tcpSocket=tcpServer->nextPendingConnection(); connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(onReadyRead())); connect(tcpSocket,SIGNAL(connected()),this,SLOT(onConnected())); connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(onDisconnected())); connect(tcpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState socketState)), this,SLOT(onStateChanged(QAbstractSocket::SocketState))); onStateChanged(tcpSocket->state()); } void MainWindow::onReadyRead() { QString str; while(tcpSocket->canReadLine()) { QString read=tcpSocket->readLine(); //qDebug()<<tcpSocket->readLine()<<endl; if(read=="人有悲欢离合\n") { str="月有阴晴圆缺"; sendMsg(str); } else if(read=="此情可待成追忆\n") { str="只是当时已惘然"; sendMsg(str); } else if(read=="宁教我负天下人\n") { str="休教天下人负我"; sendMsg(str); } else { str="喂喂喂!你在说啥?"; sendMsg(str); } } } void MainWindow::onConnected() { labelState->setText("连接状态: 已连接"); } void MainWindow::onDisconnected() { labelState->setText("连接状态: 已断开连接"); tcpSocket->deleteLater();//之后删 } void MainWindow::onStateChanged(QAbstractSocket::SocketState socketState) { switch (socketState) { case QAbstractSocket::UnconnectedState: labelState->setText("连接状态: 已断开连接"); break; case QAbstractSocket::ConnectedState: labelState->setText("连接状态: 已连接"); break; } } void MainWindow::initTCPServer() { tcpServer=new QTcpServer(this); connect(tcpServer,SIGNAL(newConnection()),this,SLOT(onNewConnection())); } void MainWindow::getHostAddress() { QHostInfo hostInfo =QHostInfo::fromName(QHostInfo::localHostName()); QList<QHostAddress> lists=hostInfo.addresses(); for(int i=0;i<lists.count();i++) { QHostAddress address=lists[i]; if(address.protocol()==QAbstractSocket::IPv4Protocol) { addrs.append(address.toString()); } } } void MainWindow::sendMsg(const QString &str) { QByteArray msg= str.toUtf8(); msg.append('\n'); tcpSocket->write(msg); } void MainWindow::initLabel() { labelState=new QLabel("连接状态: 未连接"); ui->statusbar->addWidget(labelState); ui->labelIP->hide(); ui->labelPort->hide(); QLinearGradient gradient(0,0,ui->label->width(),ui->label->height()); gradient.setColorAt(0,Qt::green); gradient.setColorAt(1,Qt::blue); QPalette palette; palette.setBrush(QPalette::WindowText,QBrush(gradient)); ui->label->setPalette(palette); }
二.客户端
1.界面设计
2.套接字的初始化
3.连接服务器
如果连接成功,就弹出我们的发送框.
这里的tcpSocketGet是在对话框中获取到套接字的,然后可以来发送信息.
4.界面设计师类
5.客户端的读写
读到的信息添加到对话框中.
发送信息:
发送的信息都添加了一个换行符,因为这样可以判断一行,然后对方进行读取.
6.客户端关闭连接
7.完整代码
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QTcpSocket> #include <QHostAddress> #include <QLabel> #include <dialog.h> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void on_pushButtonConnect_clicked(); void on_pushButtonDisConnect_clicked(); void onConnected(); void onDisconnected(); void onReadyRead(); private: Ui::MainWindow *ui; QTcpSocket*tcpSocket; QLabel* labState; QLabel* labIP; QLabel* labPort; Dialog* chat; void initTCPSocket(); void intitLabel(); }; #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); initTCPSocket(); intitLabel(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::initTCPSocket() { tcpSocket=new QTcpSocket(this); connect(tcpSocket,SIGNAL(connected()),this,SLOT(onConnected())); connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(onDisconnected())); connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(onReadyRead())); } void MainWindow::intitLabel() { labState=new QLabel(this); labState->setMinimumWidth(100); labPort=new QLabel(this); labPort->setMinimumWidth(100); labIP=new QLabel(this); this->statusBar()->addWidget(labState); this->statusBar()->addWidget(labPort); this->statusBar()->addWidget(labIP); } void MainWindow::on_pushButtonConnect_clicked() { QString addr=ui->lineEditAddr->text(); QString port=ui->lineEditProt->text(); if(addr==NULL||port==NULL)return; QHostAddress IP(addr); tcpSocket->connectToHost(IP,port.toInt()); } void MainWindow::on_pushButtonDisConnect_clicked() { if(tcpSocket->state()==QAbstractSocket::ConnectedState) { tcpSocket->disconnectFromHost(); chat->close(); } } void MainWindow::onConnected() { labState->setText("连接状态: 已连接"); labPort->setText("服务器端口: "+QString::number(tcpSocket->peerPort())); labIP->setText("服务器IP: "+tcpSocket->peerAddress().toString()); chat=new Dialog(this); //this->hide(); chat->tcpSocketGet(tcpSocket); chat->show(); } void MainWindow::onDisconnected() { labState->setText("连接状态: 已断开连接"); labState->clear(); labIP->clear(); labPort->clear(); } void MainWindow::onReadyRead() { while(tcpSocket->canReadLine()) { QString str=tcpSocket->readLine(); chat->setMsg(str); } }
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QTcpSocket> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = nullptr); ~Dialog(); void setMsg(const QString&str); void tcpSocketGet(QTcpSocket *tcpSocket); private slots: void on_pushButton_clicked(); private: Ui::Dialog *ui; QTcpSocket*tcpSocket; protected: void closeEvent(QCloseEvent*event); }; #endif // DIALOG_H
dialog.cpp
#include "dialog.h" #include "ui_dialog.h" #include <QDebug> #include <QHostAddress> Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); ui->plainTextEdit->setReadOnly(true); } Dialog::~Dialog() { delete ui; } void Dialog::setMsg(const QString &str) { ui->plainTextEdit->appendPlainText("服务器: "+str); } void Dialog::tcpSocketGet(QTcpSocket *tcpSocket) { this->tcpSocket=tcpSocket; //qDebug()<<this->tcpSocket->peerAddress(); } void Dialog::on_pushButton_clicked() { QString str=ui->lineEdit->text(); QByteArray msg=str.toUtf8(); msg.append('\n'); tcpSocket->write(msg); ui->plainTextEdit->appendPlainText("客户: "+str); ui->lineEdit->clear(); ui->lineEdit->setFocus(); } void Dialog::closeEvent(QCloseEvent *event) { if(tcpSocket->state()==QAbstractSocket::ConnectedState) { tcpSocket->disconnectFromHost(); } event->accept(); }
三.结语
当然我这里只是稍微的演示一下,你也可以自己在服务端做手脚,自己发送信息也可以.
念头通达,现在应该算是炼气期1层.