BeginReceiveFrom gets empty data after second packet.

  • Thread starter Thread starter Sean Wolfe
  • Start date Start date
S

Sean Wolfe

I'm putting some Asyncronous socket stuff into one of my applications. And
I'm having a bit of trouble with Udp Asyncronous sockets BeginReceiveFrom()
method. In my application I have an app that receives stock ticks from from
a feeder service. That data then gets massaged and then notifications are
sent to Clients that are viewing stock data. The Clients have a class that
they will use to talk to the Feeder Service. When they first initialize the
client, the client broadcasts a "HELO" command to find a feeder. Then if a
feeder hears it, it will send a "HERE" command. The client will then start
sending Watch commands to the Feeder service via UDP, after it receives the
"HERE", command. If the client doesn't get a "HERE" it will keep sending
"HELO" at a specified interval, until a Feeder Responds with "HELO". Then
when the Feeder Service gets a symbol updae that has a watch on it, it will
broadcast it to the clients.

The problem I have, is that After the client receives the "HERE" packet
command, all remaining packets that arrive using the BeginReceiveFrom() have
an array full of 0 bytes. I check the messages that are being sent by the
Service, and they seem fine. But all remaining data seems to be empty. the
interesting thing is, the packets are the correct size that were sent, it's
just that all the data in it is 0.

Here some code for you examination... (slighly abbreviated to make it easier
to read (?))

//using directives and whatnot......

/// <summary>
/// Class for Feeder Clients to use to connect and receive network updates
from the feeder.
/// </summary>
public class FeederNetClient
{

private Socket udpSocket;
private byte[] buffer;
private EndPoint serverEndpoint = null;
private IPAddress serverIp = null;
private bool listening = false;
private int protocolNum = 1;
private bool feederFound = false;
private int heloResendInterval = 60000;
private int version = 1;

/// <summary>
/// A default constructor. Nothing really happens here.
/// </summary>
public FeederNetClient()
{
}

/// <summary>
/// Initializes the Sockets and begins sending out the HELO broadcast.
/// </summary>
public void InitializeClient()
{
//setup the module endpoints
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any,
NetworkUtil.MmksPortNum);
//Set up the UdpSocket
this.udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);

this.listening = true;
this.sendHelo();
this.beginSocketListen(this.udpSocket);
}

/// <summary>
/// Used to stop all network communication. it also resets the state
/// of the client.
/// </summary>
public void Shutdown()
{
if(this.listening)
{
this.listening = false;
this.feederFound = false;
udpSocket.Shutdown(SocketShutdown.Both);
}
}

private void beginSocketListen(Socket listeningSocket)
{
//The buffer to be filled
this.buffer = new byte[1024];
//setup the remote endpoint
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
this.serverEndpoint = (EndPoint)(sender);
//start up to begin receiving.
listeningSocket.BeginReceiveFrom(this.buffer, 0, this.buffer.Length,
SocketFlags.None, ref this.serverEndpoint, new AsyncCallback(dataReceived),
listeningSocket);
}

/// <summary>
/// Private utility method that is a callback for the
/// BeginSendTo method on sockets.
/// </summary>
/// <param name="result">IAsyncResult object used in the Callback from the
Asyncronus
/// BeginSendTo method.</param>
private void messageSent(IAsyncResult result)
{
Socket client = (Socket)result.AsyncState;
int sent = client.EndSendTo(result);
if(sent <= 0)
throw new ApplicationException("The Object couldn't be sent.");
this.buffer = new byte[1024];
client.BeginReceiveFrom(this.buffer, 0, buffer.Length, SocketFlags.None, ref
this.serverEndpoint, new AsyncCallback(dataReceived), client);
}

