首 页 | 新 闻 | Symbian | Windows Mobile| J2ME | 下载中心 | 游戏策划 | 购书指南 | 移动开发视频教程
您现在的位置: 开发视界 >> 专家专栏 >> 新鲜的Lychee >> 文章正文
利用 RSocket::Read() 函数读取给定数据的字节数
作者:lychee08…    文章来源:本站原创    更新时间:2006-7-19 10:39:32

我们经常需要从网络中读取给定数据的字节数。例如,读取消息头可以得知消息体长度,Symbian RSocket提供了两组读取方法,RecvOneOrMore()和Recv()/Read(),前者用于尽快读取并返回模式,后者用于缓冲描述符的最大长度被填满阻塞模式。两种模式都可以完成需求。利用RecvOneOrMore(),可以通过循环不断读取并计数返回字节数直到计数和不超过所要求的信息长度。很明显,这种方法不够高效,更好的方法为将最大长度赋值给描述符,通过一次调用Recv()/Read()就可以完成。举例如下:
RSocketServ socketServ;
RSocket socket;
RSocket listener;
User::LeaveIfError(socketServ.Connect());
CleanupClosePushL(socketServ);
User::LeaveIfError(listener.Open(socketServ, KAfInet,KSockStream, KProtocolInetTcp));
User::LeaveIfError(listener.SetLocalPort(80)); 
User::LeaveIfError(listener.Listen(1));
TRequestStatus status;
TBuf8<256> buffer;
socket.Open(socketServ);
listener.Accept(socket, status);
User::WaitForRequest(status);
......
TBuf8<256>data;
socket.Read(data,status);
User::WaitForRequest(status);
......

监听器对象监听80端口,一旦要接受连接,另一个RSocket对象正如最后三行所示准备从网络中读取数据。这里,代码运行后,可以读取256字节。

这并不是最后,因为在编程时并不知道一定是256字节。要读取的数据字节只有在运行时可知。但是基于描述符TBuf栈的大小是在编译前设置的。很遗憾,在SDK文档或google中并没有找到解决该问题的实例代码。我试图用基于HBufC的堆来代替,其大小可以在运行时设置, 但HBufC是不可以修改的。但是RSocket::Read方法要求可修改的描述符。这可以通过HBufC::Des().方法来修改。《如何得知描述符类型》一文中很好的给出了关于Symbian系统的描述符系统的介绍。代码修改后如下:
TPtr8 gDataPtr(NULL,0);
UInt32 msglen;
//... assign value to msglen ...
HBufC8* buffer = HBufC8::NewL(msglen);
gDataPtr.Set(buffer->Des());
socket.Read(gDataPtr,status);
User::WaitForRequest(status);

代码执行正如所期待的,但是这就是正确的吗?有时程序会永远堵塞,这时我花费了一天的时间来查找原因。例如,当msglen值为137时,并跟踪buffer->Des().MaxLength() 所赋予的新值,就会得到140!RSocket::Read方法只见查最大长度并试图填满。它会持续等待根本不存在的三个字节,即使所要求的137已经被接收。

为何最大长度是140而不是所要求的137?因为正如描述符细节中的Tip9所阐述的“HBufC堆单元的最大长度是用来设置返回 TPtr的最大长度”。堆单元的大小只能通过授权,其中包含用户给定的大小,但是不是相等的!137不是整数边界,所以用140代替。

不能想象Symbian描述符系统对于该简单问题没有提供解决方法来满足RSocket::Read方法的要求。我已经犹豫不再挖掘该问题了,最终选择非Symian1方式,采用C类型数列。
TUint8 *buf=new TUint8[msglen];
gDataPtr.Set(buf,0,msglen);
blank.Read(gDataPtr,status);
User::WaitForRequest(status);
当然必须注意自己将数列空间释放掉。如果某位Symbian专家能提供解决该问题的方法将不甚感激。在我要删除SymbianSDK并按转Jave和.net两个文件之前,不得不解释到此了。

此文为开发视界翻译转载者请注明出处否则追究法律责任

相关文章:
遍历Symbian某目录下的所有文件
在P800/P910中找回已拨打号码
编程IrComm3 原始通信
虚拟机模型
Symbian sdk帮助-类TDes8
Graphics(5)