前言
前一個博客,試了TCP的服務器與客戶端的連接與斷開,接下就是客戶端與服務器互發信息。
客戶端
1.往服務器發送信息
//發送消息
void Client::on_buttonSendMessage_clicked()
{
QString data = ui->textEditInput->toPlainText();
if(data.length() != 0)
{
tcpClient->write(data.toLatin1());
ui->textEditInput->clear();
ui->textEditStatus->append("發送文本消息成功!");
data.clear();
}
else
{
ui->textEditStatus->append("不能發送空的消息!");
}
}
當客戶端連接上服務器之後,在輸入窗口下輸入文字(英文),然後點發送按鍵,信息往服務器發送。
2.接收來自服務器的信息
2.1 在構造函數裏添加一個槽函數做接收到信息的事件響應
connect(tcpClient, SIGNAL(readyRead()), this, SLOT(readServerMessage()));
2.1 實現這個槽函數,接收信息並顯示出來
//接收服務器端的信息並顯示
void Client::readServerMessage()
{
QByteArray buffer = tcpClient->readAll();
if(!buffer.isEmpty())
{
ui->textEditAccept->append(buffer);
}
}
服務器
1.在服務器要加上有新客戶端連接時的槽函數
//有新的連接時的槽函數
connect(tcpServer,SIGNAL(newConnection()),this, SLOT(newConnectionSlot()));
槽函數實現
//有新客戶端連接時
void Server::newConnectionSlot()
{
//返回套接字指針
currentClient = tcpServer->nextPendingConnection();
tcpClient.append(currentClient);
ui->comboBoxIP->addItem(tr("%1:%2").arg(currentClient->peerAddress().toString().split("::ffff:")[1])\
.arg(currentClient->peerPort()));
//讀取消息處理
connect(currentClient, SIGNAL(readyRead()), this, SLOT(readMessageData()));
}
2.接收來自客戶端的信息並顯示出來
//接收消息並顯示到界面
void Server::readMessageData()
{
for(int i = 0; i < tcpClient.length(); i++)
{
QByteArray buffer = tcpClient.at(i)->readAll();
if(buffer.isEmpty())
{
ui->textEditStatus->append("接收的消息爲空!");
}
else
{
ui->textEditAccept->append(buffer);
ui->textEditStatus->append("接收消息成功!");
}
}
}
3.往客戶端發送信息,這裏有兩種可能,一是隻要連接上的客戶端都發,二是指定客戶端來發送,就是綁死客戶端的IP地址。
//往客戶端發送信息
void Server::on_buttonSendMessage_clicked()
{
QString input_data = ui->textEditInput->toPlainText();
if(input_data.isEmpty())
{
ui->textEditStatus->append("不能發送空的信息!");
return;
}
//如果選擇全部發送信息
if(ui->comboBoxIP->currentIndex() == 0)
{
for(int i = 0; i < tcpClient.length(); i++)
{
tcpClient.at(i)->write(input_data.toLatin1());
ui->textEditStatus->append("信息發送成功!");
ui->textEditInput->clear();
input_data.clear();
}
}
//指定接收的客戶端
else
{
//得到選擇的IP地址
QString client_IP = ui->comboBoxIP->currentText().split(":").at(0);
//得到端口
int client_port = ui->comboBoxIP->currentText().split(":").at(1).toInt();
//遍歷連接到的客戶端
for(int i = 0; i < tcpClient.length(); i++)
{
if(tcpClient[i]->peerAddress().toString().split("::ffff:")[1]==client_IP\
&& tcpClient[i]->peerPort()==client_port)
{
tcpClient.at(i)->write(input_data.toLatin1());
ui->textEditStatus->append("發送信息到:"+client_IP+"成功!");
//ui->textEditInput->clear();
input_data.clear();
return; //ip:port唯一,無需繼續檢索
}
}
}
}
測試
運行服務器與客戶端,並點擊監聽與連接,開始互發信息
運行效果如下:
以上是就是一個服務器與客戶端的初步框架,還缺少了互相傳送圖像,上傳下載文件這兩個功能,還有異常處理機制,心跳檢測,多線程等需要完善。