2017年6月22日 星期四

[QT] 利用QTcpSocket 建立連線

前陣子寫作業要用到連線,就有去研究一下官網的example

今天要實作出一個可以自己選擇要當host還是client,然後client要輸入IP和port,最後可以傳輸文字並顯示出來....



下面先寫一些會用到比較重要,會用到的class出來

連線:
    QTcpServer
    QTcpSocket
    QNetworkInterface
互傳資料:
    QDataStream
    QByteArray
在pro file裡面記得要加上network,也就是像這樣
QT       += core gui network


再來有4個部分:
    1.host端
    2.client端
    3.傳遞資料
    4.接收資料

Host 端:
    1.new 一個QTcpServer的object出來(後面簡稱tcpServer)
    2.把自己的IP和連線用的port秀出來(給client端建立連線)
    3.讓tcpServer開始listen
    4.當有連線進來的時候把連線抓住(之後才可以拿這個連線來傳資料)
    5.當有連線進來的時候就可以開始傳資料了

我覺得還蠻直觀的,就直接放code了
//開始listen
tcpServer->listen();
//return 電腦所有的IP
QList<QHostAddress> ipList = QNetworkInterface::allAddresses();
status->setText("IP : \n");
foreach(QHostAddress i, ipList){
//蒐集這台電腦的所有IP,等等print出來
if(i.toIPv4Address()) status->setText(status->text() + i.toString() + '\n');
}
//把資訊print出來
status->setText(status->text() + "\nport : " + QString::number(tcpServer->serverPort()) + '\n');
//當有新的連線進來就準備開始了
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(prepareStart()));
view raw gistfile1.txt hosted with ❤ by GitHub

Client 端:
    1.new 一個QTcpSocket的object出來(後面傳資料就是用這個!)
    2.輸入host提供的IP 和port
    3.嘗試連線
    4.連線失敗返回2.3,成功就繼續
    5.成功就可以開始傳資料了
這也還蠻直觀的,所以也直接放code
//都有東西才開始嘗試連線
if(ipEdit->text().isEmpty() || portEdit->text().isEmpty()) return;
host = ipEdit->text();
port = portEdit->text().toInt();
//嘗試連線
tcpSocket->connectToHost(host,port);
//用一個timer每0.1秒查看是否連線成功,寫在其他地方
connect(checkConnect, SIGNAL(timeout()), this, SLOT(connectSuccess()));
connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readMessage()));
view raw gistfile1.txt hosted with ❤ by GitHub

傳遞資料(send):
    1.用QByteArray來當等等傳輸用的容器
    2.用QDataStream來把資料放到QByteArray裡面
    3.把QByteArray丟到已經建立好的連線中
       (host的連線用QTcpServer 的 nextPendingConnection 把client傳來的連線抓起來,一樣丟給tcpSocket)

QByteArray byte;
QDataStream stream(&byte, QIODevice::WriteOnly);
stream<<sendMsg->text();
tcpSocket->write(byte);
view raw gistfile1.txt hosted with ❤ by GitHub
接收資料(receive):
  1.一樣用QDataStream來接收資料(device就是設成tcpSocket啦~)
    2.開始transaction(用startTransaction)
    3.接收到的東西看是什麼type,直接用>>operator就可以了

QDataStream in(tcpSocket);
in.startTransaction();
if(!in.commitTransaction()){
return;
}
QString data;
in>>data;
receiveMsg->setText(receiveMsg->toPlainText() + '\n' + data);
view raw gistfile1.txt hosted with ❤ by GitHub
然後還有要怎麼知道現在有資料傳進來呢!!
QTcpSocket有一個signal是 readyRead(),很直觀的~~
QTcpServer也有有newConnection() 來看是不是有連線的要求
用connect把他們接起來就可以很方便的做出來了!
 
參考code:
https://github.com/afcidk/QTcpSocket

1 則留言:

  1. 請問主從之分
    主控端一定是負責listen的嗎?
    不能是受控端負責listen有沒有連線給他嗎?
    然後受控端負責接收命令和執行命令,這樣可以嗎?

    回覆刪除