private static void SendToRecvFrom_Datagram_UDP(IPAddress leftAddress, IPAddress rightAddress)
{
// TODO #5185: Harden against packet loss
const int DatagramSize = 256;
const int DatagramsToSend = 256;
const int AckTimeout = 1000;
const int TestTimeout = 30000;
var left = new Socket(leftAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
left.BindToAnonymousPort(leftAddress);
var right = new Socket(rightAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
right.BindToAnonymousPort(rightAddress);
var leftEndpoint = (IPEndPoint)left.LocalEndPoint;
var rightEndpoint = (IPEndPoint)right.LocalEndPoint;
var receiverAck = new ManualResetEventSlim();
var senderAck = new ManualResetEventSlim();
var receivedChecksums = new uint?[DatagramsToSend];
var leftThread = new Thread(() =>
{
using (left)
{
EndPoint remote = leftEndpoint.Create(leftEndpoint.Serialize());
var recvBuffer = new byte[DatagramSize];
for (int i = 0; i < DatagramsToSend; i++)
{
int received = left.ReceiveFrom(recvBuffer, SocketFlags.None, ref remote);
Assert.Equal(DatagramSize, received);
Assert.Equal(rightEndpoint, remote);
int datagramId = (int)recvBuffer[0];
Assert.Null(receivedChecksums[datagramId]);
receivedChecksums[datagramId] = Fletcher32.Checksum(recvBuffer, 0, received);
receiverAck.Set();
Assert.True(senderAck.Wait(AckTimeout));
senderAck.Reset();
}
}
});
leftThread.Start();
var sentChecksums = new uint[DatagramsToSend];
using (right)
{
var random = new Random();
var sendBuffer = new byte[DatagramSize];
for (int i = 0; i < DatagramsToSend; i++)
{
random.NextBytes(sendBuffer);
sendBuffer[0] = (byte)i;
int sent = right.SendTo(sendBuffer, SocketFlags.None, leftEndpoint);
Assert.True(receiverAck.Wait(AckTimeout));
receiverAck.Reset();
senderAck.Set();
Assert.Equal(DatagramSize, sent);
sentChecksums[i] = Fletcher32.Checksum(sendBuffer, 0, sent);
}
}
Assert.True(leftThread.Join(TestTimeout));
for (int i = 0; i < DatagramsToSend; i++)
{
Assert.NotNull(receivedChecksums[i]);
Assert.Equal(sentChecksums[i], (uint)receivedChecksums[i]);
}
}