Author Topic: TNUdpProtocol OnReceive crashing when BeginReceiveFrom  (Read 3339 times)

asinbow

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 3
    • View Profile
TNUdpProtocol OnReceive crashing when BeginReceiveFrom
« on: February 11, 2015, 11:04:05 PM »
System.Net.Sockets.SocketException (0x80004005): 远程主机强迫关闭了一个现有的连接。(Chinese. Remote host closed current connection forcibly)
   在(at) System.Net.Sockets.Socket.DoBeginReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint endPointSnapshot, SocketAddress socketAddress, OverlappedAsyncResult asyncResult)
   在(at) System.Net.Sockets.Socket.BeginReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint& remoteEP, AsyncCallback callback, Object state)
   在(at) TNet.UdpProtocol.OnReceive(IAsyncResult result) 位置(location) d:\work\repo\warship-hunter-mad\dev\jinggle-server\TNet\TNet.Server\Common\TNUdpProtocol.cs:行号(line) 198
   在(at) System.Net.LazyAsyncResult.Complete(IntPtr userToken)
   在(at) System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   在(at) System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   在(at) System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   在(at) System.Net.ContextAwareResult.Complete(IntPtr userToken)
   在(at) System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
   在(at) System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)


It crashes when both BeginReceiveFrom and connection closed by remote at the same time.
This issue still exists in 2.0.4.
Maybe should wrap with try-catch.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: TNUdpProtocol OnReceive crashing when BeginReceiveFrom
« Reply #1 on: February 13, 2015, 09:01:25 AM »
Why are you getting connection-based errors (TCP) on a UDP socket?

asinbow

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 3
    • View Profile
Re: TNUdpProtocol OnReceive crashing when BeginReceiveFrom
« Reply #2 on: February 24, 2015, 09:49:49 PM »
"In UDP land, one way this can occur is when you send a UDP packet to a host, and the remote host doesn't have a listener on that port, and bounces an ICMP host unreachable message in response."

http://stackoverflow.com/questions/7201862/an-existing-connection-was-forcibly-closed-by-the-remote-host

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: TNUdpProtocol OnReceive crashing when BeginReceiveFrom
« Reply #3 on: February 27, 2015, 04:56:30 AM »
Well, I've wrapped it on my end so it will be so in the next update.

asinbow

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 3
    • View Profile
Re: TNUdpProtocol OnReceive crashing when BeginReceiveFrom
« Reply #4 on: February 27, 2015, 10:55:41 PM »
Thanks for your response!
I've also written a test program to easily regenerate the crash.
You can use this code for test.

* Test locally:
*   Just run it.
*   It's very easy to re-generate the crash in this mode.
*
* Test across machines:
*   server:
*     Test.exe 9988
*   client:
*     Test.exe 9988 192.168.x.x
*   It's NOT very easy to re-generate the crash in this mode.

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4.  
  5. namespace Test
  6. {
  7.     class Program
  8.     {
  9.         private class AsyncData
  10.         {
  11.             public int Port;
  12.             public Socket Socket;
  13.             public EndPoint EndPoint;
  14.         }
  15.         private static void StartUDPServer(int port)
  16.         {
  17.             var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  18.             EndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);
  19.             socket.Bind(new IPEndPoint(IPAddress.Any, port));
  20.             byte[] buffer = new byte[100];
  21.             socket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref endpoint, OnReceivedFrom, new AsyncData()
  22.                 {
  23.                     Port = port,
  24.                     Socket = socket,
  25.                     EndPoint = endpoint,
  26.                 });
  27.         }
  28.  
  29.         private static void OnReceivedFrom(IAsyncResult result)
  30.         {
  31.             var data = (AsyncData)result.AsyncState;
  32.             int bytes = data.Socket.EndReceiveFrom(result, ref data.EndPoint);
  33.  
  34.             byte[] buffer = new byte[100];
  35.             data.Socket.BeginSendTo(buffer, 0, buffer.Length, SocketFlags.None, data.EndPoint, OnServerSentTo, data); // KEY_POINT-I: send anything back
  36.             data.Socket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref data.EndPoint, OnReceivedFrom, data);
  37.         }
  38.         private static void OnServerSentTo(IAsyncResult result)
  39.         {
  40.             var data = (AsyncData)result.AsyncState;
  41.             int bytes = data.Socket.EndSendTo(result);
  42.             //Console.WriteLine("sent {0} back", bytes);
  43.         }
  44.         private static void StartUDPClient(EndPoint server)
  45.         {
  46.             var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  47.             byte[] buffer = new byte[100];
  48.             socket.BeginSendTo(buffer, 0, buffer.Length, SocketFlags.None, server, OnClientSentTo, new AsyncData()
  49.                 {
  50.                     Port = 0,
  51.                     Socket = socket,
  52.                     EndPoint = server,
  53.                 });
  54.         }
  55.         private static void OnClientSentTo(IAsyncResult result)
  56.         {
  57.             var data = (AsyncData)result.AsyncState;
  58.             int bytes = data.Socket.EndSendTo(result);
  59.  
  60.             data.Socket.Close(); // KEY_POINT-II: close client it immediately
  61.  
  62.             StartUDPClient(data.EndPoint);
  63.         }
  64.  
  65.  
  66.         /**
  67.          *
  68.          * Test locally:
  69.          *   Just run it.
  70.          *   It's very easy to re-generate the crash in this mode.
  71.          *
  72.          
  73.          * Test across machines:
  74.          *   server:
  75.          *     Test.exe 9988
  76.          *   client:
  77.          *     Test.exe 9988 192.168.x.x
  78.          *   It's NOT very easy to re-generate the crash in this mode.
  79.          *
  80.         */
  81.         static void Main(string[] args)
  82.         {
  83.             bool localTest = true; // both server and client locally
  84.  
  85.             EndPoint server = null;
  86.             int port = 9988;
  87.             if (args.Length > 0) // first argument as port
  88.             {
  89.                 localTest = false;
  90.                 port = int.Parse(args[0]);
  91.             }
  92.  
  93.             if (args.Length > 1) // if client, second argument as server address
  94.             {
  95.                 foreach (var address in Dns.GetHostAddresses(args[1]))
  96.                 {
  97.                     if (address.AddressFamily  == AddressFamily.InterNetwork)
  98.                     {
  99.                         server = new IPEndPoint(address, port);
  100.                     }
  101.                 }
  102.             }
  103.  
  104.             if (localTest)
  105.             {
  106.                 server = new IPEndPoint(IPAddress.Loopback, port);
  107.                 StartUDPServer(port);
  108.                 StartUDPClient(server);
  109.             }
  110.             else if (server == null)
  111.             {
  112.                 StartUDPServer(port);
  113.             }
  114.             else
  115.             {
  116.                 StartUDPClient(server);
  117.             }
  118.  
  119.             System.Console.ReadLine();
  120.         }
  121.     }
  122. }
  123.  
  124.  

Thanks again!