把一個BREW上功能移植到Symbian平臺爲例,看一下具體的實現方式。由於網絡應用的重要地位,這裏先使用BREW3.x中ISockPort建立一個TCP的連接。首先,初始化服務器的地址:
pME->m_saSockAddr.wFamily = AEE_AF_INET;
pME->m_saSockAddr.inet.port = HTONS(SERVER_PORT);
INET_PTON(pMe->saSockAddr.wFamily, SERVER_ADDR, &(pMe->saSockAddr.inet.addr));
然後創建並打開ISockPort,
ret = ISHELL_CreateInstance(pME->m_pIShell, AEECLSID_SOCKPORT, (void**)&(pME->m_pISockPort));
ret = ISOCKPORT_OpenEx(pME->m_pISockPort, AEE_AF_INET, AEE_SOCKPORT_STREAM, 0);
接下來建立TCP連接,
ret = ISOCKPORT_Connect(pME->m_pISockPort, &pME->m_saSockAddr);
if (AEEPORT_WAIT == ret){
ISOCKPORT_WriteableEx(pME->m_pISockPort,&pME->m_cbWriteCallback, MyApp_TryConnect, pME);
return;
}
建立連接成功後,就可以從服務器讀寫數據了
ret=ISOCKPORT_Write(pME->m_pISockPort,pME->m_caWriteBuffer + pME->m_nBytesWritten, BUFFER_SIZE - pME->m_nBytesWritten);
// retry later
if (AEEPORT_WAIT == ret){
ISOCKPORT_WriteableEx(pME->m_pISockPort, &pME->m_cbWriteCallback, CApp_TryWrite, pME);
return;
}
最後,取消回調並釋放ISockPort接口。
CALLBACK_Cancel(&pME->m_cbReadCallback);
CALLBACK_Cancel(&pME->m_cbWriteCallback);
IBASE_Release((IBase*)(pME->m_pISockPort));
Symbian 是使用C++的,移植以上功能的時候,需要使用Symbian OS 中客戶端服務器框架。首先從 CActive 創建自己的對象:
#include <e32base.h>
#include <in_sock.h>
#include <es_sock.h>
class CTCPConnector : public CActive
{
private:
// these are some of the classes relevant to opening a TCP connection:
TInt iState;
RSocket iSocket;
RSocketServ iSocketServer;
RHostResolver iResolver;
TInetAddr iAddress;
…
}
然後定義服務方法
void CTCPConnector::MakeOutgoingConnectionL(const TDesC& aHost, TInt aPort){
...
iState = EGetByName;
iResolver.GetByName( /* parameters required for resolving a host */);
...
}
接下來實現建立連接的方法
void CSEIConnector::ConnectSocketL(void){
...
iSocketServer.Connect();
...
iSocket.Open(iSocketServer, KAfInet, KSockStream, KProtocolInetTcp);
...
iSocket.Connect(/*parameters required connecting */);
...
iSocket.Connect(iAddress, iStatus);
iState = ESocketConnect;
...
}
最後實現RunL() 來處理事件通知:
void CTCPConnector::RunL(){
TInt error = KErrNone;
switch(iState)
{
case EGetByName:
{
ConnectSocketL();
break;
}
case ESocketConnect:
{
Proce***equestL();
break;
}
}
}
在Symbian中的工作流程是這樣的,客戶端調用MakeOutgoingConnectionL(), MakeOutgoingConnectionL()首先發起 DNS 查詢,如果域名被成功解析,則開始調用CTCPConnector::RunL()。在CTCPConnector::RunL()中,先要檢查請求的狀態,如果當前狀態值是EGetByName就可以調用ConnectSocketL()了。在ConnectSocketL()中,要創建客戶端和服務器的類以及相應的RSocket 和 RSocketServer。最後,調用RSocket::Connect() 來創建正在的TCP連接,無論連接成功或者失敗,都將再一次運行RunL(),具體的數據讀寫過程以此類推。