fedora14 基於Qt的TCP發送文本資訊 聊天室 開發記錄

來源:互聯網
上載者:User

      TCP協議部分,還真讓我迷糊了好大一會。原因是剛弄完UDP,UDP的本地端和遠程端代碼是完全一樣的。只是初始化在建構函式裡,綁定的本地Ip地址不同,這點有函數getIp()自動完成。因此本地和遠程完全一樣。但Tcp部分不是這樣,我這裡總結一下(本人水平很低級的,屬菜鳥未入門級。總結下只是防自己忘):

一,伺服器端:

       整個工作流程是:如:

     

   程式的核心部分在tcpNewConnect()這個函數裡,當伺服器收到串連時會觸發這個槽函數。這個函數實現為:

//伺服器監聽到用戶端串連時,伺服器的響應槽函數
void Widget::tcpNewConnect()
{
    QMessageBox box;
    box.setText("tcp用戶端,請求串連....");
    box.exec();
    tcpsocketServer = tcpServer->nextPendingConnection();
    connect(tcpsocketServer, SIGNAL(readyRead()), this, SLOT(tcpReadmesg()));
    connect(ui->tcpSendButton, SIGNAL(clicked()), this, SLOT(tcpSendmesg()));
    ui->tcpSendButton->setEnabled(true);

}

這個時候tcpsocketServer被執行個體化了,tcpsocketServer是一個QTcpSocket類型的,我為了區別用戶端的tcpSocket給加了尾碼server。 也就是說tcpServer的作用僅僅是監聽,監聽到了就執行個體化一個QTcpSocket,剩下的工作由這個QTcpSocket來完成,包括接收資訊和發送資訊。

//TCP端的接收資訊並顯示槽函數
void Widget::tcpReadmesg()
{
    QTextCodec *tc=QTextCodec::codecForName("UTF-8");
    QByteArray data = tcpsocketServer->readAll();
    QString str = tc->toUnicode(data);

    QDateTime time;
    QString timeStr = time.currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");

    autoScroll();
    ui->getTextEdit->setTextColor(QColor("red"));
    ui->getTextEdit->insertPlainText("遠程" + remoteIpStr+": "+ timeStr +"--TCP--\n" );
    ui->getTextEdit->setTextColor(QColor("black"));
    ui->getTextEdit->insertPlainText(str + "\n" );
    autoScroll();
}

//TCP端的發送文本槽函數
void Widget::tcpSendmesg()
{
    autoScroll();
    QString str = ui->sendTextEdit->toPlainText();
    if(str.length()==0)
    {
        QMessageBox box;
        box.setText("請輸入內容後再發送!");
        box.exec();
    }
    else
    {
        QByteArray data = str.toAscii();
        // qDebug()<<str;
        tcpsocketServer->write(data);
        QDateTime time;
        QString timeStr = time.currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");

        ui->getTextEdit->setTextColor(QColor("red"));
        ui->getTextEdit->insertPlainText("本機" + localIpStr + ": " + timeStr + "--TCP--\n");
        ui->getTextEdit->setTextColor(QColor("black"));
        ui->getTextEdit->insertPlainText(str +"\n");
        ui->sendTextEdit->clear(); //點擊發送後,發送編輯框內清零
        ui->sendTextEdit->setFocus(); //焦點停留在發送編輯框
        autoScroll();
    }
}

       有了UDp的經驗,這兩個函數還算好些,至少編碼解碼上不會出問題了。伺服器端和接收端的顯示發送函數都是一樣的。接收函數用的QByteArray data = tcpsocketServer->readAll();發送函數寫資料用的 tcpsocketServer->write(data);著和UDP的發送接收還是有區別的。當然了只是發送簡單的文本可以這麼搞,如果發送大檔案,估計沒這麼簡單了。

二、Tcp用戶端

     用戶端只有一個QTcpSocket *tcpSocket,在建構函式裡tcpSocket = new QTcpSocket(this),我們希望按下“串連”按鍵,用戶端發出請求串連。這個按鍵的槽函數是:

//用戶端,按下啟動TCP按鍵的槽函數
void Widget::on_startTcpBtn_clicked()
{
    remoteIpStr = ui->ipEdit->text();
    port = ui->portEdit->text();
    tcpSocket->abort(); //取消原來的串連
    tcpSocket->connectToHost(remoteIpStr, port.toInt());
}

      核心的一句話是tcpSocket->connectToHost(remoteIpStr, port.toInt());注意這裡remoteIpStr是個QString類型的變數,您也可以寫成tcpSocket->connectToHost(“192.168.2.211”,
6665)這樣來測試下是沒問題的。也可以寫成 remoteHostAddr = new QHostAddress(remoteIpStr); tcpSocket->connectToHost(*remoteHostAddr, port.toInt());這樣也是沒有問題的!看來qt還是很靈活的。

     另外,在用戶端的建構函式裡還應該串連四個槽函數:

connect(tcpSocket, SIGNAL(connected()), this,SLOT(tcpIsConnect()));  
 //已經串連上時的槽函數

connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(tcpFailConnect()));
//中斷連線時的槽函數

 connect(ui->tcpSendButton, SIGNAL(clicked()), this, SLOT(tcpSendmesg())); //發送訊息
    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(tcpReadmesg()));        //收到訊息

發送訊息、接收訊息的和上面一樣,前兩個槽函數只是彈出個提示就行啦,如下:

bool Widget::tcpIsConnect()
{
    ui->tcpSendButton->setEnabled(true);
    QMessageBox box;
    box.setText("恭喜您,TCP串連已建立!");
    box.exec();
    return true;
}
void Widget::tcpFailConnect()
{
    ui->tcpSendButton->setEnabled(false);
    QMessageBox box;
    box.setText("TCP串連失敗,請重新串連或使用UDP發送!");
    box.exec();
}

      最後,總結下讓我一開始雲裡霧裡的基於Qt的TCP協議實現:

      只有兩個類用到,QTcpServer和QTcpSocket,伺服器端用到一個QTcpServer和一個QTcpSocket;用戶端只用一個QTcpSocket。QTcpServer的作用是監聽對方的串連,因此開始時要設定監聽的連接埠號碼或者監聽具體的Ip地址。當有用戶端串連時,QTcpServer調用 tcpsocketServer
= tcpServer->nextPendingConnection();來執行個體化伺服器端的QTcpSocket,然後剩下的發送和接收都由這個QTcpSocket來擔當!用戶端用到QTcpSocket,讓他發送串連請求,當串連成功後又會觸發一個函數。

      一句話:資料的發送、讀取永遠由QTcpSocket來擔當!!!QTcpSocket還可以發送串連請求,QTcpServer進行監聽,並得到發送請求的QTcpSocket執行個體。

核心的代碼,紅色加底線的部分。

疑惑:伺服器端在偵聽到串連請求時,如果不想串連用戶端,拒絕怎麼搞?估計應該再伺服器端加個按鍵,按鍵槽函數裡用QTcpServer的一些方法進行拒絕。繼續研究啊還得!



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.