服務器:
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();
}