/// <summary>
/// Private callback method for when data is received using the
BeginReceiveFrom
/// method. This method also breaks down and parses Protocol messages, and
handles commands.
/// </summary>
/// <param name="result">IAsyncResult object used in the Callback from the
Asyncronus
/// BeginReceiveFrom method.</param>
private void dataReceived(IAsyncResult result)
{
//grab the socket
Socket handler = (Socket) result.AsyncState;
// get the length of bytes received.
int bytesRead = handler.EndReceiveFrom(result, ref this.serverEndpoint);
// is there data in the buffer?
if(bytesRead > 0)
{

//NOTE to readers: This is where i have the trouble. The bytes read is fine,
but the data is all 0's
// This happens after the code passes through here a second time.

//check for the header type info
int headerBlock =
IPAddress.NetworkToHostOrder(BitConverter.ToInt32(this.buffer, 0));
int protocol =
IPAddress.NetworkToHostOrder(BitConverter.ToInt32(this.buffer, 4));
//make sure it's correct
if(headerBlock.Equals(NetworkUtil.MmksPacketID) &&
protocol.Equals(this.protocolNum))
{
//Get the version number of the protocol
int version = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(this.buffer,
8));
if(version == 1)
{
IPAddress address = ((IPEndPoint)this.serverEndpoint).Address;
this.notifyConsumer(String.Format("Received message from {0}",
address.ToString()), 1, NotificationType.Information);
//now grab the payload
byte[] payload = new byte[bytesRead - 12];
Buffer.BlockCopy(this.buffer, 12, payload, 0, bytesRead - 12);
//check the command header
string command = Encoding.ASCII.GetString(payload, 0, 4);
switch(command)
{
case "HERE":
{
this.serverIp = address;
this.feederFound = true;
break;
}
case "ACKW":
{
break;
}
case "OBJT":
{
byte[] payloadSansCommand = new byte[payload.Length - 4];
Buffer.BlockCopy(payload, 4, payloadSansCommand, 0, payload.Length - 4);
ReadObject(payloadSansCommand);
break;
}
}
}
else
throw new ApplicationException("Unhandled Protocol version"); //TODO: make a
better Exception Class for this.
}
}
//Set up to receive again
if(this.listening)
{
this.buffer = new byte[1024];
handler.BeginReceiveFrom(this.buffer, 0, buffer.Length, SocketFlags.None,
ref this.serverEndpoint, new AsyncCallback(dataReceived), handler);
}
}

/// <summary>
/// private utility method that is used to send out the HELO broadcast.
/// This broadcast is for the client to look for a Feeder Service.
/// </summary>
/// <param name="source">object contect for a called timer event.</param>
/// <param name="e">The timer event Arguments.</param>
private void sendHelo()
{
if((!this.feederFound) & this.listening)
{
//setup the broadcast endpoint
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Broadcast,
NetworkUtil.MmksPortNum);
//set up the HELO brodcast packet
string heloCommand = "HELO";
int heloByteSize = Encoding.ASCII.GetByteCount(heloCommand);
byte[] header = NetworkUtil.MmksPacketHeader(this.protocolNum,
this.version);
byte[] packet = new byte[header.Length + heloByteSize];
Buffer.BlockCopy(header, 0, packet, 0, header.Length);
Encoding.ASCII.GetBytes(heloCommand, 0, heloCommand.Length, packet,
header.Length);
//Set the options to allow broadcast
this.udpSocket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.Broadcast, 1);
// send the helo broadcast
this.udpSocket.BeginSendTo(packet, 0, packet.Length, SocketFlags.None,
ipEndPoint, new AsyncCallback(endSendHelo), udpSocket);
this.notifyConsumer("Sending HELO broadcast...", 1,
NotificationType.Information);
}
}
private void endSendHelo(IAsyncResult result)
{
Socket client = (Socket)result.AsyncState;
int sent = client.EndSendTo(result);
if(sent <= 0)
throw new ApplicationException("HELO was not sent correctly.");
System.Threading.Thread.Sleep(this.heloResendInterval);
this.sendHelo();
}
}


I didn't include everything. This may even be a bit too much but I wanted to
keep some of it so make sure i might not have missed something.

Any help is greatly apprecaited.

Sean.
 
In case anyone would liek to know or has similar problems, I had found
a solution.

It seems I had Two Asyncronus calls to BeginReceiveFrom that would
compete for a message. I'm not sure why but this woudl cause the data
to come up empty. I just removed the calls to BeginReceiveFrom for the
Sending commands (i don't think i included that code), and had the
listing in one loop of it's own.

Sean

Sean Wolfe said:
I'm putting some Asyncronous socket stuff into one of my applications. And
I'm having a bit of trouble with Udp Asyncronous sockets BeginReceiveFrom()
method. In my application I have an app that receives stock ticks from from
a feeder service. That data then gets massaged and then notifications are
sent to Clients that are viewing stock data. The Clients have a class that
they will use to talk to the Feeder Service. When they first initialize the
client, the client broadcasts a "HELO" command to find a feeder. Then if a
feeder hears it, it will send a "HERE" command. The client will then start
sending Watch commands to the Feeder service via UDP, after it receives the
"HERE", command. If the client doesn't get a "HERE" it will keep sending
"HELO" at a specified interval, until a Feeder Responds with "HELO". Then
when the Feeder Service gets a symbol updae that has a watch on it, it will
broadcast it to the clients.

The problem I have, is that After the client receives the "HERE" packet
command, all remaining packets that arrive using the BeginReceiveFrom() have
an array full of 0 bytes. I check the messages that are being sent by the
Service, and they seem fine. But all remaining data seems to be empty. the
interesting thing is, the packets are the correct size that were sent, it's
just that all the data in it is 0.

Here some code for you examination... (slighly abbreviated to make it easier
to read (?))

//using directives and whatnot......

/// <summary>
/// Class for Feeder Clients to use to connect and receive network updates
from the feeder.
/// </summary>
public class FeederNetClient
{

private Socket udpSocket;
private byte[] buffer;
private EndPoint serverEndpoint = null;
private IPAddress serverIp = null;
private bool listening = false;
private int protocolNum = 1;
private bool feederFound = false;
private int heloResendInterval = 60000;
private int version = 1;

/// <summary>
/// A default constructor. Nothing really happens here.
/// </summary>
public FeederNetClient()
{
}

/// <summary>
/// Initializes the Sockets and begins sending out the HELO broadcast.
/// </summary>
public void InitializeClient()
{
//setup the module endpoints
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any,
NetworkUtil.MmksPortNum);
//Set up the UdpSocket
this.udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);

this.listening = true;
this.sendHelo();
this.beginSocketListen(this.udpSocket);
}

/// <summary>
/// Used to stop all network communication. it also resets the state
/// of the client.
/// </summary>
public void Shutdown()
{
if(this.listening)
{
this.listening = false;
this.feederFound = false;
udpSocket.Shutdown(SocketShutdown.Both);
}
}

private void beginSocketListen(Socket listeningSocket)
{
//The buffer to be filled
this.buffer = new byte[1024];
//setup the remote endpoint
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
this.serverEndpoint = (EndPoint)(sender);
//start up to begin receiving.
listeningSocket.BeginReceiveFrom(this.buffer, 0, this.buffer.Length,
SocketFlags.None, ref this.serverEndpoint, new AsyncCallback(dataReceived),
listeningSocket);
}

/// <summary>
/// Private utility method that is a callback for the
/// BeginSendTo method on sockets.
/// </summary>
/// <param name="result">IAsyncResult object used in the Callback from the
Asyncronus
/// BeginSendTo method.</param>
private void messageSent(IAsyncResult result)
{
Socket client = (Socket)result.AsyncState;
int sent = client.EndSendTo(result);
if(sent <= 0)
throw new ApplicationException("The Object couldn't be sent.");
this.buffer = new byte[1024];
client.BeginReceiveFrom(this.buffer, 0, buffer.Length, SocketFlags.None, ref
this.serverEndpoint, new AsyncCallback(dataReceived), client);
}

