目標,qt程式作為用戶端,windows下winsock作為伺服器端,實現兩端通訊。
開始時寫了一個小函數測試:
QTcpSocket tmpSock;<br />tcpSock.connectToHost("59.64.159.87",7716);<br />tcpSock.write(buf,strlen(buf)+1);<br />msleep(3000);<br />tcpSock.disconnect();<br />
測試結果發現用戶端只能串連到伺服器端,而伺服器端收不到用戶端的訊息。
初步揣測也許是Qt的socket機制使得socket緩衝隊列沒有即時發送。
換另一方法:
QTcpSocket tmpSock;<br />char* buf ="hello";<br />tcpSock.connectToHost("59.64.159.87",7716);<br />tcpSock.write(buf,strlen(buf)+1);<br />msleep(3000);<br />tcpSock.disconnect();
運行後,發現結果仍然不對。開始思考Qtsocket通訊機制。想到這有可能是因為Qtcpsocket是非阻塞的方式引起的。
在網上尋找,發現了一些資料。
QTcpSocket因為繼承自QAbstractSocket,所以如果不採取一些措施的話,他就處於非阻塞方式,也就是事件編程,這有個好處就是可以在一個線程中實現多路tcp連結,節省資源,但是這種方式的編程難度比較大。
對於初涉這方面的朋友來說還不太適合,所有在滿足要求的情況下還是阻塞方式的socket編程比較容易理解,QAbstractSocket裡面提供了幾個函數用於阻塞方式編程,利用好它就可以簡單的編寫出網路應用了:
- waitForConnected() 等待連結的建立
- waitForReadyRead() 等待新資料的到來
- waitForBytesWritten() 等待資料寫入socket
- waitForDisconnected() 等待連結斷開
當接收資料時,我們有個模式可以遵循:
while (socket.bytesAvailable() < (int)nSize) {<br /> if (!socket.waitForReadyRead(Timeout)) {<br /> emit error(socket.error(),<br />socket.errorString());<br /> return;<br /> }<br /> }
這段話的主要意思就是等待nSize個數的到來,這是個一定要遵守的接收資料範本,可以把它寫成一個內嵌函式,如果段話滿足條件,就可以容read讀數了。
寫數的話調用write,之後調用waitForBytesWritten來確定資料是否寫完。
然後修改原來的代碼。
QTcpSocket tmpSock;<br />char* buf ="hello";<br />tcpSock.connectToHost("59.64.159.87",7716);<br />tcpSock.write(buf,strlen(buf)+1);<br />if(tcpSock.waitforreadyread(3000))<br /> emit SockCondition("successful");<br />else<br /> emit SockCondition("failed");<br />tcpSock.disconnect();
運行測試成功