Last active
September 18, 2019 22:24
-
-
Save halter73/0efed97b495150a633c7b765e24c939a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Net; | |
using System.Net.Sockets; | |
using System.Threading.Tasks; | |
namespace SlowClose | |
{ | |
class Program | |
{ | |
const int PORT = 8080; | |
const long SERVER_SEND_CHUNK_SIZE = 4 * 1024; | |
const long SERVER_SEND_CHUNK_COUNT = 8 * 1024; | |
const long CLIENT_RECEIVE_CHUNK_SIZE = 64 * 1024; | |
const double CLIENT_TARGET_BYTES_PER_SECOND = 2 * 1024 * 1024; | |
static void Main(string[] args) | |
{ | |
Console.WriteLine("Hello World!"); | |
Task.WaitAll(RunServer(), RunClient()); | |
} | |
static async Task RunServer() | |
{ | |
using (var listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) | |
{ | |
listenSocket.Bind(new IPEndPoint(IPAddress.Loopback, PORT)); | |
listenSocket.Listen(0); | |
using (var socket = await listenSocket.AcceptAsync()) | |
{ | |
var sendChunk = new byte[SERVER_SEND_CHUNK_SIZE].AsMemory(); | |
var receiveChunk = new byte[1].AsMemory(); | |
var readTask = socket.ReceiveAsync(receiveChunk, SocketFlags.None); | |
for (int i = 0; i < SERVER_SEND_CHUNK_COUNT; i++) | |
{ | |
//Console.WriteLine("Seinding"); | |
await socket.SendAsync(sendChunk, SocketFlags.None); | |
//Console.WriteLine("Sent!!!!!"); | |
} | |
Console.WriteLine("Shuting down socket."); | |
socket.Shutdown(SocketShutdown.Both); | |
Console.WriteLine("Shut down socket."); | |
try | |
{ | |
var bytesRead = await readTask; | |
Console.WriteLine("Server read task completed gracefully with {0} bytes read", bytesRead); | |
} | |
catch (Exception ex) | |
{ | |
Console.WriteLine("Server read task completed with error: {0}", ex); | |
} | |
} | |
} | |
Console.WriteLine("Server sockets disposed"); | |
} | |
static async Task RunClient() | |
{ | |
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) | |
{ | |
var stopwatch = new Stopwatch(); | |
stopwatch.Start(); | |
var totalBytesReceived = 0; | |
var receiveBuffer = new byte[CLIENT_RECEIVE_CHUNK_SIZE].AsMemory(); | |
await socket.ConnectAsync(new IPEndPoint(IPAddress.Loopback, 8080)); | |
while (totalBytesReceived < SERVER_SEND_CHUNK_SIZE * SERVER_SEND_CHUNK_COUNT) | |
{ | |
//Console.WriteLine("Receiving"); | |
var received = await socket.ReceiveAsync(receiveBuffer, SocketFlags.None); | |
//Console.WriteLine("Received: {0}", received); | |
if (received == 0) | |
{ | |
Console.WriteLine("Unexpectedly observed end of data"); | |
return; | |
} | |
totalBytesReceived += received; | |
var expectedTimeElapsed = TimeSpan.FromSeconds(totalBytesReceived / CLIENT_TARGET_BYTES_PER_SECOND); | |
var timeElapsed = stopwatch.Elapsed; | |
if (timeElapsed + TimeSpan.FromSeconds(1) < expectedTimeElapsed) | |
{ | |
Console.WriteLine("Delaying {0} seconds after receiving {1} bytes in {2} seconds", expectedTimeElapsed - timeElapsed, totalBytesReceived, timeElapsed); | |
await Task.Delay(expectedTimeElapsed - timeElapsed); | |
} | |
} | |
} | |
Console.WriteLine("Read all data"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sample output (no repro 😢):