MyBitConverter <long> _NotifyIDConverter = new MyBitConverter <long>(); // converter dùng để convert byte thành long, số long nhận được chính là notificationID được yêu cầu bởi client #endregion public ClientCommunicator(Params.RawNotificationClientCommunicatorParams param) { _Param = param; server = new TCPServer.TCPServer(_Param.ListenPort); // đăng ký sự kiện nhận được một gói tin từ client server.OnPacketReceived += (s, e) => { FromClientPacket packet = null; try { packet = PacketConverter.BytesToObject(e.Data); } catch { // Bên ngoài gửi gói tin không đúng định dạng, có thể do lỗi đường truyền cũng có thể do ý đồ phá hoại e.RespondToClient(ResultConverter.ObjectToBytes(new FromServerPacket(ServerResult.DataCorrupt, null))); e.CloseConnection(); return; } switch (packet.Type) { case FromClientPacketType.Register: { RegisterPacketData data = packet.Data as RegisterPacketData; e.RespondToClient(ResultConverter.ObjectToBytes(new FromServerPacket(Register(data), null))); e.CloseConnection(); } break; case FromClientPacketType.GetNotificationContent: { GetNotificationContentPacketData data = packet.Data as GetNotificationContentPacketData; ServerResult result; // lấy ra content byte[] content = NotificationContent(data.NotificationID, out result); e.RespondToClient(ResultConverter.ObjectToBytes(new FromServerPacket(result, content))); e.CloseConnection(); } break; } }; }
internal ServerCommunicator(int listenPort, int notifyPort, Func <ServerInfo> OnServerInfoRequestReceived, Action OnSendAllNotificationRequestReceived) { _ListenPort = listenPort; _NotifyPort = notifyPort; server = new TCPServer.TCPServer(_ListenPort); _NotifyServer = new TCPServer.TCPServer(_NotifyPort, true); server.OnPacketReceived += (s, e) => { System.Diagnostics.Debug.WriteLine("Đã nhận được yêu cầu"); FromClientPacket ReceivedPacket = null; try { ReceivedPacket = _FromClientConverter.BytesToObject(e.Data); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Gói tin bị lỗi khi vận chuyển"); e.RespondToClient(_FromServerConverter.ObjectToBytes(new FromServerPacket(FromServerPacketType.DataCorrupted, ex))); return; } // Giữa 2 server với nhau phải luôn được kết nối, vì vậy khi giao tiếp xong thì vẫn để kết nối đó cho lần tiếp theo switch (ReceivedPacket.PacketType) { case FromClientPacketType.AddNotification: { e.RespondToClient(_FromServerConverter.ObjectToBytes(new FromServerPacket(FromServerPacketType.AddNotificationResponse, AddNotification(ReceivedPacket.Data as AddNotificationPacketData)))); break; } case FromClientPacketType.RequestServerInfo: { e.RespondToClient(_FromServerConverter.ObjectToBytes(new FromServerPacket(FromServerPacketType.ServerInfo, OnServerInfoRequestReceived()))); break; } case FromClientPacketType.SendAllNotification: { // nhận được yêu cầu gửi thì khỏi cần hồi âm OnSendAllNotificationRequestReceived(); break; } } }; }
/// <summary> /// Gửi một đối tượng dữ liệu bất kì tới WNS /// </summary> /// <param name="device">Thiết bị cần nhận thông báo, giúp việc xóa thiết bị dễ dàng hơn khi xảy ra lỗi sai URI</param> /// <param name="sendobj">Object cần gửi</param> /// <param name="devicenoti">Đưa ra việc gửi cho thiết bị nào và gửi thông báo nào, giúp việc xóa nó sẽ dễ dàng hơn nếu gửi thông báo thành công</param> public void Send(Device device, T sendobj, DeviceNotification devicenoti) { bool flag = false; byte[] data = Tconverter.ObjectToBytes(sendobj); #region chuẩn bị http request và các header phù hợp để gửi raw notification HttpWebRequest request = null; try { request = HttpWebRequest.Create(device.URI) as HttpWebRequest; } catch (Exception ex) { BadURIErrorOccurred(this, new DelegatesAndEnums.BadURIEventArgs(ex, device)); return; } request.Method = "POST"; request.Headers.Add("X-WNS-Type", "wns/raw"); request.Headers.Add("X-WNS-Cache-Policy", "cache"); request.Headers.Add("X-WNS-RequestForStatus", "true"); request.ContentType = "application/octet-stream"; request.Headers.Add("Authorization", String.Format("Bearer {0}", token.Token)); #endregion // chuyển đối tượng cần gửi về dạng mảng byte để có thể gửi đi #region Gửi Notification try { // gửi yêu cầu có nội dung là mảng byte trên tới uri using (Stream requestStream = request.GetRequestStream()) requestStream.Write(data, 0, data.Length); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Lỗi xảy ra"); InternetOrFirewallErrorOccurred(this, ex); return; } #endregion #region nhận về Response try { // nhận về response HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse(); SendSuccessed(this, devicenoti); System.Diagnostics.Debug.WriteLine(webResponse.Headers["X-WNS-Status"]); System.Diagnostics.Debug.WriteLine(webResponse.Headers["X-WNS-DeviceConnectionStatus"]); flag = true; } catch (WebException webException) { #region Phân tích exception // việc gửi yêu cầu bị lỗi không phải do giao thức (các nguyên nhân khác, có thể do mạng hoặc do tường lửa) if (webException.Status != WebExceptionStatus.ProtocolError) { InternetOrFirewallErrorOccurred(this, webException); return; } // code chạy xuống dưới đây có nghĩa là lỗi giao thức // lấy status code HttpStatusCode status = ((HttpWebResponse)webException.Response).StatusCode; if (status == HttpStatusCode.Unauthorized) // nếu là lỗi do token hết hạn { try { token.RenewToken(); } catch (UnauthorizedAccessException uex) { WrongPackageSIDOrSecretKey(this, uex); return; } catch (WebException wex) { InternetOrFirewallErrorOccurred(this, wex); return; } this.Send(device, sendobj, devicenoti); } else if (status == HttpStatusCode.Gone || status == HttpStatusCode.NotFound || status == HttpStatusCode.Forbidden) // Lỗi phát sinh do URI hết hạn, không tồn tại hoặc sai nên server không được phép gửi tới { BadURIErrorOccurred(this, new DelegatesAndEnums.BadURIEventArgs(webException, device)); return; } else if (status == HttpStatusCode.NotAcceptable) // Lỗi do gửi quá nhiều thông báo tới này trong một khoảng thời gian quá ngắn { NotAccecptableErrorOccurred(this, webException); return; } else // Lỗi do một nguyên nhân khác { UnknowErrorOccurred(webException, webException); return; }; #endregion } #endregion }