/// <summary>
/// Private callback method for when data is received using the
BeginReceiveFrom
/// method. This method also breaks down and parses Protocol messages, and
handles commands.
/// </summary>
/// <param name="result">IAsyncResult object used in the Callback from the
Asyncronus
/// BeginReceiveFrom method.</param>
private void dataReceived(IAsyncResult result)
{
//grab the socket
Socket handler = (Socket) result.AsyncState;
// get the length of bytes received.
int bytesRead = handler.EndReceiveFrom(result, ref this.serverEndpoint);
// is there data in the buffer?
if(bytesRead > 0)
{

//NOTE to readers: This is where i have the trouble. The bytes read is fine,
but the data is all 0's
// This happens after the code passes through here a second time.

//check for the header type info
int headerBlock =
IPAddress.NetworkToHostOrder(BitConverter.ToInt32(this.buffer, 0));
int protocol =
IPAddress.NetworkToHostOrder(BitConverter.ToInt32(this.buffer, 4));
//make sure it's correct
if(headerBlock.Equals(NetworkUtil.MmksPacketID) &&
protocol.Equals(this.protocolNum))
{
//Get the version number of the protocol
int version = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(this.buffer,
8));
if(version == 1)
{
IPAddress address = ((IPEndPoint)this.serverEndpoint).Address;
this.notifyConsumer(String.Format("Received message from {0}",
address.ToString()), 1, NotificationType.Information);
//now grab the payload
byte[] payload = new byte[bytesRead - 12];
Buffer.BlockCopy(this.buffer, 12, payload, 0, bytesRead - 12);
//check the command header
string command = Encoding.ASCII.GetString(payload, 0, 4);
switch(command)
{
case "HERE":
{
this.serverIp = address;
this.feederFound = true;
break;
}
case "ACKW":
{
break;
}
case "OBJT":
{
byte[] payloadSansCommand = new byte[payload.Length - 4];
Buffer.BlockCopy(payload, 4, payloadSansCommand, 0, payload.Length - 4);
ReadObject(payloadSansCommand);
break;
}
}
}
else
throw new ApplicationException("Unhandled Protocol version"); //TODO: make a
better Exception Class for this.
}
}
//Set up to receive again
if(this.listening)
{
this.buffer = new byte[1024];
handler.BeginReceiveFrom(this.buffer, 0, buffer.Length, SocketFlags.None,
ref this.serverEndpoint, new AsyncCallback(dataReceived), handler);
}
}

/// <summary>
/// private utility method that is used to send out the HELO broadcast.
/// This broadcast is for the client to look for a Feeder Service.
/// </summary>
/// <param name="source">object contect for a called timer event.</param>
/// <param name="e">The timer event Arguments.</param>
private void sendHelo()
{
if((!this.feederFound) & this.listening)
{
//setup the broadcast endpoint
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Broadcast,
NetworkUtil.MmksPortNum);
//set up the HELO brodcast packet
string heloCommand = "HELO";
int heloByteSize = Encoding.ASCII.GetByteCount(heloCommand);
byte[] header = NetworkUtil.MmksPacketHeader(this.protocolNum,
this.version);
byte[] packet = new byte[header.Length + heloByteSize];
Buffer.BlockCopy(header, 0, packet, 0, header.Length);
Encoding.ASCII.GetBytes(heloCommand, 0, heloCommand.Length, packet,
header.Length);
//Set the options to allow broadcast
this.udpSocket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.Broadcast, 1);
// send the helo broadcast
this.udpSocket.BeginSendTo(packet, 0, packet.Length, SocketFlags.None,
ipEndPoint, new AsyncCallback(endSendHelo), udpSocket);
this.notifyConsumer("Sending HELO broadcast...", 1,
NotificationType.Information);
}
}
private void endSendHelo(IAsyncResult result)
{
Socket client = (Socket)result.AsyncState;
int sent = client.EndSendTo(result);
if(sent <= 0)
throw new ApplicationException("HELO was not sent correctly.");
System.Threading.Thread.Sleep(this.heloResendInterval);
this.sendHelo();
}
}


I didn't include everything. This may even be a bit too much but I wanted to
keep some of it so make sure i might not have missed something.

Any help is greatly apprecaited.

Sean.
 
Back
Top