Created
October 16, 2020 14:40
-
-
Save antonfirsov/9bcd49ea956644cc9069e5d5a00ee2e6 to your computer and use it in GitHub Desktop.
This file contains hidden or 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.Threading; | |
using System.Threading.Tasks; | |
using System.Net; | |
using System.Net.Sockets; | |
namespace HangSockets | |
{ | |
class Program | |
{ | |
static async Task Main(string[] args) | |
{ | |
await TestSendReceive(); | |
} | |
private static async Task TestSendReceive() | |
{ | |
int msDelay = 100; | |
(Socket socket1, Socket socket2) = CreateConnectedSocketPair(true); | |
using (socket2) | |
{ | |
Task socketOperation = Task.Run(() => socket1.Receive(new byte[1])); | |
// Wait a little so the operation is started. | |
await Task.Delay(msDelay); | |
msDelay *= 2; | |
Task disposeTask = Task.Run(() => socket1.Dispose()); | |
var cts = new CancellationTokenSource(); | |
Task timeoutTask = Task.Delay(5000, cts.Token); | |
Task firstFinished = await Task.WhenAny(disposeTask, socketOperation, timeoutTask); | |
if (firstFinished == timeoutTask) | |
{ | |
throw new Exception("Timeout!"); | |
} | |
cts.Cancel(); | |
await disposeTask; | |
try | |
{ | |
await socketOperation; | |
} | |
catch (SocketException se) | |
{ | |
Console.WriteLine(se.SocketErrorCode.ToString()); | |
} | |
catch (ObjectDisposedException) | |
{ | |
Console.WriteLine("ObjectDisposedException!"); | |
} | |
} | |
static (Socket client, Socket server) CreateConnectedSocketPair(bool ipv6 = false, bool dualModeClient = false) | |
{ | |
IPAddress serverAddress = ipv6 ? IPAddress.IPv6Loopback : IPAddress.Loopback; | |
using Socket listener = new Socket(serverAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | |
listener.Bind(new IPEndPoint(serverAddress, 0)); | |
listener.Listen(1); | |
IPEndPoint connectTo = (IPEndPoint)listener.LocalEndPoint; | |
if (dualModeClient) connectTo = new IPEndPoint(connectTo.Address.MapToIPv6(), connectTo.Port); | |
Socket client = new Socket(connectTo.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | |
if (dualModeClient) client.DualMode = true; | |
client.Connect(connectTo); | |
Socket server = listener.Accept(); | |
return (client, server); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment