Copy Link
Add to Bookmark
Report

6x01 Symbian Networking

eZine's profile picture
Published in 
phearless
 · 14 Jan 2024

                                 
...................
...::: phearless zine #6 :::...

.....................>---[ Symbian Networking ]---<......................

...........................>---[ by argv ]---<...........................
argv.cpp[at]gmail[dot]com

Sadrzaj:

[0] Intro
[1] Basics - Intro to Symbian TCP/IP
[2] TCP/IP - RSocket
[3] TCP/IP - Example
[4] Outro

////////////////////////////////////////////////////////////////////////////
--==<[ 0. Intro
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

U ovome tekstu cemo se bazirati na to kako da nas Symbian uredjaj spojimo na
racunalo preko TCP/IP sucelja koristeci Symbianove sockete. Mogucnosti su
velike - preko tih socketa mozemo kontrolirati odredjene radnje na racunalu,
mozemo ih koristiti za transfer fileova, etc. Da bi vidjeli to u praksi, ubacio
sam jedan jednostavni client/server program koji ce demonstrirati neke stvari
poput trazenja hosta preko IP-a ili hostnamea i transfer .sis fajlova.

////////////////////////////////////////////////////////////////////////////
--==<[ 1. Basics - Intro to Symbian TCP/IP
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

TCP/IP komunikacija se obavlja preko Symbianovog TCP/IP protokol modula -
tcpip.prt. Ovaj modul nam daje 4 protokola:

-IP (RFC791 Protokol)
-ICMP (RFC792, RFC950 Protokoli)
-TCP (RFC793 Protokol)
-UDP (RFC768 Protokol)

Protokolima se ne pristupa direktno vec kroz Symbian Socket API-je. Modul
takodjer daje DNS servis kojemu se takodjer moze pristupiti preko API interfacea
RHostResolver. Vjerujem da se sjecate ove klase iz prijasnjih tekstova.
Iako nije izlistano u protokolima gore, Symbian socket takodjer moze pristupiti
Dial-up i PPP protokolima: ali to cemo ostaviti za neki drugi put jer nam ne
treba ovdje.

////////////////////////////////////////////////////////////////////////////
--==<[ 2. TCP/IP - RSocket
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

Ovaj cu dio posvetit RSocketu i vecinom mogucnosti koje posjeduje.

RSocket nam daje podrsku za kreiranje socketa, pisanje, citanje, koristenje
pasivne ili aktivne konekcije, namjestanje adresa, etc...
Sa RSocketom se uvijek koristi RSubSessionBase koji nam daje "handle" za
RSocket funkcije.

RSocket sadrzi slijedece:
Accept(), Bind(), CancelAccept(), CancelAll(), CancelConnect(), CancelIoctl(),
CancelRead(), CancelRecv(), CancelSend(), CancelWrite(), Close(), Connect(),
EImmediate, ENormal, EStopInput, EStopOutput, GetDisconnectData(), GetOpt(),
Info(), Ioctl(), Listen(), LocalName(), LocalPort(), Name(), Open(), Read(),
Recv(), RecvFrom(), RecvOneOrMore(), RemoteName(), Send(), SendTo(), SetLocalPort(),
SetOpt(), Shutdown(), TShutdown, Transfer(), Write()

dok od RSubSessionBase nasljedjuje:
CloseSubSession(), CreateSubSession(), SendReceive(), SubSessionHandle()

-- Otvaranje i zatvaranje socketa:

Open()

TInt Open(RSocketServ& aServer,TUint addrFamily,TUint sockType, TUint protocol);
TInt Open(RSocketServ& aServer,const TDesC& aName);
TInt Open(RSocketServ& aServer);

Close()

void Close();

-- Dobivanje lokalne adrese i porta:

Bind()
TInt Bind(TSockAddr& anAddr);

SetLocalPort()
TInt SetLocalPort(TInt aPort);

LocalName()
void LocalName(TSockAddr& anAddr);

LocalPort()
TUint LocalPort();

-- Spajanje na drugi uredjaj:

Connect()
void Connect(TSockAddr& anAddr,TRequestStatus& aStatus);
void Connect(TSockAddr& anAddr,const TDesC8& aDataOut,TDes8& aDataIn,
TRequestStatus& aStatus);

CancelConnect()
void CancelConnect();

-- Slusanje i primanje konekcija:

Listen()
TInt Listen(TUint qSize);
TInt Listen(TUint qSize,const TDesC8& aDataOut);

Accept()
void Accept(RSocket& aBlankSocket,TRequestStatus& aStatus);
void Accept(RSocket& aBlankSocket,TDes8& aConnectData, TRequestStatus& aStatus);

CancelAccept()
void CancelAccept()

-- Dobivanje imena drugog uredjaja:

RemoteName()
void RemoteName(TSockAddr& anAddr);

-- Informacije o socketu

Info()
TInt Info(TProtocolDesc& aProtocol);

-- Opcije socketa

SetOpt()
TInt SetOpt(TUint anOptionName,TUint anOptionLevel,
const TDesC8& anOption=TPtrC8(NULL,0));
TInt SetOpt(TUint anOptionName,TUint anOptionLevel,TInt anOption);

GetOpt()
TInt GetOpt(TUint anOptionName,TUint anOptionLevel,TDes8& anOption);
TInt GetOpt(TUint anOptionName,TUint anOptionLevel,TInt& anOption);

-- Slanje podataka

Write()
void Write(const TDesC8& aDesc,TRequestStatus& aStatus);

Send()
void Send(const TDesC8& aDesc,TUint someFlags,TRequestStatus& aStatus);
void Send(const TDesC8& aDesc,TUint someFlags,TRequestStatus& aStatus,
TSockXfrLength& aLen);

SendTo()
void SendTo(const TDesC8& aDesc,TSockAddr& anAddr,TUint flags,
TRequestStatus& aStatus);
void SendTo(const TDesC8& aDesc,TSockAddr& anAddr,TUint flags,
TRequestStatus& aStatus,TSockXfrLength& aLen);

CancelWrite()
void CancelWrite();

CancelSend()
void CancelSend();

-- Primanje podataka

Read()
void Read(TDes8& aDesc,TRequestStatus& aStatus);

Recv()
void Recv(TDes8& aDesc,TUint flags,TRequestStatus& aStatus);
void Recv(TDes8& aDesc,TUint flags,TRequestStatus& aStatus,TSockXfrLength& aLen);

RecvOneOrMore()
void RecvOneOrMore(TDes8& aDesc,TUint flags,TRequestStatus& aStatus,
TSockXfrLength& aLen);

RecvFrom()
void RecvFrom(TDes8& aDesc,TSockAddr& anAddr,TUint flags,
TRequestStatus& aStatus);
void RecvFrom(TDes8& aDesc,TSockAddr& anAddr,TUint flags,
TRequestStatus& aStatus,TSockXfrLength& aLen);

CancelRead()
void CancelRead();

CancelRecv()
void CancelRecv();

-- Transfer Socketa

Name()
TInt Name(TName& aName);

Transfer()
TInt Transfer(RSocketServ& aServer, const TDesC& aName);

-- Prekidanje veze

Shutdown()
void Shutdown(TShutdown aHow,TRequestStatus& aStatus);
void Shutdown(TShutdown aHow,const TDesC8& aDataOut,TDes8& aDataIn,
TRequestStatus& aStatus);

GetDisconnectData()
TInt GetDisconnectData(TDes8& aDesc);

-- Prekidanje veze sa RSocket

CancelAll()
void CancelAll();

////////////////////////////////////////////////////////////////////////////
--==<[ 3. TCP/IP - Example
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

Evo jedan primjer koji ce u sebi objediniti vecinu funkcija iz prijasnjeg
poglavlja:

/////////////////
// Example.cpp //
/////////////////

#include "example.h"

const TInt KTimeOut = 30000000; // 30sec timeout

EXPORT_C CExample::CExample() : CActive(EPriorityStandard)
{
}

EXPORT_C CExample* CExample::NewL(MUINotify* aConsole)
{
CExample* self = NewLC(aConsole);
CleanupStack::Pop();
return self;
}

EXPORT_C CExample* CExample::NewLC(MUINotify* aConsole)
{
CExample* self = new(ELeave) CExample;
CleanupStack::PushL(self);
self->ConstructL(aConsole);
return self;
}

EXPORT_C void CExample::ConstructL(MUINotify* aConsole)
// otvaranje socketa
{
iConsole = aConsole;
iEngineStatus = EComplete;

iTimeOut = KTimeOut;
iTimer = CTimeOutTimer::NewL(EPriorityHigh, *this);
CActiveScheduler::Add(this);

// otvaranje kanala na socket server
User::LeaveIfError(iSocketServ.Connect());
// otvaranje TCP socketa
User::LeaveIfError(iEchoSocket.Open(iSocketServ, KAfInet, KSockStream, KProtocolInetTcp));

iEchoRead = CEchoRead::NewL(&iEchoSocket, aConsole);
iEchoWrite = CEchoWrite::NewL(&iEchoSocket, aConsole);
}

void CExample::DoCancel()
{
iTimer->Cancel();

switch (iEngineStatus)
{
case EConnecting:
iEchoSocket.CancelConnect();
break;
case ELookingUp:
iResolver.Cancel();
iResolver.Close();
break;
default:;
}
}

EXPORT_C void CExample::ConnectL(TUint32 aAddr)
// spajanje na Echo socket preko IPa
{
iAddress.SetPort(7);
iAddress.SetAddress(aAddr);
iEchoSocket.Connect(iAddress, iStatus);
iEngineStatus = EConnecting;
SetActive();
iTimer->After(iTimeOut);
}

EXPORT_C void CExample::ConnectL(const TDesC& aServerName)
// spajanje na Echo socket preko hostnamea
{
// DNS
User::LeaveIfError(iResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp));
// DNS ime
iResolver.GetByName(aServerName, iNameEntry, iStatus);

iEngineStatus=ELookingUp;
// timeout ako nema imena
iTimer->After(iTimeOut);
SetActive();
}

EXPORT_C void CExample::TestGetByAddr(TUint32 aAddr)
// trazenje hostnamea i zatim spajanje (ovo je proto, nece bit koristeno)
{
// DNS
User::LeaveIfError(iResolver.Open(iSocketServ, KAfInet, KProtocolInetUdp));
// DNS ime
iAddress.SetAddress(aAddr);
iResolver.GetByAddress(iAddress, iNameEntry, iStatus);

iEngineStatus=ELookingUp;
// time out
iTimer->After(iTimeOut);
SetActive();
}

EXPORT_C void CExample::Write(TChar aChar)
// pisanje
{
if ((iEngineStatus == EConnected) && !iEchoWrite->IsActive())
iEchoWrite->IssueWrite(aChar);
}

EXPORT_C void CExample::Read()
// citanje
{
if ((iEngineStatus == EConnected)&&(!iEchoRead->IsActive()))
iEchoRead->IssueRead();
}

void CExample::RunL()
// Aplikacija
{
iTimer->Cancel();
_LIT(KConnecting,"\n<CSpajanje\n");
_LIT(KConnectionFailed,"\n<CExample> Spajanje neuspjelo");
_LIT(KDNSFailed,"\n<CExample> DNS trazenje neuspjelo");
_LIT(KTimedOut,"\n<CExample> Timeout\n");
_LIT(KDomainName,"\nIme domene = ");
_LIT(KIPAddress,"\nIP adresa = ");

TBuf<15> ipAddr;

switch(iEngineStatus)
{
case EConnecting:
// spajanje preko IPa
if (iStatus == KErrNone)
// spojeno
{
iConsole->PrintNotify(KConnecting);
iEngineStatus = EConnected;
Read();
}
else
{
iEngineStatus = EConnectFailed;
iConsole->ErrorNotify(KConnectionFailed, iStatus.Int());
}
break;
case ETimedOut:
iConsole->ErrorNotify(KTimedOut, KErrTimedOut);
break;
case ELookingUp:
iResolver.Close();
if (iStatus == KErrNone)
// DNS lookup uspjelo
{
iNameRecord = iNameEntry();
iConsole->PrintNotify(KDomainName);
iConsole->PrintNotify(iNameRecord.iName);
TInetAddr::Cast(iNameRecord.iAddr).Output(ipAddr);
iConsole->PrintNotify(KIPAddress);
iConsole->PrintNotify(ipAddr);
ConnectL(TInetAddr::Cast(iNameRecord.iAddr).Address());
}
else
{
iStatus = ELookUpFailed;
iConsole->ErrorNotify(KDNSFailed, iStatus.Int());
}
break;

default:;
};
}

CExample::~CExample()
{
delete iEchoRead;
delete iEchoWrite;
delete iTimer;
iEchoSocket.Close();
iSocketServ.Close();
}

void CExample::TimerExpired()
{
Cancel();
iEngineStatus = ETimedOut;
TRequestStatus* p=&iStatus;
SetActive();
User::RequestComplete(p, ETimedOut);
}

EXPORT_C void CExample::Stop()
// Shutdown
{
_LIT(KETerminate,"\n<CExample> Gasenje...\n");
iConsole->PrintNotify(KETerminate);

switch (iEngineStatus)
{
case EConnected:
iEchoRead->Cancel();
iEchoWrite->Cancel();
break;
case EConnecting:
case ELookingUp:
Cancel();
break;
default:;
}
}

CEchoRead::CEchoRead() : CActive(EPriorityStandard)
{
}

CEchoRead* CEchoRead::NewL(RSocket* aSocket, MUINotify* aConsole)
{
CEchoRead* self = NewLC(aSocket, aConsole);
CleanupStack::Pop();
return self;
}

CEchoRead* CEchoRead::NewLC(RSocket* aSocket, MUINotify* aConsole)
{
CEchoRead* self = new(ELeave) CEchoRead;
CleanupStack::PushL(self);
self->ConstructL(aSocket, aConsole);
return self;
}

void CEchoRead::ConstructL(RSocket* aSocket, MUINotify* aConsole)
{
iEchoSocket = aSocket;
iConsole = aConsole;
CActiveScheduler::Add(this);
}

void CEchoRead::DoCancel()
{
iEchoSocket->CancelRead();
}

void CEchoRead::RunL()
{
if (iStatus == KErrNone)
{
_LIT(KDot,".");
iConsole->PrintNotify(KDot);
TBuf16<1> Buffer;
Buffer.Copy(iBuffer);
iConsole->PrintNotify(Buffer);
IssueRead();
}
else
{

_LIT(KCEchoReadError,"\nCEchoRead Error");
iConsole->ErrorNotify(KCEchoReadError, iStatus.Int());
}
}

void CEchoRead::IssueRead()
{
if (!IsActive())
{
iEchoSocket->Recv(iBuffer, 0, iStatus);
SetActive();
}
}

void CEchoRead::IssueRecvFrom(TInetAddr &aAddr)
{
iEchoSocket->RecvFrom(iBuffer,aAddr,NULL,iStatus);
SetActive();
};

CEchoWrite::CEchoWrite() : CActive(EPriorityStandard)
{
};

CEchoWrite* CEchoWrite::NewL(RSocket* aSocket, MUINotify* aConsole)
{
CEchoWrite* self = NewLC(aSocket, aConsole);
CleanupStack::Pop();
return self;
};

CEchoWrite* CEchoWrite::NewLC(RSocket* aSocket, MUINotify* aConsole)
{
CEchoWrite* self = new(ELeave) CEchoWrite;
CleanupStack::PushL(self);
self->ConstructL(aSocket, aConsole);
return self;
};

void CEchoWrite::ConstructL(RSocket* aSocket, MUINotify* aConsole)
{
iEchoSocket = aSocket;
iConsole = aConsole;
CActiveScheduler::Add(this);

iTimeOut = KTimeOut;
iTimer = CTimeOutTimer::NewL(10, *this);
iWriteStatus = EWaiting;
};

CEchoWrite::~CEchoWrite()
{
delete iTimer;
}

void CEchoWrite::DoCancel()
{
iEchoSocket->CancelWrite();
};

void CEchoWrite::TimerExpired()
{
Cancel();
iWriteStatus = ETimedOut;
TRequestStatus* p=&iStatus;
SetActive();
User::RequestComplete(p, ETimedOut);
}

void CEchoWrite::RunL()
{
if (iStatus == KErrNone)
{
_LIT(KWriteOperationTimedOut,"\nTimeout");
switch(iWriteStatus)
{
case ESending:
iTimer->Cancel();
iWriteStatus = EWaiting;
break;
case ETimedOut:
iConsole->ErrorNotify(KWriteOperationTimedOut, KErrTimedOut);
break;
default:;
};
}
else
{
_LIT(KCEchoWriteError,"\nCEchoWrite Error");
iConsole->ErrorNotify(KCEchoWriteError, iStatus.Int());
}
}

void CEchoWrite::IssueWrite(const TChar &aChar)
// pisanje po streamu
{
// buffer
iBuffer.SetLength(0);
iBuffer.Append(aChar);
iEchoSocket->Write(iBuffer, iStatus);
iTimer->After(iTimeOut);
SetActive();
iWriteStatus = ESending;
};

CTimeOutTimer::CTimeOutTimer(const TInt aPriority)
: CTimer(aPriority)
{
}

CTimeOutTimer::~CTimeOutTimer()
{
Cancel();
}

CTimeOutTimer* CTimeOutTimer::NewL(const TInt aPriority, MTimeOutNotify& aTimeOutNotify)
{
CTimeOutTimer *p = new (ELeave) CTimeOutTimer(aPriority);
CleanupStack::PushL(p);
p->ConstructL(aTimeOutNotify);
CleanupStack::Pop();
return p;
}

void CTimeOutTimer::ConstructL(MTimeOutNotify &aTimeOutNotify)
{
iNotify=&aTimeOutNotify;
CTimer::ConstructL();
CActiveScheduler::Add(this);
}

void CTimeOutTimer::RunL()
{
iNotify->TimerExpired();
}

// Entry point
GLDEF_C TInt E32Dll()
{
return(KErrNone);
}

///////////////
// Example.h //
///////////////

#ifndef _EXAMPLE_H_
#define _EXAMPLE_H_

#include <e32cons.h>
#include <in_sock.h>
#include <nifman.h>

class MTimeOutNotify
{
public:
virtual void TimerExpired() = 0;
};

class MUINotify
{
public:
virtual void PrintNotify(const TDesC& aMessage) = 0;
virtual void PrintNotify(TInt aMessage) = 0;
virtual void ErrorNotify(const TDesC& aErrMessage, TInt aErrCode) = 0;
};

class CTimeOutTimer: public CTimer
{
public:
static CTimeOutTimer* NewL(const TInt aPriority, MTimeOutNotify& aTimeOutNotify);
~CTimeOutTimer();

protected:
CTimeOutTimer(const TInt aPriority);
void ConstructL(MTimeOutNotify& aTimeOutNotify);
virtual void RunL();

private:
MTimeOutNotify* iNotify;
};

class CEchoRead : public CActive
{
public:
static CEchoRead* NewL(RSocket* aSocket, MUINotify* aConsole);
static CEchoRead* NewLC(RSocket* aSocket, MUINotify* aConsole);
void ConstructL(RSocket* aSocket, MUINotify* aConsole);
void IssueRead();
void IssueRecvFrom(TInetAddr &aAddr);
void DoCancel();
void RunL();

protected:
CEchoRead();

private:
MUINotify* iConsole;
RSocket* iEchoSocket;
TBuf8<1> iBuffer;
};

class CEchoWrite : public CActive, public MTimeOutNotify
{
public:
enum TWriteState
{
ESending, EWaiting ,ETimedOut
};

public:
static CEchoWrite* NewL(RSocket* aSocket, MUINotify* aConsole);
static CEchoWrite* NewLC(RSocket* aSocket, MUINotify* aConsole);
~CEchoWrite();
void ConstructL(RSocket* aSocket, MUINotify* aConsole);
void IssueWrite(const TChar &aChar);
void IssueSendTo(TInetAddr &aAddr, const TChar &aChar);
void DoCancel();
void RunL();
void TimerExpired();

protected:
CEchoWrite();

private:
MUINotify* iConsole;
RSocket* iEchoSocket;
TBuf8<1> iBuffer;
CTimeOutTimer* iTimer;
TInt iTimeOut;
TWriteState iWriteStatus;
};

class CExampleine : public CActive, public MTimeOutNotify
{
public:
enum TExampleineState
{
EComplete, EConnecting, EConnected, ETimedOut,
ELookingUp, ELookUpFailed, EConnectFailed,

};
public:
IMPORT_C CExampleine();
IMPORT_C static CExampleine* NewL(MUINotify* aConsole);
IMPORT_C static CExampleine* NewLC(MUINotify* aConsole);
IMPORT_C void ConstructL(MUINotify* aConsole);
IMPORT_C void Stop();
IMPORT_C void ConnectL(TUint32 aAddr);
IMPORT_C void ConnectL(const TDesC& aServerName);
IMPORT_C void Write(TChar aChar);
IMPORT_C void Read();
IMPORT_C void TestGetByAddr(TUint32 aAddr);

void TimerExpired();
void DoCancel();
void RunL();

~CExampleine();

private:
TExampleineState iEngineStatus;
MUINotify* iConsole;
CEchoRead* iEchoRead;
CEchoWrite* iEchoWrite;
RSocket iEchoSocket;
RSocketServ iSocketServ;
RHostResolver iResolver;
TNameEntry iNameEntry;
TNameRecord iNameRecord;
CTimeOutTimer* iTimer;
TInt iTimeOut;
TInetAddr iAddress;
};

#endif

////////////////////////////////////////////////////////////////////////////
--==<[ 4. Outro
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

Nazalost ovaj tekst nije uspio kako sam se nadao ponajvise zbog toga jer sam
u velikoj vremenskoj krizi tijekom ljeta. Za slijedeci broj vam obecavam pravu
poslasticu, ali zato dobro proucite ovaj dio jer ce vam trebati ukoliko zelite
shvatiti slijedeci tekst. Materija nije velika, jedna klasa i njene funkcije,
ali zato su mogucnosti velike. Pozdrav svima.

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT