S
Stephan Steiner
Hi
I have a small program listening to UDP broadcast datagrams that are
periodically sent out. It will stop listening for a certain period if either
a sufficient number of packets has been received (this is triggered from a
class not in the sample code), or if there has been no data on the net for a
certain period. During the time where I don't want any packets, I set my
socket receive buffer size to zero.
The problem is, when I used a UDPClient, I was always getting data that was
sent during the period where no listening took place (and changing the
buffer size didn't help), so I'm using sockets directly. However, I don't
receive a single packet now and I have no clue why. sock.Available is always
zero, even if I send a thousand UDP datagrams during the active period.
Here's my code:
public class Receiver
{
IPEndPoint remoteSender;
EndPoint tempRemoteEP;
byte[] packet;
public Thread thread;
bool listening;
Timer tim;
TimerState s;
public int nbPackets;
int seqNo;
Socket sock;
int nbBytesRx;
public Receiver()
{
sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
sock.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.Broadcast, 1);
remoteSender = new IPEndPoint(IPAddress.Any,0);
tempRemoteEP = (EndPoint)remoteSender;
sock.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveBuffer, 0);
listening = false;
nbPackets = 0;
packet = new byte[1024];
s = new TimerState();
TimerCallback timerDelegate = new TimerCallback(this.timeToSleep);
tim = new Timer(timerDelegate, null, Timeout.Infinite, Timeout.Infinite);
ThreadStart startMethod = new ThreadStart(this.run);
thread = new Thread(startMethod);
thread.Start();
thread.Suspend();
}
/**
* method that is running when the thread is active
* receives a packet from the network and processes it
*/
public void run()
{
while (true)
{
if (sock.Available > 0)
{
this.nbBytesRx = sock.ReceiveFrom(packet, ref tempRemoteEP);
nbPackets++;
seqNo = BitConverter.ToInt16(packet, 0);
Console.Write(nbPackets.ToString() + ":" + seqNo.ToString() + " / " );
}
}
}
/**
* resumes the thread
*/
public void activate()
{
if (thread.ThreadState == ThreadState.Suspended || thread.ThreadState ==
ThreadState.SuspendRequested)
{
Console.WriteLine("activated");
tim.Change(5000, 5000);
if (sock.Available > 0)
{
Console.Write("pending data");
}
sock.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveBuffer, 8192);
thread.Resume();
}
else
{
Console.WriteLine("thread was already running");
}
this.listening = true;
}
/**
* suspends the thread
*/
public void deactivate()
{
if (thread.ThreadState == ThreadState.Running)
{
Console.WriteLine("\r\ndeactivated. " + this.nbPackets.ToString() + "
packets received");
tim.Change(Timeout.Infinite,Timeout.Infinite); // disable timer for the
time being
sock.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveBuffer, 0);
thread.Suspend();
}
else
{
Console.WriteLine("thread was already inactive");
}
this.listening = false;
this.nbPackets = 0;
}
public void shutDown()
{
if (thread.ThreadState == ThreadState.Suspended)
thread.Resume();
thread.Abort();
}
/**
* Callback for the timer. Checks whether it's time to suspend the thread
because no new packets
* are coming in
*/
public void timeToSleep(Object state)
{
//TimerState stat = (TimerState)state;
if (this.nbPackets > s.counter) // new packets received in current period
{
s.counter = this.nbPackets;
}
else
{
if (this.listening)
{
this.deactivate();
s.counter = 0;
}
}
}
}
public struct TimerState
{
public int counter;
public Timer tim;
}
and to test I use this code which periodically activates and deactivates the
receiver.
static void Main(string[] args)
{
Receiver rec = new Receiver();
while (true)
{
rec.activate();
Thread.Sleep(10000);
rec.deactivate();
Thread.Sleep(10000);
}
}
Any help would be much appreciated.
Regards
Stephan Steiner
I have a small program listening to UDP broadcast datagrams that are
periodically sent out. It will stop listening for a certain period if either
a sufficient number of packets has been received (this is triggered from a
class not in the sample code), or if there has been no data on the net for a
certain period. During the time where I don't want any packets, I set my
socket receive buffer size to zero.
The problem is, when I used a UDPClient, I was always getting data that was
sent during the period where no listening took place (and changing the
buffer size didn't help), so I'm using sockets directly. However, I don't
receive a single packet now and I have no clue why. sock.Available is always
zero, even if I send a thousand UDP datagrams during the active period.
Here's my code:
public class Receiver
{
IPEndPoint remoteSender;
EndPoint tempRemoteEP;
byte[] packet;
public Thread thread;
bool listening;
Timer tim;
TimerState s;
public int nbPackets;
int seqNo;
Socket sock;
int nbBytesRx;
public Receiver()
{
sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
sock.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.Broadcast, 1);
remoteSender = new IPEndPoint(IPAddress.Any,0);
tempRemoteEP = (EndPoint)remoteSender;
sock.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveBuffer, 0);
listening = false;
nbPackets = 0;
packet = new byte[1024];
s = new TimerState();
TimerCallback timerDelegate = new TimerCallback(this.timeToSleep);
tim = new Timer(timerDelegate, null, Timeout.Infinite, Timeout.Infinite);
ThreadStart startMethod = new ThreadStart(this.run);
thread = new Thread(startMethod);
thread.Start();
thread.Suspend();
}
/**
* method that is running when the thread is active
* receives a packet from the network and processes it
*/
public void run()
{
while (true)
{
if (sock.Available > 0)
{
this.nbBytesRx = sock.ReceiveFrom(packet, ref tempRemoteEP);
nbPackets++;
seqNo = BitConverter.ToInt16(packet, 0);
Console.Write(nbPackets.ToString() + ":" + seqNo.ToString() + " / " );
}
}
}
/**
* resumes the thread
*/
public void activate()
{
if (thread.ThreadState == ThreadState.Suspended || thread.ThreadState ==
ThreadState.SuspendRequested)
{
Console.WriteLine("activated");
tim.Change(5000, 5000);
if (sock.Available > 0)
{
Console.Write("pending data");
}
sock.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveBuffer, 8192);
thread.Resume();
}
else
{
Console.WriteLine("thread was already running");
}
this.listening = true;
}
/**
* suspends the thread
*/
public void deactivate()
{
if (thread.ThreadState == ThreadState.Running)
{
Console.WriteLine("\r\ndeactivated. " + this.nbPackets.ToString() + "
packets received");
tim.Change(Timeout.Infinite,Timeout.Infinite); // disable timer for the
time being
sock.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveBuffer, 0);
thread.Suspend();
}
else
{
Console.WriteLine("thread was already inactive");
}
this.listening = false;
this.nbPackets = 0;
}
public void shutDown()
{
if (thread.ThreadState == ThreadState.Suspended)
thread.Resume();
thread.Abort();
}
/**
* Callback for the timer. Checks whether it's time to suspend the thread
because no new packets
* are coming in
*/
public void timeToSleep(Object state)
{
//TimerState stat = (TimerState)state;
if (this.nbPackets > s.counter) // new packets received in current period
{
s.counter = this.nbPackets;
}
else
{
if (this.listening)
{
this.deactivate();
s.counter = 0;
}
}
}
}
public struct TimerState
{
public int counter;
public Timer tim;
}
and to test I use this code which periodically activates and deactivates the
receiver.
static void Main(string[] args)
{
Receiver rec = new Receiver();
while (true)
{
rec.activate();
Thread.Sleep(10000);
rec.deactivate();
Thread.Sleep(10000);
}
}
Any help would be much appreciated.
Regards
Stephan Steiner