using System; using System.Threading; using Top.Api; using WebSocketSharp; namespace Taobao.Top.Link.Channel.WebSocket { /// simple websocket client helper /// public static class WebSocketClient { /// connect to uri via websocket /// /// remote address /// timeout in milliseconds /// public static IClientChannel Connect(Uri uri, int timeout) { return Connect(Log.Instance, uri, timeout); } /// connect to uri via websocket /// /// loggerFactory /// remote address /// timeout in milliseconds /// public static IClientChannel Connect(ITopLogger logger, Uri uri, int timeout) { //log first var log = logger; var h = new WaitHandle(); var onOpen = new EventHandler((o, e) => h.Set()); var onError = new EventHandler((o, e) => h.Set(e.Message)); var socket = new WebSocketSharp.WebSocket(uri.ToString()); var channel = new WebSocketClientChannel(socket) { Uri = uri }; socket.OnOpen += onOpen; socket.OnError += onError; socket.Connect(); if (!h.WaitOne(timeout, false)) throw new LinkException("connect timeout"); if (h.IsError) throw new LinkException(h.Error); socket.OnOpen -= onOpen; socket.OnError -= onError; socket.OnError += (o, e) => On(log , channel.OnError , new ChannelContext(new LinkException(e.Message))); socket.OnClose += (o, e) => On(log , channel.OnClosed , new ChannelClosedEventArgs(e.Reason)); socket.OnMessage += (o, e) => On(log , channel.OnMessage , new ChannelContext(e.RawData, channel)); return channel; } private static void On(ITopLogger log, EventHandler eventHandler, T args) where T : EventArgs { try { if (eventHandler != null) eventHandler(null, args); } catch (Exception e) { //here is global on error log.Error(e.StackTrace); //TODO:close channel here? } } class WaitHandle : EventWaitHandle { public bool IsError { get; private set; } public string Error { get; private set; } public WaitHandle() : base(false, EventResetMode.AutoReset) { } public void Set(string error) { this.IsError = true; this.Error = error; this.Set(); } } } }