• 33517阅读
  • 7回复

如何正常关闭QTcpsocket?我觉得很难协调好客户端和服务端的关闭操作 [复制链接]

上一主题 下一主题
离线iiiyyyhhhsss
 

只看楼主 倒序阅读 楼主  发表于: 2010-03-22
— 本帖被 XChinux 从 General Qt Programming 移动到本区(2011-01-02) —
如果在客户端:

this->tcpSocket->write(str->toAscii());
this->tcpSocket->close();


对于以上的代码,我有两个问题:

第一:

虽然是先write后close,但是网络传输不能确保write的数据比close的信息先到达目的主机,可能导致目的主机的socket还没有接收完数据,就被close了


第二:

即时write的数据全部比close信息先到达目的主机,但通常我们用readAll()或者其它的函数去读取接收的数据,如果由于服务器正忙,readAll()函数被延迟了,

在readAll()之前close()信息到达,那么,我们readAll()得出的数据还是空的...


我不理解tcp协议在QTcpSocket里是如何运作的?

我们tcpSocket->write()后,如何得知目的主机已经接收到所有数据?  好让我们关闭socket?
[ 此帖被iiiyyyhhhsss在2010-03-22 12:57重新编辑 ]
离线ker704334
只看该作者 1楼 发表于: 2010-03-22
在tcpSocket->write()之后
可以使用
tcpSocket->waitForBytesWritten()
来让write()动作完全被执行
离线iiiyyyhhhsss

只看该作者 2楼 发表于: 2010-03-22
引用第1楼ker704334于2010-03-22 13:44发表的  :
在tcpSocket->write()之后
可以使用
tcpSocket->waitForBytesWritten()
来让write()动作完全被执行



我试过了,不行,

但我这里问题的关键,  不是检测数据有没有完全发送出去,

而是检测数据有没有完全达到目的主机...
离线iiiyyyhhhsss

只看该作者 3楼 发表于: 2010-03-22
谁有标准的多线程QTcpServer和客户端的程序代码借鉴借鉴?

qt自带的例子里,有一个多线程的,但是没有客户端,弄不懂它们是如何处理关闭过程的...
离线318065268
只看该作者 4楼 发表于: 2010-03-22
非常感谢二楼的!
正巧让我一个很棘手的问题得到了很好的解决!

对于楼主的问题,可以使用这个函数:
myClient->disconnectFromHost();
Qt的例子里面有这段话:
which will close the connection after QTcpSocket has finished writing the fortune to the network. Because QTcpSocket works asynchronously, the data will be written after this function returns, and control goes back to Qt's event loop. The socket will then close。
也就是说,和服务器连接的断开会在发送完数据之后进行。
如果我们加了这样一个槽函数:
connect(myClient, SIGNAL(disconnected()),myClient, SLOT(deleteLater()));
就能够避免出现内存泄漏。

其实Qt实现socket,按它说的,是异步的。也就是说,内部讲会新开线程实现的。是可能在你的函数结束后才发送数据的。所以如果我们再把网络发送做到一个线程里面,感觉是多此一举。
至于判断是否服务器收到了信息,这个底层的Socket编程应该有这样的规则,每次发送完之后,服务器端都会发送确认回执,握手-->传输-->回执,这是一个完整的过程。所以也不用担心Qt的程序不知道远程主机是否收到信息。
Email  rsail@126.com(私人邮箱)
QQ:   318065268
离线iiiyyyhhhsss

只看该作者 5楼 发表于: 2010-03-22
引用第4楼318065268于2010-03-22 17:14发表的  :
非常感谢二楼的!
正巧让我一个很棘手的问题得到了很好的解决!
对于楼主的问题,可以使用这个函数:
myClient->disconnectFromHost();
.......



我觉得你的观点,又很多漏洞:

例如,
第一:
既然说传输是异步的,那么,就是说客户端write()与服务器不是同步的,以下两个语句

tcpSocket->write();
tcpSocket->close();

close()被执行时,客户端应该是不知道服务器是否已经完全接收write()的数据的

第二:
通常服务器要同时处理多个连接的时候,一般是需要多线程的,而且是要我们写代码建立新的线程的,而不是qt内部已经封装分配了线程的
<<c++ gui programming with qt4 (2nd)>>书上第287页有这样说到的
离线318065268
只看该作者 6楼 发表于: 2010-03-22
close没有研究过,我也没说用close,例子中的这几行代码就可以了:
    tcpSocket.write(block);
     tcpSocket.disconnectFromHost();
     tcpSocket.waitForDisconnected();

楼上说的也有道理。那结合参考文档中的说法,应该是传输数据的进程和主界面的进程是分离的,这个不需要做更多的工作。但是如果没有多线程处理,传输数据的工作只能在那一个数据传输进程中排队进行了。这样可能更接近事实一些。
Email  rsail@126.com(私人邮箱)
QQ:   318065268
离线iiiyyyhhhsss

只看该作者 7楼 发表于: 2010-03-22
引用第6楼318065268于2010-03-22 18:17发表的  :
close没有研究过,我也没说用close,例子中的这几行代码就可以了:
    tcpSocket.write(block);
     tcpSocket.disconnectFromHost();
     tcpSocket.waitForDisconnected();
.......



验证过了 ,你的方法是正确的

而我的
    tcpSocket.write(block);
      tcpSocket.close()

是错误的

根据这里描述

void QAbstractSocket::disconnectFromHost ()
Attempts to close the socket. If there is pending data waiting to be written, QAbstractSocket will enter ClosingState and wait until all data has been written. Eventually, it will enter UnconnectedState and emit the disconnected() signal.

See also connectToHost().

只有当所有的数据write()完毕(即发送出去)后,关闭的信息才会发送出去

tcpSocket.waitForDisconnected();程序在这里阻塞了

thanks,这样的关闭是正常的
快速回复
限100 字节
 
上一个 下一个