使用 RSocket 出现过的几个问题,总结如下:
1. RSocket 提供了好几个 Recv,Read, RecvOneOrMore 等函数来接收数据,如:void Read(TDes8& aDesc,TRequestStatus& aStatus);
SDK DOC 上描述如下,
For a stream-interfaced sockets, the function only completes when the full amount of requested data has been received (or the connection breaks). This means when the descriptor has been filled to its maximum length (not its current length). For a connection-oriented datagram-interfaced, the function completes when a datagram arrives even if it is not sufficient to fill the buffer.
函数返回有两种情况,第一是缓冲区被填满,第二是没有数据可以接收。这里有一个特别需要注意的地方,当缓冲区被填满返回时, aDesc 的 Length 等于它的 MaxLength; 但当没有数据可以接收使函数返回时, aDesc 的 Length = 0, 但它里面可能实际已经有数据了;这个时候如果不用 SetLength 改变 aDesc 的长度,当你把缓冲写文件或者用 aDesc[index] 访问缓冲区时会出错。针对这种情况建议使用 void RecvOneOrMore(TDes8& aDesc,TUint flags,TRequestStatus& aStatus,TSockXfrLength& aLen); 该函数返回接收到的数据的长度,可以在返回用利用 aLen 重新给 aDesc 来 SetLength.
注意,这些函数 aStatus 当返回 -25 ( KErrEof) 时,表示 no more data is available for reading ,或者网络已断。
2. Symbian emulator 对 TCP/Socket 的支持并不是很好, emulator 使用的是 ethernet 的网络环境,并没有很好的模拟无线网络环境,所以比如当我们实现 http 的客户端进行下载时,远端的 web server 是把 emulator 当做一台 pc 终端来发送数据的,很容易就使 Socket server crash, 这时候得到的错误是 -15 ,表示 socket server terminate; 如果把程序放到真机上运行,则会是正常的。所以当实现这种和网络环境有很大关系的程序时,不要太依赖 emulator, 很多时候需要在真机上调试,测试。
3. 现在的 Mobile network 采用的分配 IP 的方式类似 internet 的 DHCP 方式, IPV6 还没有广泛应用,移动网络也还没有完全采用 MOBILE ip 技术,所以当你通过 GPRS 等无线网络联网时,每次得到的也许是不同的 IP 地址,那当你写 SOCKET 的 CLIENT&SERVER 程序时就会出现问题(如果程序都是在手机上运行)。通常采用的方式是用模拟器,可以在两台机器上运行两个模拟器给他们分配固定的 IP 地址,这样就可以通信了。还有一种方法就是在一台机器上运行一个 VMWARE 虚拟机(装有 SYMBIAN SDK ),这样你就可以在一台机器上调试了;两种方法的本质是一样的,就是利用模拟器,但这时又需要注意以上的 2 中描述的问题了。
4. Symbian 的 RSocket 提供的 API 是支持异步的,一般结合 Active object 一起使用,但有时并不利于我们实现程序,可以把它实现成同步的,以利于逻辑的实现和清晰。如:
TRequestStatus status;
iSocket.Connect(iAddress, status);
User::WaitForRequest(status);
以上是我使用 RSocket 时的一点总结,有的是我查了很久才找出的 BUG ,总的感觉就是切忌想当然,尤其在 SYMBIAN 下,比如问题 1 ,我一开始就不知道 aDesc 在实际有数据的情况下长度还会是 0 ,结果为此调试了很久。
