非常簡(jiǎn)單的代碼,實(shí)現(xiàn)了基本功能,不過(guò)還是嘗試過(guò)一些彎路的,在此記錄一下。
服務(wù)端選擇NodeJS,因?yàn)槭乾F(xiàn)在的主流,容易開發(fā)和部署??蛻舳耸褂肣T5的VS版本,易于開發(fā)用戶界面。
1、服務(wù)端代碼:
var net = require('net');
var chatServer = net.createServer();
chatServer.on('connection', function(client) {//連接
client.on('data', function(data) {//客戶端發(fā)送數(shù)據(jù),服務(wù)端接收數(shù)據(jù)同時(shí)向客戶端返回一些數(shù)據(jù)
console.log('data: ' + data);
// 這里進(jìn)行各種處理
client.write('Hello, ' + data);
});
});
chatServer.listen(8800);//服務(wù)器啟動(dòng),監(jiān)聽端口
沒有過(guò)多可說(shuō)的,網(wǎng)上一大堆例子。我還沒有處理斷線動(dòng)作,沒有處理error,只是實(shí)現(xiàn)了最基本的連接及與客戶端互相通信。
需要注意的是服務(wù)器可能限制了端口,如果是linux服務(wù)器,需要查看并設(shè)置iptables(Centos7沒有使用iptables,而要設(shè)置firewalld防火墻)
2、客戶端代碼:
void my_client::on_login_button_clicked()
{
bool is_connected = true;
if (NULL == tcp_socket)
{
tcp_socket = new QTcpSocket(this);
tcp_socket->abort();//網(wǎng)上統(tǒng)一都有這么一句,我也不知道原因,沒有深究
tcp_socket->connectToHost(server_ip, server_port.toInt(), QTcpSocket::ReadWrite);
connect(tcp_socket, SIGNAL(readyRead()), this, SLOT(readMessage()));
is_connected = tcp_socket->waitForConnected();
}
if (is_connected)
{
QString client_msg("{\"name\":\"" + usr_name + "\",\"pwd\":\"" + usr_pwd + "\"}");//JSON字符串,我還沒有開始用QT自帶的JSON,先這樣臨時(shí)處理一下
tcp_socket->write(client_msg.toStdString().c_str());
tcp_socket->waitForBytesWritten();
}
else
{
QMessageBox::about(NULL, QStringLiteral("連接"), QStringLiteral("連接") + "\nname:" + usr_name + "\nip:" + server_ip);//QStringLiteral是個(gè)用于在QT界面顯示中文的宏,否則會(huì)顯示亂碼。我試用了設(shè)置全局編碼沒有成功。
}
}
void my_client::readMessage()
{
QString server_msg = tcp_socket->readAll();
QMessageBox::about(NULL, QStringLiteral("連接成功"), QStringLiteral("連接成功") + "\nmsg:" + server_msg);
}
這個(gè)還是踩了幾個(gè)坑的。
(1)要在依賴中添加庫(kù)。Properties->Linker->Input->Additional Dependencies,添加Qt5Networkd.lib。這是指在vs下,創(chuàng)建項(xiàng)目時(shí)沒有選擇添加網(wǎng)絡(luò)依賴的情況。在創(chuàng)建新項(xiàng)目時(shí),如果選擇了網(wǎng)絡(luò)依賴,這里就不用改了。如果是非vs,修改系統(tǒng)文件,網(wǎng)上可以找到方法。如果不這么做,會(huì)有無(wú)法解決external link的情況。
(2)socket連接之后,要使用如下代碼進(jìn)行信號(hào)和槽的連接:
connect(tcp_socket, SIGNAL(readyRead()), this, SLOT(readMessage()));
這里有一個(gè)小坑,就是在頭文件定義readMessage()時(shí),需要明確添加slots宏,像這樣:
private slots:
void readMessage();
否則會(huì)無(wú)法正確觸發(fā)。
(3)接收數(shù)據(jù)在網(wǎng)上有幾種方法,我分別嘗試后,只有這種方法成功了:
QString server_msg = tcp_socket->readAll();
其它方法大概還是我沒設(shè)置好,沒有仔細(xì)研究。
不管怎么說(shuō),目前可以做到客戶端和服務(wù)器間互相收發(fā)消息,算是最最基本的通訊功能實(shí)現(xiàn)了,后續(xù)可以開始做框架設(shè)計(jì)、業(yè)務(wù)性開發(fā)、優(yōu)化等等工作了。