Hi, I am trying to use UDP to send messages in a small mobile network. The aim is to have the messages be broadcast to everyone on the network (ie. 255.255.255.255). I want to be able to use the same class for both sending and receiving the messages, instead of a separate server and separate client class.
Currently I am using active objects to schedule the read and write parts. I cannot, for the life of me, manage to send UDP packets over the network. I have no idea where I am going wrong. I have tried changing the broadcast addr to 0.0.0.0 - didn't work. Then setting the socket 'SendTo()' address to 255.255.255.255 and the 'Recv()' address to 0.0.0.0 (after reading some wiki howto for python networking) - didn't work. I thought maybe it was the set up of the socket. so i switched between using socket.connect and socket.bind commands - still didn't work. HELP! Below is the code I am using:
#include "Management/Broadcast/BroadcastManager.h"
const TUint KSocketBufferSize = 256;
const TInt KTimeOut = 50000000;
CBroadcastManager::CBroadcastManager( CLogger& aLog, RSocketServ& aSocketServer, RConnection& aConnection)
: CActive( CActive::EPriorityStandard )
{
iLog = &aLog;
iSocketServer = &aSocketServer;
iConnection = &aConnection;
iLog->LogL(_L("Constructed broadcast manager"));
}
void CBroadcastManager::ConstructL()
{
iBroadcastStatus = EBroadcastStarted;
iLog->LogL(_L("Creating Timer active object"));
iTimeOut = KTimeOut;
iTimer = CBroadcastTimeOut::NewL(EPriorityHigh, *this);
iLog->LogL(_L("Adding broadcast manager to the scheduler"));
CActiveScheduler::Add(this); // Add to scheduler
iLog->LogL(_L("Opening UDP socket"));
TRAPD(err, iBroadcastSocket.Open(*iSocketServer, KAfInet, KSockDatagram, KProtocolInetUdp, *iConnection) );
if(err != KErrNone)
{
iLog->LogNumL(_L("Error opening broadcast socket"), err );
}
iLog->LogL(_L("Creating read and write active objects"));
iBroadcastRead = CBroadcastRead::NewL(iBroadcastSocket, *iLog);
iBroadcastWrite = CBroadcastWrite::NewL(iBroadcastSocket, *iLog);
iLog->LogL(_L("Finished constructing broadcast manager"));
}
CBroadcastManager::~CBroadcastManager()
{
iBroadcastSocket.CancelAll();
delete iBroadcastRead;
delete iBroadcastWrite;
delete iTimer;
iBroadcastSocket.Close();
}
void CBroadcastManager::DoCancel()
// Cancel asychronous requests
{
iTimer->Cancel();
// Cancel appropriate request to socket
switch (iBroadcastStatus)
{
case EBroadcastConnecting:
iBroadcastSocket.CancelConnect();
break;
default:
break;
}
}
/*
Connect to an Socket by IP address
*/
EXPORT_C void CBroadcastManager::ConnectL(TUint32 aAddr)
{
iLog->LogL(_L("Connecting to address"));
// port number for test purposes - may need to be changed
iAddress.SetPort(7000);
iAddress.SetAddress(aAddr);
iAddress.SetFamily( KAfInet );
iLog->LogL(_L("Connecting/binding broadcast socket to address"));
//iBroadcastSocket.SetLocalPort(7000);
TInt err = iBroadcastSocket.Connect(iAddress, iStatus));
// TInt err = iBroadcastSocket.Bind(iAddress));
iBroadcastStatus = EBroadcastConnecting;
iLog->LogL(_L("Setting active and timer"));
SetActive();
iTimer->After(iTimeOut);
}
/*
Exported function wrapping call to iBroadcastWrite: writes character to socket
*/
EXPORT_C void CBroadcastManager::Write(TChar aChar)
{
/*
In this simple implementation, if iBroadcastWrite is already active, ignore call.
Full implementation would buffer data
*/
if ((iBroadcastStatus == EBroadcastConnected) && !iBroadcastWrite->IsActive()) {
iLog->LogL(_L("Issuing SendTo to broadcast socket on 255.255.255.255"));
iBroadcastWrite->IssueSendTo(KInetAddrBroadcast, aChar);
}
}
/*
Exported function wrapping call to iBroadcastRead: reads character from socket
*/
EXPORT_C void CBroadcastManager::Read()
{
if ((iBroadcastStatus == EBroadcastConnected)&&(!iBroadcastRead->IsActive())) {
iLog->LogL(_L("Reading charachters from broadcast socket on 0.0.0.0"));
iBroadcastRead->IssueRecvFrom(KInetAddrAny);
}
}
/*
Active object request complete handler.
iBroadcastStatus flags what request was made, so its
completion can be handled appropriately
*/
void CBroadcastManager::RunL()
{
// Cancel TimeOut timer before completion
iTimer->Cancel();
_LIT(KConnecting,"\n<CBroadcastManager> Connecting\n");
_LIT(KConnectionFailed,"\n<CBroadcastManager> Connection failed");
_LIT(KDNSFailed,"\n<CBroadcastManager> DNS lookup failed");
_LIT(KTimedOut,"\n<CBroadcastManager> Timed out\n");
_LIT(KDomainName,"\nDomain name = ");
_LIT(KIPAddress,"\nIP address = ");
switch(iBroadcastStatus)
{
case EBroadcastConnecting:
// IP connection request
if (iStatus == KErrNone)
// Connection completed sucessfully
{
iLog->LogL(KConnecting);
iBroadcastStatus = EBroadcastConnected;
Read(); //Start iBroadcastRead Active object
}
else
{
iBroadcastStatus = EBroadcastConnectFailed;
iLog->LogNumL(KConnectionFailed, iStatus.Int());
}
break;
case EBroadcastTimedOut:
// Timeout request
iLog->LogNumL(KTimedOut, KErrTimedOut);
break;
default:
break;
};
}
/*
Implements MTimeOutNotify: called when timeout expired
*/
void CBroadcastManager::TimerExpired()
{
Cancel();
iBroadcastStatus = EBroadcastTimedOut;
TRequestStatus* status = &iStatus;
SetActive();
User::RequestComplete(status, EBroadcastTimedOut);
}
/*
Shutdown connection request
*/
EXPORT_C void CBroadcastManager::Stop()
{
_LIT(KETerminate,"\n<CBroadcastManager> Terminating\n");
iLog->LogL(KETerminate);
switch (iBroadcastStatus)
{
case EBroadcastConnected:
// Stop live connection
iBroadcastRead->Cancel();
iBroadcastWrite->Cancel();
break;
case EBroadcastConnecting:
default:
break;
}
}
#include "Management/Broadcast/BroadcastRead.h"
void CBroadcastRead::ConstructL(RSocket& aSocket, CLogger& aLog)
{
iBroadcastSocket = &aSocket;
iLog = &aLog;
CActiveScheduler::Add(this);
}
/*
Cancel asychronous read request
*/
void CBroadcastRead::DoCancel()
{
iBroadcastSocket->CancelRead();
}
/*
Active object request complete handler
*/
void CBroadcastRead::RunL()
{
if (iStatus == KErrNone)
// Character has been read from socket
{
iLog->LogL(_L("Received broadcast message "));
_LIT(KDot,".");
iLog->LogL(KDot);
TBuf16<1> Buffer;
Buffer.Copy(iBuffer);
iLog->LogL(Buffer);
IssueRecvFrom(KInetAddrAny);
}
else
{
// Error: pass it up to user interface
_LIT(KCEchoReadError,"\CBroadcastRead error");
iLog->LogNumL(KCEchoReadError, iStatus.Int());
}
}
void CBroadcastRead::IssueRecvFrom(TUint32 aAddr)
{
iAddress.SetPort(7000);
iAddress.SetAddress(aAddr);
iAddress.SetFamily( KAfInet );
iBroadcastSocket->RecvFrom(iBuffer,iAddress,NULL,iStatus);
SetActive();
};
#include "Management/Broadcast/BroadcastWrite.h"
// 50 seconds time-out
const TInt KTimeOut = 50000000;
void CBroadcastWrite::ConstructL(RSocket& aSocket, CLogger& aLog)
{
iBroadcastSocket = &aSocket;
iLog = &aLog;
CActiveScheduler::Add(this);
iTimeOut = KTimeOut;
iTimer = CBroadcastTimeOut::NewL(10, *this);
iWriteStatus = EWaiting;
}
/*
Cancels asychronous write request
*/
void CBroadcastWrite::DoCancel()
{
iBroadcastSocket->CancelWrite();
};
/*
Implements MTimeOutNotify: called when timeout expired
*/
void CBroadcastWrite::TimerExpired()
{
Cancel();
iWriteStatus = ETimedOut;
TRequestStatus* status = &iStatus;
SetActive();
User::RequestComplete(status, ETimedOut);
}
/*
Active object request complete handler
*/
void CBroadcastWrite::RunL()
{
if (iStatus == KErrNone)
{
_LIT(KWriteOperationTimedOut,"\nWrite operation timed out");
switch(iWriteStatus)
{
// Character has been written to socket
case ESending:
// Cancel TimeOut timer
iTimer->Cancel();
iWriteStatus = EWaiting;
break;
// Request timed out
case ETimedOut:
iLog->LogNumL(KWriteOperationTimedOut, KErrTimedOut);
break;
default:
break;
};
}
else
{
// Error: pass it up to user interface
_LIT(KCEchoWriteError,"\CBroadcastWrite error");
iLog->LogNumL(KCEchoWriteError, iStatus.Int());
}
}
void CBroadcastWrite::IssueSendTo(TUint32 aAddr, const TChar &aChar)
{
// Set up buffer
iBuffer.SetLength(0);
iBuffer.Append(aChar);
iAddress.SetPort(7000);
iAddress.SetAddress(aAddr);
iAddress.SetFamily( KAfInet );
iLog->LogL(_L("Sending broadcast message "));
iBroadcastSocket->SendTo(iBuffer,iAddress,NULL,iStatus);
// Request timeout
iTimer->After(iTimeOut);
iWriteStatus = ESending;
SetActive();
};
Ok, i have been testing the code with different IP addresses. If I put in the localhost address (127.0.0.1) the program works and I am able to send and recieve multiple messages. But if I change the IP address to 255.255.255.255 or 0.0.0.0 or a combination of these I get no messages received. Can anyone give me some advice as to what I am doing wrong?
I am using two Nokia N80's over WLan as test devices.
Forum posts: 3
Ok, i have been testing the code with different IP addresses. If I put in the localhost address (127.0.0.1) the program works and I am able to send and recieve multiple messages. But if I change the IP address to 255.255.255.255 or 0.0.0.0 or a combination of these I get no messages received. Can anyone give me some advice as to what I am doing wrong?
I am using two Nokia N80's over WLan as test devices.
Thanks in advance!