qt 實現簡單聊天(一個服務器和多個客服端)
阿新 • • 發佈:2018-02-27
qt源碼地址:https://github.com/haidragon/easyChat
思路 :
思路 :
-
一個服務器一直接聽某個 ip 的某個端口
listen(QHostAddress::Any,port);
2.一個服務器有一個容器保存所有各客服端的鏈接(每個鏈接都是一個類)。QList<TcpClientSocket> tcpClientSocketList;每當一個客服端鏈接上那個服務器一直接聽的套節字時。服務器會自動調用一個函數。incomingConnection(qintptr socketDescriptor);(這個函數是繼承過來的虛函數)
3.每次調用鏈接函數時 new 一個新的客服端流(也就是另外增加一個類。這個類就是客服端流類)TcpClientSocket
4.服務器管理所有的服端流。
5.每次新創建一個客服端流時會往流裏寫入鏈接成功的數據。//鏈接後就往套節字裏發內容 void TcpClient::slotConnected() { sendBtn->setEnabled(true); enterBtn->setText(tr("離開")); int length=0; QString msg=userName+tr(":Enter Chat Room"); if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length()) { return; } }
6.由於每個客服端流是分開的只有服務器能夠知道所有流裏的數據。因此每當有客服端流中有數據時在服務器中會發給其它客服端流。其它客服端流只要流中有數據會一直更新。實現了簡單群聊。
void Server::updateClients(QString msg,int length) { emit updateServer(msg,length); //這裏是往每個鏈接裏與 for(int i=0;i<tcpClientSocketList.count();i++) { QTcpSocket *item = tcpClientSocketList.at(i); if(item->write(msg.toLatin1(),length)!=length) { continue; } } }
7.服務器端也實現了 ui 見面
8.每個客服端只要斷開鏈接。它就會在這個流中發一個斷開信號。因為服務器保存了每個客服端的流。當某個客服端流斷開時會發一個斷開信號同時帶上標誌。服務器只要檢測到了這個信號會及時處理。else { int length=0; QString msg=userName+tr(":Leave Chat Room"); if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg. length()) { return; } tcpSocket->disconnectFromHost(); status=false; } ///////// tcpclientsocket類 void TcpClientSocket::slotDisconnected() { emit disconnected(this->socketDescriptor()); } ///server類 void Server::slotDisconnected(int descriptor) { for(int i=0;i<tcpClientSocketList.count();i++) { QTcpSocket *item = tcpClientSocketList.at(i); if(item->socketDescriptor()==descriptor) { tcpClientSocketList.removeAt(i); return; } } return; }
qt 實現簡單聊天(一個服務器和多個客服端)