在 TCP/IP Sockets打开之前,一个与Socket Server的会话必须已经建立。这是Socket连接初始化阶段的唯一要求。消息通道的数量可以传递到方法中,这个数量标示了最多可有有多少个异步的操作允许在任何时候运行。这个默认值是KESockDefaultMessageSLots=8;如果值太小的话,可能会返回KErrServerBusy错误值。一个合理的信道数量值应该是N+2,N是当前的数量。初始化函数创建一个会话到Socket Server:
void CTcpIpSocketServerEngine::InitializeL()
 ...{
User::LeaveIfError( iServerSocket.Connect() );
}
在初始化只有,这个Socket就算是打开了。一个Socket可以以两种方式打开,空的Socket或是带着特殊协议的Socket。空白的Socket在连接到匹配的client之前不能使用数据传递,使用Accpt()来接收Client的连接。当打开Socket时,它的类型和角色必须要确定,角色当然就是指Server或者Client了。作为Server,两个Socket都需要打开,一个用来监听连接请求,另一个是空白Socket,用来传递数据给Client。
void CTcpIpSocketServerEngine::OpenL()
 ...{
TInt result;
if ( iSocketRole == EClient )
 ...{
result = iSocket.Open( iServerSocket, KAfInet,
KSockStream, KUndefinedProtocol);
User::LeaveIfError( result );
}
else
 ...{
result = iListernerSocket.Open( iServerSocket,
KAfInet, KSockStream, KUndefinedProtocol );
User::LeaveIfError( result );
result = iSocket.Open( iServerSocket );
User::LeaveIfError( result );
}
}
Socket的构造依赖与Socket的类型和角色。一个无连接的Socket很容易构造,本地地址使用Bind()简单地指派,客户端的Socket流类型必须使用Connect()指派远程Socket的地址。
void CTcpIpSocketServerEngine::ConfigureL()
 ...{
if ( iSocketRole == EClient )
 ...{
TInetAddr serverAddr( INET_ADDR(127,0,0,1), KServerPort );
iSocket.Connect( serverAddr, iStatus );
}
else
 ...{
TInetAddr anyAddrOnServerPort( KInetAddrAny, KServerPort );
iListenerSocket.Bind( anyAddrOnServerPort );
// Set up a queue for incoming connections
iListenerSocket.Listen( KQueueSize );
// Accept incoming connections
iListenerSocket.Accept( iSocket, iStatus );
}
SetActive();
}
不同类型和角色Socket使用不同的函数来收发数据:数据包Socket使用SendTo ()和RecvFrom(),而流Socket使用Send()和Recv()。流Socket还有不同版本的Send()和Recv()重载函数提供使用。所有的函数都带一个Buffer作为参数来发送或者读取。
需要注意的是,在串行通信中,数据经常是传递8-bit bytes,甚至在Unicode系统里也这样。一个可选的参数可以用来设置传递的标志,比如这是紧急的数据;另一个参数是发送读取的长度。在很多情况下,人们使用计时器来防止万一无限制的等待读取或者发送。
void CTcpIpSocketServerEngine::Receive()
 ...{
if ( !iSocketRxAO->IsActive() )
 ...{
iSocketRxAO->Recv();
}
}
void CRecSocketAO::Recv()
 ...{
if (!IsActive())
 ...{
iSocket.RecvOneOrMore( iBuffer, 0, iStatus, iRecvLen );
SetActive();
}
}
使用完Socket需要对它进行关闭Close(),在关闭之前,所有未完成的异步操作都应该取消,使用CancelAll()可以取消所有的操作包括(read,write,input-output control,connect and accept)除非是关闭等不能取消的操作。虽然Close()是同步的方法,但它在socket的input和output都停止的情况下调用异步的Shutdown()方法来异步的关闭Socket。
因为有大量通信软件使用了纯C的,Symbian OS也有一套BSD4.3Sockets的实现叫做LIBC,这就方便了移植通讯软件到Symbian上,因为Symbian可以使用C语言实现的通信引擎。LIBC库包含一个标准TCP/IP库,包括ARP(address resolution protocol)、RARP(reverse address resolution protocol)、IP(Internet Protocol)、ICMP(Internet control messages protocol)、TCP(transmission control protocol)和UDP(user datagram protocol)
另外在数据传输过程中,Sockest可能需要使用其他服务,比如Host-name Resolution和Device Discovery。RHostResolver类提供了Host-name Resolution域名解决方案。RSocket也是一样的。Host-name Resolution用在以下四种服务:获取某个地址的域名或者通过域名来获取地址,还可以来设置和获取本机的主机名。
实际上的具体服务和协议是相关的,TCP/IP Sockets需要通过DNS(Domain Name Service)来转换文本地址和数字IP地址,lrDA的域名解析需要和附近的设备来收发请求获取。 |