一个简单的文件传输验证码识别C/S实现(2)

基于Qt写的,此处摘写代码片段。

1)、读文件封装数据 int QEasyWrapper::wrap(char *buf, std::size_t maxlen) { memset(buf,0,maxlen); QFile f(fPath_.c_str()); f.open(QIODevice::ReadOnly); QByteArray ba=f.readAll(); std::cout<<ba.size()<<"cont:"<<std::endl; f.close(); if(0>= ba.size()){ std::cout<<"file open err"<<std::endl; return -1; } sprintf(buf,"%s%c%d%c",fName_.c_str(),sep_,ba.size(),sep_); int headLen=strlen(buf); int cpyLen=std::min<int>(maxlen,ba.length()+headLen); memcpy(&buf[headLen],ba.data(),cpyLen); std::cout<<"headLen"<<headLen<<";wholeLen:"<<cpyLen<<std::endl; return cpyLen; } 2)、利用QTcpSocket进行数据的传输与接收

发送:

int TcpFileSender::write(char *buf, std::size_t len) { int sndLen=sock->write(buf,len); std::cout<<"waitforwrite:"<<sock->waitForBytesWritten(5000)<<std::endl; std::cout<<"len:"<<len<<";sndLen:"<<sndLen<<std::endl; return sndLen; }

接收:

int TcpFileSender::read(char *buf, std::size_t buflen) { std::cout<<"waitforread:"<<sock->waitForReadyRead(5000)<<std::endl; if(rcvBuf_.size()<1 || buflen<1) return 0; QByteArray ba=sock->readAll(); std::cout<<"rcv:"<<ba.size()<<";"<<ba.data()<<std::endl; int cpyLen=std::min<std::size_t>(buflen,ba.size()); memcpy(buf,ba.data(),cpyLen); return cpyLen; } tips

QtcpSocket在使用过程中 发送后与接收前一定要成套调用waitfor相关的函数
如果不调用,发送之后立即调用接收的读相关函数,接收到的将是空,因为write和read 这2个接口是非阻塞的,直接执行,发还没发完呢就开始读了,当然收不到数据。当然,用connect将ReadyRead信号绑定到一个函数进行接收是可以收到数的。

还有一种情况,write之后未加waitfor,read之前加了waitfor,会报超时。因为你发的时候直接就返回,未等待其执行完毕,然后调用waitForReadyRead,直接将socket阻塞掉了,相当于发了一半被waitForReadyRead阻塞了,服务端未收齐数据自然不会回复。这样最终就超时了。

针对这个细节,个人理解,QTcpSocket底层做了一个“线程”封装进行数据的收发,waitFor相关函数会阻塞此线程。而且直接在主线程中调用Sleep也是不行的。此“线程”还非彼线程,会随主线程一起被阻塞。待有机会再研究下。欢迎熟悉底层或者源码的同学拍砖指正。
:)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/8ee8ca25e2f6926f95452a07be7cbcc3.html