WebSocketClient.cs 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. using System;
  2. using System.Threading;
  3. using Top.Api;
  4. using WebSocketSharp;
  5. namespace Taobao.Top.Link.Channel.WebSocket
  6. {
  7. /// <summary>simple websocket client helper
  8. /// </summary>
  9. public static class WebSocketClient
  10. {
  11. /// <summary>connect to uri via websocket
  12. /// </summary>
  13. /// <param name="uri">remote address</param>
  14. /// <param name="timeout">timeout in milliseconds</param>
  15. /// <returns></returns>
  16. public static IClientChannel Connect(Uri uri, int timeout)
  17. {
  18. return Connect(Log.Instance, uri, timeout);
  19. }
  20. /// <summary>connect to uri via websocket
  21. /// </summary>
  22. /// <param name="loggerFactory">loggerFactory</param>
  23. /// <param name="uri">remote address</param>
  24. /// <param name="timeout">timeout in milliseconds</param>
  25. /// <returns></returns>
  26. public static IClientChannel Connect(ITopLogger logger, Uri uri, int timeout)
  27. {
  28. //log first
  29. var log = logger;
  30. var h = new WaitHandle();
  31. var onOpen = new EventHandler((o, e) => h.Set());
  32. var onError = new EventHandler<ErrorEventArgs>((o, e) => h.Set(e.Message));
  33. var socket = new WebSocketSharp.WebSocket(uri.ToString());
  34. var channel = new WebSocketClientChannel(socket) { Uri = uri };
  35. socket.OnOpen += onOpen;
  36. socket.OnError += onError;
  37. socket.Connect();
  38. if (!h.WaitOne(timeout, false))
  39. throw new LinkException("connect timeout");
  40. if (h.IsError)
  41. throw new LinkException(h.Error);
  42. socket.OnOpen -= onOpen;
  43. socket.OnError -= onError;
  44. socket.OnError += (o, e) => On(log
  45. , channel.OnError
  46. , new ChannelContext(new LinkException(e.Message)));
  47. socket.OnClose += (o, e) => On(log
  48. , channel.OnClosed
  49. , new ChannelClosedEventArgs(e.Reason));
  50. socket.OnMessage += (o, e) => On(log
  51. , channel.OnMessage
  52. , new ChannelContext(e.RawData, channel));
  53. return channel;
  54. }
  55. private static void On<T>(ITopLogger log, EventHandler<T> eventHandler, T args) where T : EventArgs
  56. {
  57. try
  58. {
  59. if (eventHandler != null)
  60. eventHandler(null, args);
  61. }
  62. catch (Exception e)
  63. {
  64. //here is global on error
  65. log.Error(e.StackTrace);
  66. //TODO:close channel here?
  67. }
  68. }
  69. class WaitHandle : EventWaitHandle
  70. {
  71. public bool IsError { get; private set; }
  72. public string Error { get; private set; }
  73. public WaitHandle() : base(false, EventResetMode.AutoReset) { }
  74. public void Set(string error)
  75. {
  76. this.IsError = true;
  77. this.Error = error;
  78. this.Set();
  79. }
  80. }
  81. }
  82. }