No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TcpClient.cs 2.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. using System;
  6. using System.Net;
  7. using System.Net.Sockets;
  8. using System.Threading;
  9. namespace Microsoft.Unity.VisualStudio.Editor.Messaging
  10. {
  11. internal class TcpClient
  12. {
  13. private const int ConnectOrReadTimeoutMilliseconds = 5000;
  14. private class State
  15. {
  16. public System.Net.Sockets.TcpClient TcpClient;
  17. public NetworkStream NetworkStream;
  18. public byte[] Buffer;
  19. public Action<byte[]> OnBufferAvailable;
  20. }
  21. public static void Queue(IPAddress address, int port, int bufferSize, Action<byte[]> onBufferAvailable)
  22. {
  23. var client = new System.Net.Sockets.TcpClient();
  24. var state = new State {OnBufferAvailable = onBufferAvailable, TcpClient = client, Buffer = new byte[bufferSize]};
  25. try
  26. {
  27. ThreadPool.QueueUserWorkItem(_ =>
  28. {
  29. var handle = client.BeginConnect(address, port, OnClientConnected, state);
  30. if (!handle.AsyncWaitHandle.WaitOne(ConnectOrReadTimeoutMilliseconds))
  31. Cleanup(state);
  32. });
  33. }
  34. catch (Exception)
  35. {
  36. Cleanup(state);
  37. }
  38. }
  39. private static void OnClientConnected(IAsyncResult result)
  40. {
  41. var state = (State)result.AsyncState;
  42. try
  43. {
  44. state.TcpClient.EndConnect(result);
  45. state.NetworkStream = state.TcpClient.GetStream();
  46. var handle = state.NetworkStream.BeginRead(state.Buffer, 0, state.Buffer.Length, OnEndRead, state);
  47. if (!handle.AsyncWaitHandle.WaitOne(ConnectOrReadTimeoutMilliseconds))
  48. Cleanup(state);
  49. }
  50. catch (Exception)
  51. {
  52. Cleanup(state);
  53. }
  54. }
  55. private static void OnEndRead(IAsyncResult result)
  56. {
  57. var state = (State)result.AsyncState;
  58. try
  59. {
  60. var count = state.NetworkStream.EndRead(result);
  61. if (count == state.Buffer.Length)
  62. state.OnBufferAvailable?.Invoke(state.Buffer);
  63. }
  64. catch (Exception)
  65. {
  66. // Ignore and cleanup
  67. }
  68. finally
  69. {
  70. Cleanup(state);
  71. }
  72. }
  73. private static void Cleanup(State state)
  74. {
  75. state.NetworkStream?.Dispose();
  76. state.TcpClient?.Close();
  77. state.NetworkStream = null;
  78. state.TcpClient = null;
  79. state.Buffer = null;
  80. state.OnBufferAvailable = null;
  81. }
  82. }
  83. }