Hi,
I have written a small application that sends and receives UDP datagrams of a certain size at a certain speed; both work fine on 1 host (sending to localhost and receiving there also). The aim of the application is to test packet loss over a direct ethernet connection in a variety of physical conditions.
When I test the applications on 2 different host, the receiver is not able to receive the packets rapidly enough an easily 5% gets lost at only 0.5 Mbit/sec on a direct point-to-point ethernet connection.
Using a packet sniffer I can see that all the packets arrive correctly at the receiver's side. It's a problem of my .NET program not being able to receive the datagrams rapidly enough. I have tried 2 ways :
with UDPClient.Receive and with asynchronous callback on a socket and BeginReceiveFrom/EindReceiveFrom. The former gives better results than the latter.
Is there a solution to this, more specifically, is there a way to increate the buffer size at the receiver on a lower level in the .NET software stack?
I need to process at least 6 Mbit/sec without big packet loss in "perfect" physical conditions.
Below the code that I have been using (2 ways).
I already posted this on microsoft.public.dotnet.framework.performance, but got no response.... I am getting desperate for a solution.
Thanks for your help,
Emmanuel Lambert
----------------------------------------
// 1) Using UDPClient.Receive
-------------------------
public void receiveStream()
{
try
{
iUdpReceiveClient = new UdpClient(iPort);
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any,iPort);
iPacketsReceived = 0;
iReceivedPacketsLost = 0;
iReceivedPacketsLostPct = 0;
while (!iStop)
{
Byte[] receiveBytes = iUdpReceiveClient.Receive(ref
RemoteIpEndPoint);
long packetVolgnr = buildLong(receiveBytes);
iPacketsReceived++;
iReceivedPacketSize = receiveBytes.Length;
iReceivedPacketsLost = packetVolgnr - iPacketsReceived;
if (packetVolgnr != 0)
{
iReceivedPacketsLostPct =
Math.Round((double)iReceivedPacketsLost / (double)packetVolgnr *
100.0, 2);
}
}
}
catch (Exception e)
{
if ( (iFncSendError != null) && (!iStop) )
{
iFncSendError(e.Message+"\n"+e.StackTrace);
}
}
}
// 2) Using Asynchronous Callback on a Socket
//(code can be structured better, this is only for testing purposes)
---------------------------------------------
private Socket iSocket;
private byte[] iBuffer = new byte[100000];
public void receiveStreamAsync()
{
iPacketsReceived = 0;
iReceivedPacketsLost = 0;
iReceivedPacketsLostPct = 0;
AsyncCallback AcceptReceive = new AsyncCallback(this.ReceiveData);
iSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any,iPort);
EndPoint tempRemoteEP = (EndPoint)RemoteIpEndPoint;
iSocket.Bind(RemoteIpEndPoint);
iSocket.BeginReceiveFrom(iBuffer, 0, iBuffer.Length,
SocketFlags.None, ref tempRemoteEP,AcceptReceive, null);
}
private void ReceiveData(IAsyncResult result)
{
try
{
AsyncCallback AcceptReceive = new AsyncCallback(this.ReceiveData);
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any,
iPort);
EndPoint tempRemoteEP = (EndPoint)RemoteIpEndPoint;
int numBytes = iSocket.EndReceiveFrom(result, ref tempRemoteEP);
long packetVolgnr = buildLong(iBuffer);
iPacketsReceived++;
iReceivedPacketSize = numBytes;
iReceivedPacketsLost = packetVolgnr - iPacketsReceived;
if (packetVolgnr != 0)
{
iReceivedPacketsLostPct =
Math.Round((double)iReceivedPacketsLost / (double)packetVolgnr *
100.0, 2);
}
iSocket.BeginReceiveFrom(iBuffer, 0, iBuffer.Length,
SocketFlags.None, ref tempRemoteEP, AcceptReceive, null);
}
catch (Exception e)
{
if ((iFncSendError != null) && (!iStop))
{
iFncSendError(e.Message + "\n" + e.StackTrace);
}
}
}
I have written a small application that sends and receives UDP datagrams of a certain size at a certain speed; both work fine on 1 host (sending to localhost and receiving there also). The aim of the application is to test packet loss over a direct ethernet connection in a variety of physical conditions.
When I test the applications on 2 different host, the receiver is not able to receive the packets rapidly enough an easily 5% gets lost at only 0.5 Mbit/sec on a direct point-to-point ethernet connection.
Using a packet sniffer I can see that all the packets arrive correctly at the receiver's side. It's a problem of my .NET program not being able to receive the datagrams rapidly enough. I have tried 2 ways :
with UDPClient.Receive and with asynchronous callback on a socket and BeginReceiveFrom/EindReceiveFrom. The former gives better results than the latter.
Is there a solution to this, more specifically, is there a way to increate the buffer size at the receiver on a lower level in the .NET software stack?
I need to process at least 6 Mbit/sec without big packet loss in "perfect" physical conditions.
Below the code that I have been using (2 ways).
I already posted this on microsoft.public.dotnet.framework.performance, but got no response.... I am getting desperate for a solution.
Thanks for your help,
Emmanuel Lambert
----------------------------------------
// 1) Using UDPClient.Receive
-------------------------
public void receiveStream()
{
try
{
iUdpReceiveClient = new UdpClient(iPort);
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any,iPort);
iPacketsReceived = 0;
iReceivedPacketsLost = 0;
iReceivedPacketsLostPct = 0;
while (!iStop)
{
Byte[] receiveBytes = iUdpReceiveClient.Receive(ref
RemoteIpEndPoint);
long packetVolgnr = buildLong(receiveBytes);
iPacketsReceived++;
iReceivedPacketSize = receiveBytes.Length;
iReceivedPacketsLost = packetVolgnr - iPacketsReceived;
if (packetVolgnr != 0)
{
iReceivedPacketsLostPct =
Math.Round((double)iReceivedPacketsLost / (double)packetVolgnr *
100.0, 2);
}
}
}
catch (Exception e)
{
if ( (iFncSendError != null) && (!iStop) )
{
iFncSendError(e.Message+"\n"+e.StackTrace);
}
}
}
// 2) Using Asynchronous Callback on a Socket
//(code can be structured better, this is only for testing purposes)
---------------------------------------------
private Socket iSocket;
private byte[] iBuffer = new byte[100000];
public void receiveStreamAsync()
{
iPacketsReceived = 0;
iReceivedPacketsLost = 0;
iReceivedPacketsLostPct = 0;
AsyncCallback AcceptReceive = new AsyncCallback(this.ReceiveData);
iSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any,iPort);
EndPoint tempRemoteEP = (EndPoint)RemoteIpEndPoint;
iSocket.Bind(RemoteIpEndPoint);
iSocket.BeginReceiveFrom(iBuffer, 0, iBuffer.Length,
SocketFlags.None, ref tempRemoteEP,AcceptReceive, null);
}
private void ReceiveData(IAsyncResult result)
{
try
{
AsyncCallback AcceptReceive = new AsyncCallback(this.ReceiveData);
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any,
iPort);
EndPoint tempRemoteEP = (EndPoint)RemoteIpEndPoint;
int numBytes = iSocket.EndReceiveFrom(result, ref tempRemoteEP);
long packetVolgnr = buildLong(iBuffer);
iPacketsReceived++;
iReceivedPacketSize = numBytes;
iReceivedPacketsLost = packetVolgnr - iPacketsReceived;
if (packetVolgnr != 0)
{
iReceivedPacketsLostPct =
Math.Round((double)iReceivedPacketsLost / (double)packetVolgnr *
100.0, 2);
}
iSocket.BeginReceiveFrom(iBuffer, 0, iBuffer.Length,
SocketFlags.None, ref tempRemoteEP, AcceptReceive, null);
}
catch (Exception e)
{
if ((iFncSendError != null) && (!iStop))
{
iFncSendError(e.Message + "\n" + e.StackTrace);
}
}
}