/// <summary> /// Send /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void ButtonF5_Click(object sender, EventArgs e) { Logger.WriteLine(MethodBase.GetCurrentMethod().Name); base.ButtonF5_Click(sender, e); // ▼▼▼ 業務処理 ▼▼▼ // メッセージ送信 string sendMsg = tboxMessage.Text; string toName = cboxTarget.Text; string fromName = tboxName.Text; TcpMessageUtility mgr; if (toName.Equals("全員")) { mgr = new TcpMessageUtility(TcpMessageUtility.HeaderAllMsg, fromName, TcpMessageUtility.TargetAll, sendMsg); } else { mgr = new TcpMessageUtility(TcpMessageUtility.HeaderTargetMsg, fromName, toName, sendMsg); } if (!TcpClientUtil.Send(mgr.GetSendMessage())) { listViewLog.Items.Add("送信に失敗しました。再接続して下さい。"); CloseAndInit(); } // ▲▲▲ 業務処理 ▲▲▲ }
/// <summary> /// DisConnect /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void ButtonF2_Click(object sender, EventArgs e) { base.ButtonF2_Click(sender, e); // ▼▼▼ 業務処理 ▼▼▼ ReadCancelTokenSource.Cancel(); TcpClientUtil.Dispose(); TcpClientUtil = null; SetControlEnabled(ActionMode.Init); // ▲▲▲ 業務処理 ▲▲▲ }
private async void CloseTcpClient() { // TCP破棄 TcpClientUtil?.Dispose(); TcpClientUtil = null; // キャンセル ReadCancelTokenSource.Cancel(); // 受信スレッド終了待ち await readLoopTask; readLoopTask?.Dispose(); readLoopTask = null; }
/// <summary> /// Connect /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void ButtonF1_Click(object sender, EventArgs e) { Logger.WriteLine(MethodBase.GetCurrentMethod().Name); base.ButtonF1_Click(sender, e); // ▼▼▼ 業務処理 ▼▼▼ if (TcpClientUtil != null) { // 既に接続している場合、再接続前に破棄する TcpClientUtil.Dispose(); } // 接続 string ip = tboxIP.Text; int.TryParse(tboxPort.Text, out int port); try { TcpClientUtil = new TcpClientManager(ip, port); listViewLog.Items.Add($"接続しました。{TcpClientUtil.GetClientIpAndPort()}->{TcpClientUtil.GetServerIpAndPort()}"); // 名前を送信 string name = tboxName.Text; TcpMessageUtility mgr = new TcpMessageUtility(TcpMessageUtility.HeaderConnect, name, TcpMessageUtility.TargetAll, name); TcpClientUtil.Send(mgr.GetSendMessage()); } catch (SocketException ex) { Debug.WriteLine(ex.ToString()); listViewLog.Items.Add(ex.Message); return; } // 読み込みループ開始 // Task停止用のトークン発行 ReadCancelTokenSource = new CancellationTokenSource(); CancellationToken cToken = ReadCancelTokenSource.Token; readLoopTask = ReadLoop(cToken); readLoopTask.ConfigureAwait(false); // ボタンの有効無効を設定 SetControlEnabled(ActionMode.Connect); // ▲▲▲ 業務処理 ▲▲▲ }
private IEnumerator Run() { // Reconnection attempts so we don't hammer the system on failure. float connectionPollTimeSec = 0.25f; TcpClient socket = null; PacketBuffer packetBuffer = new PacketBuffer(4 * 1024); System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch(); ClientConnector connector = null; while (!_quitFlag) { // First try establish a connection. while (!_quitFlag && !_connection.Connected) { if (connector == null) { connector = new ClientConnector(_connection.EndPoint); } if (!connector.Connecting) { if (connector.Connected) { socket = connector.Accept(); connector = null; _connection.Connected = true; Status = NetworkThreadStatus.Connected; _currentFrame = _totalFrames = 0u; _packetQueue.Enqueue(BuildResetPacket()); } else { connector.Abort(); connector = null; if (!_connection.AutoReconnect) { // Failed connection and no auto reconnect. Status = NetworkThreadStatus.ConnectionFailed; break; } } } if (socket == null) { // Wait the timeout period before attempting to reconnect. yield return(Workthread.CreateWait(connectionPollTimeSec)); } } timer.Start(); // Read while connected. while (!_quitFlag && TcpClientUtil.Connected(socket)) { // We have a connection. Read messages while we can. if (socket.Available > 0) { // Data available. Read from the network stream into a buffer and attempt to // read a valid message. packetBuffer.Append(socket.GetStream(), socket.Available); PacketBuffer completedPacket; bool crcOk = true; while ((completedPacket = packetBuffer.PopPacket(out crcOk)) != null || !crcOk) { if (crcOk) { // Decode and decompress collated packets. This will just return the same packet // if not collated. _collatedDecoder.SetPacket(completedPacket); while ((completedPacket = _collatedDecoder.Next()) != null) { if (completedPacket.Header.RoutingID == (ushort)RoutingID.Control) { ushort controlMessageId = completedPacket.Header.MessageID; if (controlMessageId == (ushort)ControlMessageID.EndFrame) { timer.Stop(); FrameTime = timer.ElapsedMilliseconds * 1e-3f; timer.Reset(); timer.Start(); ++_currentFrame; ++_totalFrames; } } _packetQueue.Enqueue(completedPacket); } } else { // TODO: Log CRC failure. } } } else { yield return(null); } } // Disconnected. if (socket != null) { socket.LingerState.Enabled = false; socket.Close(); socket = null; } if (_connection.Connected) { Status = NetworkThreadStatus.Disconnected; _connection.Connected = false; } if (!_connection.AutoReconnect) { break; } Status = NetworkThreadStatus.Reconnecting; } }
private async Task ReadLoop(CancellationToken cToken) { Logger.WriteLine(MethodBase.GetCurrentMethod().Name); try { while (!cToken.IsCancellationRequested) { string texts = await TcpClientUtil.ReadAsync(cToken).ConfigureAwait(false); if (texts != null) { foreach (string text in texts.Split('\n')) { Logger.WriteLine(text); TcpMessageUtility mgr = new TcpMessageUtility(text); switch (mgr.Header) { case TcpMessageUtility.HeaderConnect: // 申請した名前が登録できたか判定する // Connect,IP:Port,送信した名前,登録した名前 if (TcpClientUtil.GetClientIpAndPort().Equals(mgr.SendFromTarget)) { // 自分が送信したNAMEの返信 if (!mgr.SendToTarget.Equals(mgr.Value)) { // 別名に変更された場合、名前を変更する Invoke((Action)(() => { tboxName.Text = mgr.Value; listViewLog.Items.Add($"既に名前が使われていたため、名前を{mgr.Value}に変更しました。"); })); } } else { // 他の人が送信したNAMEの受信 Invoke((Action)(() => { listViewLog.Items.Add($"{mgr.Value}が接続しました。"); })); } // リストに追加する Invoke((Action)(() => { listBoxUser.Items.Add(mgr.Value); cboxTarget.Items.Add(mgr.Value); })); break; case TcpMessageUtility.HeaderName: // リストに追加する Invoke((Action)(() => { listBoxUser.Items.Add(mgr.Value); cboxTarget.Items.Add(mgr.Value); })); break; case TcpMessageUtility.HeaderTargetMsg: Invoke((Action)(() => { listViewLog.Items.Add(mgr.GetRecvTargetMessage()); })); break; case TcpMessageUtility.HeaderAllMsg: default: Invoke((Action)(() => { listViewLog.Items.Add(mgr.GetRecvMessage()); })); break; } } } else { Logger.WriteLine("切断されました。"); Invoke((Action)(() => { listViewLog.Items.Add("切断されました。"); })); break; } } } catch (ObjectDisposedException ex) // EOF. { Debug.WriteLine(ex.ToString()); Invoke((Action)(() => { listViewLog.Items.Add("切断されました。"); })); } //catch (Exception ex) //{ // Debug.WriteLine(ex.ToString()); // try // { // Invoke((Action)(() => // { // listViewLog.Items.Add(ex.Message); // })); // } // catch (Exception ex2) // { // Debug.WriteLine(ex.Message); // Debug.WriteLine(ex2.Message); // } //} }
public void Run(FrameDisplay frameDisplay) { int connectionPollTimeSecMs = 250; TcpClient socket = null; PacketBuffer packetBuffer = null; CollatedPacketDecoder collatedDecoder = new CollatedPacketDecoder(); BinaryWriter recordingWriter = null; #if PACKET_TIMING Stopwatch timer = new Stopwatch(); #endif // PACKET_TIMING bool once = true; Console.CancelKeyPress += new ConsoleCancelEventHandler(ControlCHandler); if (!Quiet) { Console.WriteLine(string.Format("Connecting to {0}", ServerEndPoint)); } while (!Quit && (Persist || once)) { once = false; // First try establish a connection. while (!Quit && !Connected) { if ((socket = AttemptConnection()) != null) { #if PACKET_TIMING timer.Reset(); timer.Start(); #endif // PACKET_TIMING TotalFrames = 0u; frameDisplay.Reset(); if (!Quiet) { frameDisplay.Start(); } recordingWriter = CreateOutputWriter(); if (recordingWriter != null) { Connected = true; // Create a new packet buffer for this connection. packetBuffer = new PacketBuffer(4 * 1024); } Log.Flush(); } else { Log.Flush(); // Wait the timeout period before attempting to reconnect. System.Threading.Thread.Sleep(connectionPollTimeSecMs); } } // Read while connected or data still available. while (!Quit && socket != null && (TcpClientUtil.Connected(socket) || socket.Available > 0)) { // We have a connection. Read messages while we can. if (socket.Available > 0) { // Data available. Read from the network stream into a buffer and attempt to // read a valid message. packetBuffer.Append(socket.GetStream(), socket.Available); PacketBuffer completedPacket; bool exportPacket = true; bool crcOk = true; while ((completedPacket = packetBuffer.PopPacket(out crcOk)) != null || !crcOk) { if (crcOk) { if (packetBuffer.DroppedByteCount != 0) { Console.Error.WriteLine("Dropped {0} bad bytes", packetBuffer.DroppedByteCount); packetBuffer.DroppedByteCount = 0; } if (DecodeMode == Mode.Passthrough) { completedPacket.ExportTo(recordingWriter); // Approximate packets as frames. Not exactly correct though. if (completedPacket.Header.RoutingID == (ushort)RoutingID.Control) { if (completedPacket.Header.MessageID == (ushort)ControlMessageID.EndFrame) { ++TotalFrames; frameDisplay.IncrementFrame(); #if PACKET_TIMING if (TotalFrames >= PacketLimit) { timer.Stop(); Quit = true; } #endif // PACKET_TIMING } } continue; } // Decode and decompress collated packets. This will just return the same packet // if not collated. collatedDecoder.SetPacket(completedPacket); while ((completedPacket = collatedDecoder.Next()) != null) { //Console.WriteLine("Msg: {0} {1}", completedPacket.Header.RoutingID, completedPacket.Header.MessageID); switch (completedPacket.Header.RoutingID) { case (ushort)RoutingID.Control: ushort controlMessageId = completedPacket.Header.MessageID; if (controlMessageId == (ushort)ControlMessageID.EndFrame) { ++TotalFrames; frameDisplay.IncrementFrame(); #if PACKET_TIMING if (TotalFrames >= PacketLimit) { timer.Stop(); Quit = true; } #endif // PACKET_TIMING } break; case (ushort)RoutingID.ServerInfo: NetworkReader packetReader = new NetworkReader(completedPacket.CreateReadStream(true)); _serverInfo.Read(packetReader); exportPacket = false; break; default: break; } if (exportPacket) { completedPacket.ExportTo(recordingWriter); } } } else { Console.Error.WriteLine("CRC Failure"); // TODO: Log CRC failure. } } Log.Flush(); } else { Log.Flush(); System.Threading.Thread.Sleep(0); } } frameDisplay.Stop(); if (packetBuffer != null && packetBuffer.DroppedByteCount != 0) { Console.Error.WriteLine("Dropped {0} bad bytes", packetBuffer.DroppedByteCount); packetBuffer.DroppedByteCount = 0; } if (recordingWriter != null) { FinaliseOutput(recordingWriter, TotalFrames); recordingWriter.Flush(); recordingWriter.Close(); recordingWriter = null; } if (!Quiet) { Console.WriteLine("Connection closed"); } // Disconnected. if (socket != null) { socket.Close(); socket = null; } Connected = false; // GC to force flushing streams and collect other resource. GC.Collect(); } #if PACKET_TIMING Console.WriteLine($"Processed {PacketLimit} packets in {timer.ElapsedMilliseconds}ms"); #endif // PACKET_TIMING }
private IEnumerator Run() { // Reconnection attempts so we don't hammer the system on failure. float connectionPollTimeSec = 0.25f; TcpClient socket = null; PacketBuffer packetBuffer = new PacketBuffer(4 * 1024); System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch(); ClientConnector connector = null; while (!_quitFlag) { // First try establish a connection. while (!_quitFlag && !_connection.Connected) { if (connector == null) { connector = new ClientConnector(_connection.EndPoint); } if (!connector.Connecting) { if (connector.Connected) { socket = connector.Accept(); connector = null; _connection.Connected = true; Status = NetworkThreadStatus.Connected; _currentFrame = _totalFrames = 0u; _packetQueue.Enqueue(BuildResetPacket()); } else { connector.Abort(); connector = null; if (!_connection.AutoReconnect) { // Failed connection and no auto reconnect. Status = NetworkThreadStatus.ConnectionFailed; break; } } } if (socket == null) { // Wait the timeout period before attempting to reconnect. yield return(Workthread.CreateWait(connectionPollTimeSec)); } } timer.Start(); // Read while connected. while (!_quitFlag && TcpClientUtil.Connected(socket)) { // We have a connection. Read messages while we can. if (socket.Available > 0) { // Data available. Read from the network stream into a buffer and attempt to // read a valid message. packetBuffer.Append(socket.GetStream(), socket.Available); PacketBuffer completedPacket; bool crcOk = true; while ((completedPacket = packetBuffer.PopPacket(out crcOk)) != null || !crcOk) { if (crcOk) { // Decode and decompress collated packets. This will just return the same packet // if not collated. _collatedDecoder.SetPacket(completedPacket); while ((completedPacket = _collatedDecoder.Next()) != null) { if (completedPacket.Header.RoutingID == (ushort)RoutingID.Control) { ushort controlMessageId = completedPacket.Header.MessageID; if (controlMessageId == (ushort)ControlMessageID.EndFrame) { // Add a frame flush flag to every end frame message to ensure the render thread renders. // TODO: consider a way to frame skip in a live visualisation link. byte[] packetData = completedPacket.Data; int memberOffset = PacketHeader.Size + Marshal.OffsetOf(typeof(ControlMessage), "ControlFlags").ToInt32(); uint controlFlags = BitConverter.ToUInt32(packetData, memberOffset); controlFlags = Endian.FromNetwork(controlFlags); // Add the flush flag controlFlags |= (uint)EndFrameFlag.Flush; // Convert back to bytes and copy into the packet buffer. byte[] frameNumberBytes = BitConverter.GetBytes(Endian.ToNetwork(controlFlags)); Array.Copy(frameNumberBytes, 0, packetData, memberOffset, frameNumberBytes.Length); // Recalculate the CRC as we've modified the packet. completedPacket.UpdateCrc(); // Update the frame timer.Stop(); FrameTime = timer.ElapsedMilliseconds * 1e-3f; timer.Reset(); timer.Start(); ++_currentFrame; ++_totalFrames; } } _packetQueue.Enqueue(completedPacket); } } else { // TODO: Log CRC failure. } } } else { yield return(null); } } // Disconnected. if (socket != null) { socket.LingerState.Enabled = false; socket.Close(); socket = null; } if (_connection.Connected) { Status = NetworkThreadStatus.Disconnected; _connection.Connected = false; } if (!_connection.AutoReconnect) { break; } Status = NetworkThreadStatus.Reconnecting; } }