public void SendRecvAsync_Stream_TCP(IPAddress listenAt, bool useMultipleBuffers)
{
const int BytesToSend = 123456;
const int ListenBacklog = 1;
const int LingerTime = 60;
const int TestTimeout = 30000;
var server = new Socket(listenAt.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
server.BindToAnonymousPort(listenAt);
server.Listen(ListenBacklog);
var serverFinished = new TaskCompletionSource<bool>();
int bytesReceived = 0;
var receivedChecksum = new Fletcher32();
var serverEventArgs = new SocketAsyncEventArgs();
server.AcceptAsync(serverEventArgs, remote =>
{
Action<int> recvHandler = null;
bool first = true;
if (!useMultipleBuffers)
{
var recvBuffer = new byte[256];
recvHandler = received =>
{
if (!first)
{
if (received == 0)
{
remote.Dispose();
server.Dispose();
serverFinished.SetResult(true);
return;
}
bytesReceived += received;
receivedChecksum.Add(recvBuffer, 0, received);
}
else
{
first = false;
}
remote.ReceiveAsync(serverEventArgs, recvBuffer, 0, recvBuffer.Length, SocketFlags.None, recvHandler);
};
}
else
{
var recvBuffers = new List<ArraySegment<byte>> {
new ArraySegment<byte>(new byte[123]),
new ArraySegment<byte>(new byte[256], 2, 100),
new ArraySegment<byte>(new byte[1], 0, 0),
new ArraySegment<byte>(new byte[64], 9, 33)
};
recvHandler = received =>
{
if (!first)
{
if (received == 0)
{
remote.Dispose();
server.Dispose();
serverFinished.SetResult(true);
return;
}
bytesReceived += received;
for (int i = 0, remaining = received; i < recvBuffers.Count && remaining > 0; i++)
{
ArraySegment<byte> buffer = recvBuffers[i];
int toAdd = Math.Min(buffer.Count, remaining);
receivedChecksum.Add(buffer.Array, buffer.Offset, toAdd);
remaining -= toAdd;
}
}
else
{
first = false;
}
remote.ReceiveAsync(serverEventArgs, recvBuffers, SocketFlags.None, recvHandler);
};
}
recvHandler(0);
});
EndPoint clientEndpoint = server.LocalEndPoint;
var client = new Socket(clientEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
int bytesSent = 0;
var sentChecksum = new Fletcher32();
var clientEventArgs = new SocketAsyncEventArgs();
client.ConnectAsync(clientEventArgs, clientEndpoint, () =>
{
Action<int> sendHandler = null;
var random = new Random();
var remaining = BytesToSend;
bool first = true;
if (!useMultipleBuffers)
{
var sendBuffer = new byte[512];
sendHandler = sent =>
{
if (!first)
{
bytesSent += sent;
sentChecksum.Add(sendBuffer, 0, sent);
remaining -= sent;
Assert.True(remaining >= 0);
if (remaining == 0)
{
client.LingerState = new LingerOption(true, LingerTime);
client.Dispose();
return;
}
}
else
{
first = false;
}
random.NextBytes(sendBuffer);
client.SendAsync(clientEventArgs, sendBuffer, 0, Math.Min(sendBuffer.Length, remaining), SocketFlags.None, sendHandler);
};
}
else
{
var sendBuffers = new List<ArraySegment<byte>> {
new ArraySegment<byte>(new byte[23]),
new ArraySegment<byte>(new byte[256], 2, 100),
new ArraySegment<byte>(new byte[1], 0, 0),
new ArraySegment<byte>(new byte[64], 9, 9)
};
sendHandler = sent =>
{
if (!first)
{
bytesSent += sent;
for (int i = 0, r = sent; i < sendBuffers.Count && r > 0; i++)
{
ArraySegment<byte> buffer = sendBuffers[i];
int toAdd = Math.Min(buffer.Count, r);
sentChecksum.Add(buffer.Array, buffer.Offset, toAdd);
r -= toAdd;
}
remaining -= sent;
if (remaining <= 0)
{
client.LingerState = new LingerOption(true, LingerTime);
client.Dispose();
return;
}
}
else
{
first = false;
}
for (int i = 0; i < sendBuffers.Count; i++)
{
random.NextBytes(sendBuffers[i].Array);
}
client.SendAsync(clientEventArgs, sendBuffers, SocketFlags.None, sendHandler);
};
}
sendHandler(0);
});
Assert.True(serverFinished.Task.Wait(TestTimeout), "Completed within allowed time");
Assert.Equal(bytesSent, bytesReceived);
Assert.Equal(sentChecksum.Sum, receivedChecksum.Sum);
}