/// <summary> /// отправка сообщения с получением ответа в возвращаемом значении /// ВАЖНО: событие не будет райзиться /// </summary> /// <param name="message"></param> /// <param name="onProgress"> </param> public DoMessage SendSyncMessage(DoMessage message, int timeout = -1, Action <double> onProgress = null) { if (message == null) { return(null); } DoMessage result = null; bool hasResult = false; SendMessage(message, response => { result = response; hasResult = true; }, onProgress); var opTimeout = SYNC_MESSAGE_TIMEOUT; if (timeout > 0) { opTimeout = timeout; } var step = 100; log.Debug(string.Format("таймаут операции {0} мс", opTimeout)); while ((opTimeout -= step) > 0 && !hasResult) { Thread.Sleep(step); } return(result); }
public byte[] SerializeMessage(DoMessage message) { if (message == null) { return(new byte[0]); } IEnumerable <byte> binary = null; var jm = new JsonMessage { Message = message }; string json = JsonConvert.SerializeObject(jm, serializerSettings); byte[] bytes = Encoding.UTF8.GetBytes(json); if (binary != null) { List <byte> b = bytes.ToList(); b.Add(0x03); b.AddRange(binary); bytes = b.ToArray(); } return(bytes); }
/// <summary> /// добавляет запрос в число ожидающих ответа /// </summary> /// <param name="request"></param> /// <param name="callback"></param> public void Add(DoMessage request, Action <DoMessage> callback) { lock (callbacks) { if (callbacks.ContainsKey(request.Id)) { throw new Exception("дублирующийся код запроса"); } callbacks.Add(request.Id, callback); //выполняется 1 раз через TOKEN_LIFE_TIME мс. Удаляет запрос из числа ожидающих Timer timer = new Timer(arg => { lock (callbacks) { if (callbacks.ContainsKey(request.Id)) { callbacks[request.Id](null); callbacks.Remove(request.Id); log.Debug(string.Format("каллбак для {0} был удален по таймауту", request)); } } }, null, timeout, System.Threading.Timeout.Infinite); } }
/// <summary> /// отправка сообщения с получением ответа в калбэке /// ВАЖНО: событие не будет райзиться /// </summary> /// <param name="message"></param> /// <param name="callback"></param> /// <param name="onProgress"></param> public void SendMessage(DoMessage message, Action <DoMessage> callback, Action <double> onProgress = null) { if (message == null) { return; } //todo check message access if (callback != null) { responseWaiterSet.Add(message, callback); } SendMessage(message); }
protected void RaiseMessageRecieved(DoMessage message) { if (MessageRecieved != null) { //обработка поступившего сообщения происходит в фоновом потоке ThreadPool.QueueUserWorkItem((arg) => { try { MessageRecieved(this, new MessageReceivedEventArgs(message)); } catch (Exception ex) { log.Error(string.Format("ошибка при обработке сообщения {0}", message), ex); } }); } }
/// <summary> /// отправляет сообщение на сервер /// </summary> /// <param name="message"></param> public void SendMessage(DoMessage message) { if (message == null) { return; } byte[] data = null; try { data = serializer.SerializeMessage(message); SendData(data); //log.Debug(string.Format("[{0}] сообщение {1} отправлено на точку {2}", this, message, GetRemoteAddress())); } catch (Exception e) { log.Error(string.Format("[{0}] ошибка при сериализации сообщения. Сообщение типа {1}", this, message.GetType().Name), e); } }
private void ProcessMessage(DoMessage message) { if (message == null) { return; } if (responseWaiterSet.Has(message.Id)) { //вызываем callback ожидающего var callback = responseWaiterSet.Get(message.Id); if (callback != null) { callback(message); } } else { RaiseMessageRecieved(message); } }
/// <summary> /// общение между точками соединения /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnMessageRecieved(object sender, MessageReceivedEventArgs e) { if (e.Message is DoMessage) { var message = e.Message as DoMessage; switch (message.What) { case "connect": { var arg = (IDictionary <string, object>)message.Argument; ConnectionId = Guid.Parse(arg["connection-id"].ToString()); var version = (string)arg["version"]; var response = new DoMessage(message.Id, "connect", new Dictionary <string, object> { { "connection-id", ConnectionId }, { "is-version-acceptable", IsClientVersionAcceptable(version) }, { "server-date", DateTime.Now } }, new Guid[] { }); //var response = new ConnectResponse(e.Message.Id, request.ConnectionId, IsClientVersionAcceptable(request.Version)); SendMessage(response); break; } } } //хендшейк между точками //if (e.Message is ConnectRequest) //{ // var request = e.Message as ConnectRequest; // ConnectionId = request.ConnectionId; // var response = new ConnectResponse(e.Message.Id, request.ConnectionId, IsClientVersionAcceptable(request.Version)); // SendMessage(response); //} //if (e.Message is PingRequest) //{ // lastPingSuccess = true; // var response = new PingResponse(e.Message.Id); // SendMessage(response); //} }
async static Task Run() { var requests = new DoMessage[] { new DoMessage() { In = "First" }, new DoMessage() { In = "Second" }, new DoMessage() { In = "Third" }, new DoMessage() { In = "4" }, new DoMessage() { In = "5" }, new DoMessage() { In = "6" }, new DoMessage() { In = "7" }, new DoMessage() { In = "8" }, new DoMessage() { In = "9" }, new DoMessage() { In = "10" }, new DoMessage() { In = "11" } }; Channel channel = new Channel("localhost", 50051, ChannelCredentials.Insecure); var client = new MyService.MyServiceClient(channel); Console.WriteLine("Starting..."); var options = new CallOptions().WithDeadline(DateTime.UtcNow.AddSeconds(15)).WithWaitForReady(true); using (var call = client.Do(options)) { var responseReaderTask = Task.Run(async() => { Console.WriteLine("Receiving..."); while (await call.ResponseStream.MoveNext()) { Console.WriteLine("Waiting..."); var note = call.ResponseStream.Current; Console.WriteLine("Received " + note.In); } Console.WriteLine("End Received"); }).ContinueWith(task => { if (task.IsFaulted) { Console.WriteLine("SERVER: " + task.Exception.ToString()); foreach (var item in task.Exception.InnerExceptions) { Console.WriteLine("--- INNER SERVER"); Console.WriteLine(item.ToString()); } } }); Console.WriteLine("Sending"); foreach (DoMessage request in requests) { Console.WriteLine("Sending " + request.In); await call.RequestStream.WriteAsync(request); Console.WriteLine("Sent " + request.In); } await call.RequestStream.CompleteAsync(); Console.WriteLine("End Sending"); await responseReaderTask; } channel.ShutdownAsync().Wait(); Console.WriteLine("Hello World!"); }
public static void Init(string Url, DoCallBack _callBack, DoMessage _doMessage, DoShowInfo _doShowInfo) { FleckLog.Level = LogLevel.Debug; _DoCallBack = _callBack; _DoMessage = _doMessage; _DoShowInfo = _doShowInfo; //var allSockets = new List<IWebSocketConnection>(); //var server = new WebSocketServer("ws://0.0.0.0:4696"); var server = new WebSocketServer(Url); server.Start(socket => { socket.OnOpen = () => { ShowInfo("Open!"); //allSockets.Add(socket); string clientUrl = socket.ConnectionInfo.ClientIpAddress + ":" + socket.ConnectionInfo.ClientPort; string deviceMachineCode = ""; string deviceKey = ""; try { //从headers得到机器码 deviceMachineCode = socket.ConnectionInfo.Headers["deviceMachineCode"]; deviceKey = socket.ConnectionInfo.Headers["deviceKey"]; } catch { } ShowInfo("与客户端:" + clientUrl + " 建立WebSock连接!"); ShowInfo("请求deviceKey:" + deviceKey); //判断是否可以接入 if (!string.IsNullOrEmpty(deviceKey)) { bool isOk = ValidDevices.Keys.Contains(deviceKey); ShowInfo(string.Format("设备[{0}]请求接入,结果[{1}]", deviceKey, isOk)); if (isOk) { if (dic_Sockets.Keys.Contains(deviceKey)) { dic_Sockets[deviceKey] = socket; } else { dic_Sockets.Add(deviceKey, socket); } return; } } else { ShowInfo(string.Format("{0}|服务器:请求接入失败,原因:未传入DeviceKey", DateTime.Now.ToString())); } //如果不是有效的设备,则断开 socket.Close(); }; socket.OnError = (Exception ex) => { ShowInfo("OnError!" + ex.ToString()); //allSockets.Remove(socket); }; socket.OnClose = () => { ShowInfo("Close!"); //allSockets.Remove(socket); }; socket.OnMessage = message => { ShowInfo("socket.OnMessage:" + message); try { MModel_Ws.ResultInfo resultInfo = JsonConvert.DeserializeObject <MModel_Ws.ResultInfo>(message); string taskName = resultInfo.taskname; //得到请求后的返回处理 if (MessageList.Keys.Contains(taskName)) { DoCallBack callBack = MessageList[taskName]; if (callBack != null) { callBack.Invoke(resultInfo); return; } } TaskInfo taskInfo = JsonConvert.DeserializeObject <TaskInfo>(message); //如果在请求回调列表中没有找到,则处理“接收” _DoMessage?.Invoke(socket, taskInfo); } catch (Exception ex) { ShowInfo(ex.Message); } }; socket.OnPing = (byte[] ex) => { ShowInfo("OnPing!" + System.Text.Encoding.Default.GetString(ex)); socket.SendPong(ex); }; }); //var input = Console.ReadLine(); //while (input != "exit") //{ // foreach (var socket in dic_Sockets.Values) // { // socket.Send(input); // } // input = Console.ReadLine(); //} }
public MessageReceivedEventArgs(DoMessage message) { Message = message; }
/// <summary> /// вычленяет пакет из потока байт /// </summary> /// <param name="stream"></param> /// <returns>возвращает остаток от неполного пакета</returns> private IEnumerable <byte> GetPackage(IEnumerable <byte> stream) { try { //1. проверка на наличие полных пакетов в потоке if (stream.Count() <= HEADER_LENGTH + 1) { return(stream); } byte[] header = stream.Take(HEADER_LENGTH).ToArray(); byte checkSum = stream.ElementAt(HEADER_LENGTH); byte calcCheckSum = (byte)header.Sum(b => b); if (checkSum != calcCheckSum) { return new byte[] { } } ; int packageLength = (int)BitConverter.ToUInt32(header, 0); if (stream.Count() < packageLength + 1) { return(stream); } var compressed = stream.ElementAt(HEADER_LENGTH + 1) == 1; var messageBody = stream.Skip(HEADER_LENGTH + 1 + 1).Take(packageLength).ToArray(); if (compressed) { using (var msgStream = new MemoryStream(messageBody)) { using (ZipFile zipFile = ZipFile.Read(msgStream)) { foreach (var zipEntry in zipFile.Entries) { if (zipEntry.FileName == "body") { MemoryStream entryStream = new MemoryStream(); zipEntry.Extract(entryStream); messageBody = entryStream.GetBuffer(); break; } } } } } //2. обработка пакета DoMessage message = ToMessage(messageBody); //System.IO.File.AppendAllText(@"d:\foo.txt", string.Format("{0:HH:mm:ss}\t{1}\t{2}\tIN\t{3}\n", DateTime.Now, idleThreadName, instance, message)); //log.DebugFormat("[{0}] на точку соединения поступило сообщение {1}", this, message); ThreadPool.QueueUserWorkItem(arg => { //if (message is ServiceMessage) //{ // ProcessServerMessage(message as ServiceMessage); //} //else //{ ProcessMessage(message); //} }); //3. поиск остальных пакетов в потоке return(GetPackage(stream.Skip(HEADER_LENGTH + 1 + 1 + packageLength))); } catch (Exception ex) { return(new byte[] { }); } }