服務器: incomming incomming.pro #------------------------------------------------- # # Project created by QtCreator 2016-04-08T09:25:22 # #------------------------------------------------- QT += core gui QT +=network greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = incomming TEMPLATE = app SOURCES += main.cpp\ mainwindow.cpp \ myserver.cpp \ socketthread.cpp \ mytcpsocket.cpp HEADERS += mainwindow.h \ myserver.h \ socketthread.h \ mytcpsocket.h FORMS += mainwindow.ui mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> class QTcpSocket; class myserver; namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT private: myserver * server; public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H myserver.h #ifndef MYSERVER #define MYSERVER #include<QObject> #include<QTcpServer> #include<QWidget> class myserver :public QTcpServer{ Q_OBJECT public: myserver(QWidget * parent); protected: virtual void incomingConnection(qintptr socketDescriptor); }; //|定義的結束 必須加; #endif // MYSERVER mytcpsocket.h #ifndef MYTCPSOCKET #define MYTCPSOCKET #include<QTcpSocket> class mytcpsocket :public QTcpSocket { Q_OBJECT public: mytcpsocket(QWidget * parent,qintptr p); private slots: void on_discon(); public: void on_connected(); }; #endif // MYTCPSOCKET socketthread.h #ifndef SOCKETTHREAD #define SOCKETTHREAD #include<QThread> #include<QTcpSocket> #include<QWidget> class mytcpsocket; class socketThread :public QThread { private: qintptr ptr; mytcpsocket * socket; public: socketThread(QWidget * parent,qintptr p); protected: virtual void run(); }; #endif // SOCKETTHREAD mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include"myserver.h" #include<QHostAddress> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); this->server=new myserver(this); this->server->listen(QHostAddress::LocalHost,520); } MainWindow::~MainWindow() { delete ui; } myserver.cpp #include"myserver.h" #include<QMessageBox> #include"mytcpsocket.h" #include"socketthread.h" myserver::myserver(QWidget * parent):QTcpServer(parent){ } void myserver::incomingConnection(qintptr socketDescriptor) { QMessageBox::about(0,"提示","有新鏈接"); socketThread * thread=new socketThread(0,socketDescriptor); thread->start(); /* mytcpsocket * socket=new mytcpsocket(0,socketDescriptor); QThread * thread=new QThread(); socket->moveToThread(thread); thread->start(); */ } mytcpsocket.cpp #include"mytcpsocket.h" #include<QByteArray> #include<QDataStream> #include<QString> #include<QMessageBox> #include<QDebug> mytcpsocket::mytcpsocket(QWidget *parent,qintptr p):QTcpSocket(0) { //connect(this,SIGNAL(),this,SLOT(on_connected())); this->setSocketDescriptor(p); this->on_connected(); this->connect(this,SIGNAL(disconnected()),this,SLOT(on_discon())); } void mytcpsocket::on_connected() { QByteArray arr; QDataStream dts(&arr,QIODevice::WriteOnly); dts<<QString("這是數據"); this->write(arr); //QMessageBox::about(0,"x","發送成功!"); qDebug()<<"發送成功"; } void mytcpsocket::on_discon() { qDebug()<<"有一個客戶端斷開!"; } socketthread.cpp #include"socketthread.h" #include<QString> #include<QByteArray> #include<QDataStream> #include<QMessageBox> #include<QDebug> #include"mytcpsocket.h" socketThread::socketThread(QWidget *parent,qintptr p):QThread(parent) { qDebug()<<"QThread構造函數依然在 舊線程"; this->ptr=p; } void socketThread::run(){ /*1.QObject->moveToThread(Thread *)會把一個Qt對象移動到一個新線程中運行 默認在run()中調用了 exec()這樣 run()執行完後不會 * 直接關閉 線程 還會讓它 進入消息循環 直到調用了 結束 槽 * 2.QtcpSocket 的write()函數是異步的 也就是 調用了 後不會當即 發送數據,它會直接往下執行 直到run()的尾部,若是run()沒有 * 調用exec()進行消息循環等待,那麼 這個線程 直接就結束了,不會再發送。(發送數據失敗) *3.若是在run()中調用了 exec()(發送成功) *4.若是在 write(QByteArray);後面加一句 socket->waitForBytesWritten();這裏就會阻塞等待 直到數據開始發送,這樣 * 不須要exec()在 線程結束以前直接就發送完了 *socket->waitForConnected() * socket->waitForDisconnected() * socket->waitForReadyRead()都是一個道理 */ qDebug()<<"開始新線程"; /* QTcpSocket * socket=new QTcpSocket(); socket->setSocketDescriptor(this->ptr); QByteArray arr; QDataStream dts(&arr,QIODevice::WriteOnly); dts<<QString("這是數據"); socket->write(arr); */ mytcpsocket * socket=new mytcpsocket(0,this->ptr); socket->waitForBytesWritten(); // this->exec(); /* 1. 鏈接服務器 m_tcpSocket->connectToHost("127.0.0.1", 9877); connected = m_tcpSocket->waitForConnected(); 只有使用waitForConnected()後,QTcpSocket才真正嘗試鏈接服務器,並返回是否鏈接的結果。 2. 寫數據 m_tcpSocket->write(str.toStdString().c_str(), strlen(str.toStdString().c_str())); m_tcpSocket->waitForBytesWritten(); 當使用waitForBytesWritten()後,QTcpSocket才真正發送數據。 m_tcpSocket->write(str1.toStdString().c_str(), strlen(str1.toStdString().c_str())); m_tcpSocket->write(str2.toStdString().c_str(), strlen(str2.toStdString().c_str())); 的結果是發送了str1str2 3. 斷開與服務器的鏈接 m_tcpSocket->disconnectFromHost() m_tcpSocket->waitForDisconnected() 4. 善於使用QTcpSocket的SIGNAL:connected(), disconnected(), error(QAbstractSocket::SocketError) 配合自定義私有開關變量bool connected, QTimer 能夠實現自動重鏈接等邏輯。 */ } main.cpp #include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } /***********************/ 客戶端 useincomming useincomming.pro #------------------------------------------------- # # Project created by QtCreator 2016-04-08T09:36:28 # #------------------------------------------------- QT += core gui QT +=network greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = useincomming TEMPLATE = app SOURCES += main.cpp\ mainwindow.cpp HEADERS += mainwindow.h FORMS += mainwindow.ui mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> class QTcpSocket; namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private: QTcpSocket * socket; private: Ui::MainWindow *ui; private slots: void on_readyread(); void on_conn(); }; #endif // MAINWINDOW_H mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include<QTcpSocket> #include<QHostAddress> #include<QString> #include<QByteArray> #include<QDataStream> #include<QMessageBox> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); this->socket=new QTcpSocket(this); this->socket->connectToHost(QHostAddress::LocalHost,520); connect(this->socket,SIGNAL(connected()),this,SLOT(on_conn())); connect(this->socket,SIGNAL(readyRead()),this,SLOT(on_readyread())); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_readyread() { QMessageBox::about(this,"提示","開始接受"); QByteArray array=this->socket->readAll(); QDataStream dts(&array,QIODevice::ReadOnly); QString data; dts>>data; QMessageBox::about(this,"提示",data); } void MainWindow::on_conn() { QMessageBox::about(this,"提示","鏈接成功"); } main.cpp #include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }