Skip to content

Instantly share code, notes, and snippets.

@ayende ayende/tcp-race.cs
Last active Nov 27, 2018

Embed
What would you like to do?
class Program
{
private static TcpListener _listener;
private static readonly byte[] ShortMessageBuffer = Encoding.UTF8.GetBytes("Hello\r\n");
private static readonly byte[] LongMessageBuffer = Encoding.UTF8.GetBytes("Be my friend, please?\r\n");
static readonly byte[] HeartbeatBuffer = Encoding.UTF8.GetBytes("\r\n");
static void Main()
{
_listener = new TcpListener(IPAddress.Loopback, 9090);
_listener.Start();
for (int i = 0; i < 4; i++)
{
ListenToNewTcpConnection();
}
for (int i = 0; i < 1000; i++)
{
Console.Write("\r" + i + " ");
RunClient().Wait();
}
}
private static async Task RunClient()
{
using (var tcpClient = new TcpClient())
{
await tcpClient.ConnectAsync("127.0.0.1", 9090);
using (var networkStream = tcpClient.GetStream())
{
var streamReader = new StreamReader(networkStream);
await networkStream.WriteAsync(ShortMessageBuffer, 0, ShortMessageBuffer.Length);
await networkStream.WriteAsync(LongMessageBuffer, 0, LongMessageBuffer.Length);
var reply = await streamReader.ReadLineAsync();
if (reply != "ixqZU8RhEpaoJ6v4xHgE1w==")
throw new InvalidDataException("Bad server?");
await networkStream.FlushAsync();
do
{
reply = await streamReader.ReadLineAsync();
} while (string.IsNullOrEmpty(reply));
Console.WriteLine(reply);
}
}
}
private static void ListenToNewTcpConnection()
{
Task.Run(async () =>
{
var tcpClient = await _listener.AcceptTcpClientAsync();
ListenToNewTcpConnection();
using(var networkStream = tcpClient.GetStream())
{
var streamReader = new StreamReader(networkStream);
var greet = await streamReader.ReadLineAsync();
var computeHash = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(greet));
var replyBuffer = Encoding.UTF8.GetBytes(Convert.ToBase64String(computeHash) + "\r\n");
await networkStream.WriteAsync(replyBuffer, 0, replyBuffer.Length);
// now the connection is valid, we can start talking to each other
await ProcessConnection(networkStream);
}
});
}
private static async Task ProcessConnection(NetworkStream stream)
{
using (var streamReader = new StreamReader(stream))
using (var streamWriter = new StreamWriter(stream))
{
var readNextLine = streamReader.ReadLineAsync();
while (true)
{
var resultingTask = await Task.WhenAny(readNextLine, Task.Delay(5000));
if (resultingTask != readNextLine)
{
// keep alive for the tcp connection
await stream.WriteAsync(HeartbeatBuffer, 0, HeartbeatBuffer.Length);
continue;
}
var msg = await readNextLine;
readNextLine = streamReader.ReadLineAsync();
msg = new string(msg.Reverse().ToArray());
await streamWriter.WriteLineAsync(msg);
await streamWriter.FlushAsync();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.