From ac15e63a0ad778e8d39301c2729688d526cad4d9 Mon Sep 17 00:00:00 2001 From: syneffort Date: Fri, 6 Oct 2023 16:35:40 +0900 Subject: [PATCH] tap server, client --- MySolution/MySolution.sln | 18 +++ MySolution/STcpHelper/STcpClient.cs | 103 +++++++++++++++++ MySolution/STcpHelper/STcpHelper.csproj | 9 ++ MySolution/STcpHelper/STcpServer.cs | 123 +++++++++++++++++++++ MySolution/SerialComApp/SerialCommApp.resx | 2 +- MySolution/TAPClient/Program.cs | 21 ++++ MySolution/TAPClient/TAPClient.csproj | 14 +++ MySolution/TAPServer/Program.cs | 22 ++++ MySolution/TAPServer/TAPServer.csproj | 14 +++ 9 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 MySolution/STcpHelper/STcpClient.cs create mode 100644 MySolution/STcpHelper/STcpHelper.csproj create mode 100644 MySolution/STcpHelper/STcpServer.cs create mode 100644 MySolution/TAPClient/Program.cs create mode 100644 MySolution/TAPClient/TAPClient.csproj create mode 100644 MySolution/TAPServer/Program.cs create mode 100644 MySolution/TAPServer/TAPServer.csproj diff --git a/MySolution/MySolution.sln b/MySolution/MySolution.sln index f27f0aa..ec58baf 100644 --- a/MySolution/MySolution.sln +++ b/MySolution/MySolution.sln @@ -7,6 +7,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp", "ConsoleApp\Co EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SerialCommApp", "SerialComApp\SerialCommApp.csproj", "{21CB97AA-1550-4C56-894D-76E6B75B91DC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TAPServer", "TAPServer\TAPServer.csproj", "{4CA4FF89-FA3A-42C0-8A66-D84F9C4F8EBC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STcpHelper", "STcpHelper\STcpHelper.csproj", "{86B2F7FF-8D76-4C46-91E4-E83F7EED4A68}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TAPClient", "TAPClient\TAPClient.csproj", "{6F0DC5AC-D046-4506-A339-EC50C18C4CDB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,6 +27,18 @@ Global {21CB97AA-1550-4C56-894D-76E6B75B91DC}.Debug|Any CPU.Build.0 = Debug|Any CPU {21CB97AA-1550-4C56-894D-76E6B75B91DC}.Release|Any CPU.ActiveCfg = Release|Any CPU {21CB97AA-1550-4C56-894D-76E6B75B91DC}.Release|Any CPU.Build.0 = Release|Any CPU + {4CA4FF89-FA3A-42C0-8A66-D84F9C4F8EBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CA4FF89-FA3A-42C0-8A66-D84F9C4F8EBC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CA4FF89-FA3A-42C0-8A66-D84F9C4F8EBC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4CA4FF89-FA3A-42C0-8A66-D84F9C4F8EBC}.Release|Any CPU.Build.0 = Release|Any CPU + {86B2F7FF-8D76-4C46-91E4-E83F7EED4A68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86B2F7FF-8D76-4C46-91E4-E83F7EED4A68}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86B2F7FF-8D76-4C46-91E4-E83F7EED4A68}.Release|Any CPU.ActiveCfg = Release|Any CPU + {86B2F7FF-8D76-4C46-91E4-E83F7EED4A68}.Release|Any CPU.Build.0 = Release|Any CPU + {6F0DC5AC-D046-4506-A339-EC50C18C4CDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6F0DC5AC-D046-4506-A339-EC50C18C4CDB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6F0DC5AC-D046-4506-A339-EC50C18C4CDB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6F0DC5AC-D046-4506-A339-EC50C18C4CDB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MySolution/STcpHelper/STcpClient.cs b/MySolution/STcpHelper/STcpClient.cs new file mode 100644 index 0000000..5521427 --- /dev/null +++ b/MySolution/STcpHelper/STcpClient.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +namespace STcpHelper +{ + public class STcpClient + { + private CancellationTokenSource _cts = new CancellationTokenSource(); + + public event EventHandler MessageCallback; + public event EventHandler ErrorCallback; + + private TcpClient _client; + private NetworkStream _stream; + + public async void Connect(string ip, int port) + { + try + { + _client = new TcpClient(); + await _client.ConnectAsync(ip, port); + _stream = _client.GetStream(); + + _cts = new CancellationTokenSource(); + _ = Task.Run(async () => + { + byte[] readBuffer = new byte[1024]; + while (true) + { + Thread.Sleep(50); + if (_cts.IsCancellationRequested) + break; + + int bytesRead = await this._stream.ReadAsync(readBuffer); + if (bytesRead < 1) + break; + + string message = Encoding.UTF8.GetString(readBuffer, 0, bytesRead); + if (this.MessageCallback != null) + this.MessageCallback(this, message); + } + }, _cts.Token); + } + catch (Exception ex) + { + WriteError(ex); + } + } + + public async void SendMessage(string message) + { + try + { + byte[] sendBytes = Encoding.UTF8.GetBytes(message); + await _stream.WriteAsync(sendBytes); + } + catch (Exception ex) + { + WriteError(ex); + } + } + + public void Close() + { + try + { + if (_client == null) + return; + + if (_stream != null) + { + _stream.Flush(); + _stream.Close(); + } + + _cts.Cancel(); + + _client.Close(); + _client.Dispose(); + } + catch (Exception ex) + { + WriteError(ex); + } + } + + private void WriteMessage(string message) + { + if (this.MessageCallback != null) + this.MessageCallback(this, message); + } + + private void WriteError(Exception ex) + { + if (this.ErrorCallback != null) + this.ErrorCallback(this, ex); + } + } +} diff --git a/MySolution/STcpHelper/STcpHelper.csproj b/MySolution/STcpHelper/STcpHelper.csproj new file mode 100644 index 0000000..132c02c --- /dev/null +++ b/MySolution/STcpHelper/STcpHelper.csproj @@ -0,0 +1,9 @@ + + + + net6.0 + enable + enable + + + diff --git a/MySolution/STcpHelper/STcpServer.cs b/MySolution/STcpHelper/STcpServer.cs new file mode 100644 index 0000000..dfbd447 --- /dev/null +++ b/MySolution/STcpHelper/STcpServer.cs @@ -0,0 +1,123 @@ +using System.Net; +using System.Net.Sockets; +using System.Text; + +namespace STcpHelper +{ + public class STcpServer + { + private CancellationTokenSource _cts; + + private List _clients; + + private readonly int BUFFER_SIZE; + private int _port; + + private TcpListener _listener; + + public event EventHandler MessageCallback; + public event EventHandler ErrorCallback; + + public STcpServer(int port, int bufferSize = 1024) + { + _port = port; + BUFFER_SIZE = bufferSize; + _clients = new List(); + } + + public async void Start() + { + _listener = new TcpListener(IPAddress.Parse("127.0.0.1"), _port); + _listener.Start(); + WriteMessage("Server start..."); + + _cts = new CancellationTokenSource(); + while (true) + { + if (_cts.IsCancellationRequested) + break; + + TcpClient client = await _listener.AcceptTcpClientAsync(); + _clients.Add(client); + WriteMessage($"Client accepted({client.Client.RemoteEndPoint.ToString()})"); + + + _cts = new CancellationTokenSource(); + _ = Task.Run(async () => + { + using (NetworkStream stream = client.GetStream()) + { + byte[] buffer = new byte[BUFFER_SIZE]; + int bytesRead; + try + { + while ((bytesRead = await stream.ReadAsync(buffer, 0, BUFFER_SIZE)) > 0) + { + string message = Encoding.UTF8.GetString(buffer, 0, bytesRead); + WriteMessage($"[{client.Client.RemoteEndPoint.ToString()}] {message}"); + + // Broadcast + BroadcastMessage(message, client); + + if (!IsClientConnected(client)) + break; + } + } + catch (Exception ex) + { + WriteError(ex); + } + + WriteMessage($"Client disconnected({client.Client.RemoteEndPoint.ToString()})"); + client.Close(); + _clients.Remove(client); + } + }, _cts.Token); + } + } + + public void Stop() + { + _cts.Cancel(); + } + + private void BroadcastMessage(string message, TcpClient sender) + { + byte[] resonseByte = Encoding.UTF8.GetBytes(message); + foreach (TcpClient client in _clients) + { + if (client != sender && IsClientConnected(client)) + client.GetStream().WriteAsync(resonseByte, 0, resonseByte.Length); + } + } + + private bool IsClientConnected(TcpClient client) + { + try + { + if (client != null && + client.Client != null && + client.Client.Connected) + return true; + } + catch (Exception ex) + { + WriteError(ex); + } + + return false; + } + + private void WriteMessage(string message) + { + if (this.MessageCallback != null) + this.MessageCallback(this, message); + } + + private void WriteError(Exception ex) + { + if (this.ErrorCallback != null) + this.ErrorCallback(this, ex); + } + } +} \ No newline at end of file diff --git a/MySolution/SerialComApp/SerialCommApp.resx b/MySolution/SerialComApp/SerialCommApp.resx index 74f57dc..6b10039 100644 --- a/MySolution/SerialComApp/SerialCommApp.resx +++ b/MySolution/SerialComApp/SerialCommApp.resx @@ -121,7 +121,7 @@ iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL - EAAACxABrSO9dQAAAsBJREFUaEPt2cnLTXEcx/FrzJCphJ0F2diIbEQokWFnzhClyFB6yEJEyh+gUMaU + DwAACw8BkvkDpQAAAsBJREFUaEPt2cnLTXEcx/FrzJCphJ0F2diIbEQokWFnzhClyFB6yEJEyh+gUMaU WdlYWLBRiszjAmFjaUgZMvP+LE6dTp9z7jnnnt990PnUa/N07+/7u/ee3/g06tSpU+efzihswFncxzt8 x1e8xm0cx2oMx1+R7liOG/hdwC9cxXx0Q6dkNp7DdbCIh5iKtqUvjsF1piz9InvQE0EzDPfgOlGFKxiE IBmKZ3CF03zBt8TfmrmFAag0fXAXrmCcXrMd4zAYUYZgInbjCdx74y6h0sF9BK5QRANxJvKkKxaj2QSw diff --git a/MySolution/TAPClient/Program.cs b/MySolution/TAPClient/Program.cs new file mode 100644 index 0000000..9a93e79 --- /dev/null +++ b/MySolution/TAPClient/Program.cs @@ -0,0 +1,21 @@ +using STcpHelper; + +namespace TAPClient +{ + internal class Program + { + static void Main(string[] args) + { + STcpClient client = new STcpClient(); + client.ErrorCallback += ((sender, ex) => { Console.WriteLine($"[ERR] {ex.Message}"); }); + client.MessageCallback += ((sender, msg) => { Console.WriteLine(msg); }); + client.Connect("127.0.0.1", 8207); + + while (true) + { + string message = Console.ReadLine(); + client.SendMessage(message); + } + } + } +} \ No newline at end of file diff --git a/MySolution/TAPClient/TAPClient.csproj b/MySolution/TAPClient/TAPClient.csproj new file mode 100644 index 0000000..8c59ce3 --- /dev/null +++ b/MySolution/TAPClient/TAPClient.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + diff --git a/MySolution/TAPServer/Program.cs b/MySolution/TAPServer/Program.cs new file mode 100644 index 0000000..167c360 --- /dev/null +++ b/MySolution/TAPServer/Program.cs @@ -0,0 +1,22 @@ +using STcpHelper; + +namespace TAPServer +{ + internal class Program + { + static void Main(string[] args) + { + STcpServer server = new STcpServer(8207); + server.ErrorCallback += ((sender, ex) => { Console.WriteLine($"[ERR] {ex.Message}"); }); + server.MessageCallback += ((sender, msg) => { Console.WriteLine(msg); }); + server.Start(); + + while (true) + { + string command = Console.ReadLine(); + if (command == "exit") + server.Stop(); + } + } + } +} \ No newline at end of file diff --git a/MySolution/TAPServer/TAPServer.csproj b/MySolution/TAPServer/TAPServer.csproj new file mode 100644 index 0000000..8c59ce3 --- /dev/null +++ b/MySolution/TAPServer/TAPServer.csproj @@ -0,0 +1,14 @@ + + + + Exe + net6.0 + enable + enable + + + + + + +