Symbian编程总结-网络与通信-套接字(1)-套接字体系结构与相关API
本文章由杨芹勍原创,如需转载请注明出处。谢谢!
套接字编程在网络与通信中起着举足轻重的作用。套接字的API最初为方便在BSD Unix中建立TCP/IP的连接而设计的,现在已经成为多种平台(包括Symbian)建立TCP/IP连接的标准API。除了TCP/IP外,套接字API足以通用于其他对应的网络类型和协议。Symbian利用了这个事实,可以使用套接字API在红外线、蓝牙等协议上建立连接。本系列将从网络套接字入手,概述套接字编程的核心实质,同时以大家熟知的.net Socket编程作为参照物,介绍Symbian中的套接字编程。
一、Symbian OS 套接字体系结构
1、客户机/服务器模式
Symbian OS的套接字是基于客户机/服务器(C/S)模式的。这一点可以从套接字编程中使用到的以下几个类体现:RSocketServ、RSocket、RConnection。RSocketServ派生自RSessionBase,作为与系统服务器通信的父会话;RSocket和RConnection都派生自RSubSessionBase,作为RSocketServ的子会话与系统服务器通信。简单的说,要想进行Socket编程,必须得通过RSocketServ连接系统的套接字服务器。有关Symbian OS的客户机/服务器框架的只是,请参阅“深入篇-客户机/服务器框架系列”文章。
2、客户端的套接字与服务器端的套接字
这里的“客户端”、“服务器端”与Symbian OS的“客户机/服务器”不是一个概念。这里的“客户端”、“服务器端”指的是在网络中两个互相暴露的两个连接的端点。Socket服务器端被动等待Socket客户端的连接,反过来,Socket客户端主动请求与Socket服务器端连接。一旦连接完毕,两个端点就可以向对方发送或接收数据。
3、面向连接的套接字和面向无连接的套接字
在此所说的面向连接的套接字为TCP模式,而面向无连接的套接字为UDP模式。有关TCP和UDP的相关知识,请参阅《TCP/IP详解》第二卷的相关章节。
4、异步套接字与同步套接字
在.net中,Socket类的许多操作都对应有同步版本和异步版本,如:Accept与BeginAccept、EndAccept,Receive与BeginReceive、EndReceive等等。而在Symbian中,RSocket提供的对应方法都为异步函数,我们可以使用活动对象或者User::WaitForRequest方法进行封装调用,请参阅“活动对象正解(4)-异步函数的同步调用 ”。下面例举几个异步方法的原型:
IMPORT_C void Send(const TDesC8& aDesc,TUint someFlags,TRequestStatus& aStatus); IMPORT_C void Recv(TDes8& aDesc,TUint flags,TRequestStatus& aStatus); IMPORT_C void Accept(RSocket& aBlankSocket,TRequestStatus& aStatus);
二、Socket编程流程及相关API
一般情况下,我们会在手机上建立客户端的套接字,去连接远程服务器端的套接字,而且使用的是TCP方式连接。所以,在此我们将以客户端的TCP Socket编程作为入手点,简单介绍Socket编程流程。
首先先用时序图描述一下具体流程:
接下来简单的介绍相关API:
- 连接套接字服务器:RSocketServ::Connect()
此函数返回错误代码,由于套接字服务器可能已经连接,所以此处可能返回KErrAlreadyExists,应该使用如下方法进行判断:
TInt err = iSocketServ.Connect(); if (err != KErrNone && err != KErrAlreadyExists) { User::Leave(err); } - 打开套接字:RSocket::Open()
IMPORT_C TInt Open(RSocketServ& aServer,TUint addrFamily,TUint sockType,TUint protocol);
第一个参数传入套接字服务器,后面几个参数表示连接模式的常量。针对于TCP连接,应该使用如下代码:
iSocket.Open(iSocketServ, KAfInet, KSockStream, KProtocolInetTcp);
如果记不住每种连接模式对应这三个参数的值,还可以通过使用RSocketServ::FindProtocol的方法,传入模式名称获取一个TProtocolDesc对象,在这个对象中描述了对应的addrFamily、socketType、protocol的值。具体用法请参看SDK。 - 将网络端点表示为 IP 地址和端口号:TInetAddr
TInetAddr类似于.net中的IPEndPoint类。使用TInetAddr::Input方法传入IP地址,使用TInetAddr::SetPort方法传入端口号。 - 连接服务器端Socket:RSocket::Connect
此方法为异步函数,原型如下:
IMPORT_C void Connect(TSockAddr& anAddr,TRequestStatus& aStatus);
其中参数anAddr为我们创建的绑定远程服务器IP地址和端口的TInetAddr类实例。 - 向服务器端发送数据:RSocket::Send
此方法为异步函数,原型如下:
IMPORT_C void Send(const TDesC8& aDesc,TUint someFlags,TRequestStatus& aStatus); - 接收服务器端返回的数据:RSocket::Recv
此方法为异步函数,原型如下:
IMPORT_C void Recv(TDes8& aDesc,TUint flags,TRequestStatus& aStatus);
三、小演练:连接服务器端的套接字
1、在此我们使用C#建立一个TCP套接字服务器端,将完成以下几点功能:
- 监听IP 127.0.0.1和端口8532,等待客户端的连接;
- 客户端连接后,在屏幕上打印出客户端的IP地址和端口;
- 等待客户端发送文本数据;
- 收到数据后将数据内容打印到控制台上;
- 将收到的数据返回给客户端。
2、使用Symbian C++建立一个TCP套接字客户端,完成以下几点功能:
- 运用我们以上学到的几个API,连接IP 127.0.0.1和端口8532;
- 向服务器发送字符串“12345678”;
- 等待服务器端返回数据;
- 将服务器端返回的数据(12345678)打印到屏幕上。
客户端和服务器端运行效果如下:
四、小结
这一节作为Socket编程的入门,所涉及的知识点比较少且相对较简单,在下一节里我将详细介绍RSocketServ、RSocket、RConnection的使用方法,并针对TCP、UDP方式进行说明。
五、参考文献
- Series 60 应用程序开发