diff --git a/Examples/PacketEchoClient/.editorconfig b/Examples/PacketEchoClient/.editorconfig
new file mode 100644
index 0000000..67a80f6
--- /dev/null
+++ b/Examples/PacketEchoClient/.editorconfig
@@ -0,0 +1,124 @@
+# .editorconfig에 대해 자세히 알아보려면 다음을 참조하세요. https://aka.ms/editorconfigdocs
+###############################
+# Core EditorConfig Options #
+###############################
+root = true
+# All files
+[*]
+indent_style = space
+# Code files
+[*.{cs,csx,vb,vbx}]
+indent_size = 4
+insert_final_newline = true
+charset = utf-8-bom
+###############################
+# .NET Coding Conventions #
+###############################
+[*.{cs,vb}]
+# Organize usings
+dotnet_sort_system_directives_first = true
+# this. preferences
+dotnet_style_qualification_for_field = false:silent
+dotnet_style_qualification_for_property = false:silent
+dotnet_style_qualification_for_method = false:silent
+dotnet_style_qualification_for_event = false:silent
+# Language keywords vs BCL types preferences
+dotnet_style_predefined_type_for_locals_parameters_members = true:silent
+dotnet_style_predefined_type_for_member_access = true:silent
+# Parentheses preferences
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
+# Modifier preferences
+dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
+dotnet_style_readonly_field = true:suggestion
+# Expression-level preferences
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_auto_properties = true:silent
+dotnet_style_prefer_conditional_expression_over_assignment = true:silent
+dotnet_style_prefer_conditional_expression_over_return = true:silent
+###############################
+# Naming Conventions #
+###############################
+# Style Definitions
+dotnet_naming_style.pascal_case_style.capitalization = pascal_case
+# Use PascalCase for constant fields
+dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
+dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
+dotnet_naming_symbols.constant_fields.applicable_kinds = field
+dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
+dotnet_naming_symbols.constant_fields.required_modifiers = const
+###############################
+# C# Coding Conventions #
+###############################
+[*.cs]
+# var preferences
+csharp_style_var_for_built_in_types = true:silent
+csharp_style_var_when_type_is_apparent = true:silent
+csharp_style_var_elsewhere = true:silent
+# Expression-bodied members
+csharp_style_expression_bodied_methods = false:silent
+csharp_style_expression_bodied_constructors = false:silent
+csharp_style_expression_bodied_operators = false:silent
+csharp_style_expression_bodied_properties = true:silent
+csharp_style_expression_bodied_indexers = true:silent
+csharp_style_expression_bodied_accessors = true:silent
+# Pattern matching preferences
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
+# Null-checking preferences
+csharp_style_throw_expression = true:suggestion
+csharp_style_conditional_delegate_call = true:suggestion
+# Modifier preferences
+csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
+# Expression-level preferences
+csharp_prefer_braces = true:silent
+csharp_style_deconstructed_variable_declaration = true:suggestion
+csharp_prefer_simple_default_expression = true:suggestion
+csharp_style_pattern_local_over_anonymous_function = true:suggestion
+csharp_style_inlined_variable_declaration = true:suggestion
+###############################
+# C# Formatting Rules #
+###############################
+# New line preferences
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_between_query_expression_clauses = true
+# Indentation preferences
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = flush_left
+# Space preferences
+csharp_space_after_cast = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_parentheses = false
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+# Wrapping preferences
+csharp_preserve_single_line_statements = true
+csharp_preserve_single_line_blocks = true
+###############################
+# VB Coding Conventions #
+###############################
+[*.vb]
+# Modifier preferences
+visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion
diff --git a/Examples/PacketEchoClient/PacketEchoClient.csproj b/Examples/PacketEchoClient/PacketEchoClient.csproj
index edebcc8..c997b9b 100644
--- a/Examples/PacketEchoClient/PacketEchoClient.csproj
+++ b/Examples/PacketEchoClient/PacketEchoClient.csproj
@@ -47,6 +47,7 @@
+
diff --git a/Examples/PacketEchoServer/.editorconfig b/Examples/PacketEchoServer/.editorconfig
new file mode 100644
index 0000000..67a80f6
--- /dev/null
+++ b/Examples/PacketEchoServer/.editorconfig
@@ -0,0 +1,124 @@
+# .editorconfig에 대해 자세히 알아보려면 다음을 참조하세요. https://aka.ms/editorconfigdocs
+###############################
+# Core EditorConfig Options #
+###############################
+root = true
+# All files
+[*]
+indent_style = space
+# Code files
+[*.{cs,csx,vb,vbx}]
+indent_size = 4
+insert_final_newline = true
+charset = utf-8-bom
+###############################
+# .NET Coding Conventions #
+###############################
+[*.{cs,vb}]
+# Organize usings
+dotnet_sort_system_directives_first = true
+# this. preferences
+dotnet_style_qualification_for_field = false:silent
+dotnet_style_qualification_for_property = false:silent
+dotnet_style_qualification_for_method = false:silent
+dotnet_style_qualification_for_event = false:silent
+# Language keywords vs BCL types preferences
+dotnet_style_predefined_type_for_locals_parameters_members = true:silent
+dotnet_style_predefined_type_for_member_access = true:silent
+# Parentheses preferences
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
+# Modifier preferences
+dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
+dotnet_style_readonly_field = true:suggestion
+# Expression-level preferences
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_auto_properties = true:silent
+dotnet_style_prefer_conditional_expression_over_assignment = true:silent
+dotnet_style_prefer_conditional_expression_over_return = true:silent
+###############################
+# Naming Conventions #
+###############################
+# Style Definitions
+dotnet_naming_style.pascal_case_style.capitalization = pascal_case
+# Use PascalCase for constant fields
+dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
+dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
+dotnet_naming_symbols.constant_fields.applicable_kinds = field
+dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
+dotnet_naming_symbols.constant_fields.required_modifiers = const
+###############################
+# C# Coding Conventions #
+###############################
+[*.cs]
+# var preferences
+csharp_style_var_for_built_in_types = true:silent
+csharp_style_var_when_type_is_apparent = true:silent
+csharp_style_var_elsewhere = true:silent
+# Expression-bodied members
+csharp_style_expression_bodied_methods = false:silent
+csharp_style_expression_bodied_constructors = false:silent
+csharp_style_expression_bodied_operators = false:silent
+csharp_style_expression_bodied_properties = true:silent
+csharp_style_expression_bodied_indexers = true:silent
+csharp_style_expression_bodied_accessors = true:silent
+# Pattern matching preferences
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
+# Null-checking preferences
+csharp_style_throw_expression = true:suggestion
+csharp_style_conditional_delegate_call = true:suggestion
+# Modifier preferences
+csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
+# Expression-level preferences
+csharp_prefer_braces = true:silent
+csharp_style_deconstructed_variable_declaration = true:suggestion
+csharp_prefer_simple_default_expression = true:suggestion
+csharp_style_pattern_local_over_anonymous_function = true:suggestion
+csharp_style_inlined_variable_declaration = true:suggestion
+###############################
+# C# Formatting Rules #
+###############################
+# New line preferences
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_between_query_expression_clauses = true
+# Indentation preferences
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = flush_left
+# Space preferences
+csharp_space_after_cast = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_parentheses = false
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+# Wrapping preferences
+csharp_preserve_single_line_statements = true
+csharp_preserve_single_line_blocks = true
+###############################
+# VB Coding Conventions #
+###############################
+[*.vb]
+# Modifier preferences
+visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion
diff --git a/Examples/PacketEchoServer/PacketEchoServer.csproj b/Examples/PacketEchoServer/PacketEchoServer.csproj
index 8baa008..cda8f7f 100644
--- a/Examples/PacketEchoServer/PacketEchoServer.csproj
+++ b/Examples/PacketEchoServer/PacketEchoServer.csproj
@@ -47,6 +47,7 @@
+
diff --git a/SimpleTcp/Client/BaseTcpClient.cs b/SimpleTcp/Client/BaseTcpClient.cs
index ab1abb0..8e828fa 100644
--- a/SimpleTcp/Client/BaseTcpClient.cs
+++ b/SimpleTcp/Client/BaseTcpClient.cs
@@ -121,8 +121,12 @@ public void Disconnect()
{
lock(syncObject)
{
- tcpClient?.Close();
- tcpClient = null;
+ try
+ {
+ tcpClient?.Close();
+ tcpClient = null;
+ }
+ catch { }
buffer = null;
ringBuffer = null;
diff --git a/SimpleTcp/Server/BaseTcpServer.cs b/SimpleTcp/Server/BaseTcpServer.cs
index 501f4f7..67d1ade 100644
--- a/SimpleTcp/Server/BaseTcpServer.cs
+++ b/SimpleTcp/Server/BaseTcpServer.cs
@@ -9,29 +9,29 @@
namespace SimpleTcp.Server
{
- public abstract class BaseTcpServer : IDisposable
- {
- #region Properties
- ///
+ public abstract class BaseTcpServer : IDisposable
+ {
+ #region Properties
+ ///
/// Server is started
///
- public bool IsStarted { get => (tcpListener != null); }
+ public bool IsStarted { get => (tcpListener != null); }
- ///
+ ///
/// Connected clients
///
- public IClient[] Clients
- {
- get
- {
- lock (syncObject)
- {
- return connections.ToArray();
- }
- }
- }
-
- ///
+ public IClient[] Clients
+ {
+ get
+ {
+ lock (syncObject)
+ {
+ return connections.ToArray();
+ }
+ }
+ }
+
+ ///
/// Opened Server Port
///
public int Port { get => (tcpListener?.LocalEndpoint as IPEndPoint)?.Port ?? -1; }
@@ -45,23 +45,23 @@ public IClient[] Clients
/// Get Total sended bytes count
///
public long TotalSendedBytes { get; private set; }
- #endregion
+ #endregion
- #region Private Member
- private object syncObject = new object();
- private TcpListener tcpListener = null;
- private List connections = new List();
- #endregion
+ #region Private Member
+ private object syncObject = new object();
+ private TcpListener tcpListener = null;
+ private List connections = new List();
+ #endregion
+
+ #region Protected Member
- #region Protected Member
-
- #endregion
+ #endregion
#region Public Member
///
/// Client connected event handler
///
- public event ClientConnectedHandler ClientConnected;
+ public event ClientConnectedHandler ClientConnected;
///
/// Client disconnected event handler
@@ -78,7 +78,7 @@ public IClient[] Clients
/// If you specify a valid port, the server starts immediately.
public BaseTcpServer(int port = -1)
{
- if(port > 0)
+ if (port > 0)
{
Start(port);
}
@@ -90,7 +90,7 @@ public BaseTcpServer(int port = -1)
///
/// Server port
public void Start(int port)
- {
+ {
lock (syncObject)
{
if (IsStarted)
@@ -111,148 +111,156 @@ public void Start(int port)
throw e;
}
}
- }
+ }
///
/// Stop tcp server
///
public void Stop()
- {
+ {
lock (syncObject)
{
- tcpListener?.Stop();
- tcpListener = null;
+ try
+ {
+ connections?.ForEach(client => client.TcpClient?.Client?.Disconnect(false));
+ connections?.Clear();
+ }
+ catch { }
- connections?.ForEach(client => client.TcpClient?.Client?.Disconnect(false));
- connections?.Clear();
+ try
+ {
+ tcpListener?.Stop();
+ tcpListener = null;
+ }
+ catch { }
}
- }
-
- public virtual void Dispose()
- {
- Stop();
- }
-
- protected IClient GetClient(TcpClient tcpClient)
- {
- lock(syncObject)
- {
- return connections.First(connection => connection.TcpClient == tcpClient);
- }
- }
-
- protected void WriteToAllClients(byte[] buffer, int offset, int count)
- {
- Parallel.ForEach(connections, connection =>
- {
- connection.Write(buffer, offset, count);
- });
- }
- #endregion
-
- #region Protected Methods
- protected virtual void OnDataReceived(IClient client, int receivedSize) { }
- protected virtual void OnClientConnected(IClient client) { }
- protected virtual void OnClientDisconnected(IClient client) { }
- #endregion
-
- #region Private Methods
- private void AcceptTcpClientCallback(IAsyncResult ar)
- {
- if(ar.AsyncState is TcpListener tcpListener)
- {
- TcpClient tcpClient = tcpListener.EndAcceptTcpClient(ar);
- if(tcpClient != null) // new client connected
- {
- Connection connection = new Connection(this, tcpClient);
- lock(syncObject)
- {
- connections.Add(connection);
- }
-
- try
- {
- connection.BeginRead(
- new Connection.DataReceivedCallback(DataReceivedCallback),
- new Connection.DisconnectedCallback(DisconnectedCallback));
- OnClientConnected(connection);
+ }
+
+ public virtual void Dispose()
+ {
+ Stop();
+ }
+
+ protected IClient GetClient(TcpClient tcpClient)
+ {
+ lock (syncObject)
+ {
+ return connections.First(connection => connection.TcpClient == tcpClient);
+ }
+ }
+
+ protected void WriteToAllClients(byte[] buffer, int offset, int count)
+ {
+ Parallel.ForEach(connections, connection =>
+ {
+ connection.Write(buffer, offset, count);
+ });
+ }
+ #endregion
+
+ #region Protected Methods
+ protected virtual void OnDataReceived(IClient client, int receivedSize) { }
+ protected virtual void OnClientConnected(IClient client) { }
+ protected virtual void OnClientDisconnected(IClient client) { }
+ #endregion
+
+ #region Private Methods
+ private void AcceptTcpClientCallback(IAsyncResult ar)
+ {
+ if (ar.AsyncState is TcpListener tcpListener)
+ {
+ TcpClient tcpClient = tcpListener.EndAcceptTcpClient(ar);
+ if (tcpClient != null) // new client connected
+ {
+ Connection connection = new Connection(this, tcpClient);
+ lock (syncObject)
+ {
+ connections.Add(connection);
+ }
+
+ try
+ {
+ connection.BeginRead(
+ new Connection.DataReceivedCallback(DataReceivedCallback),
+ new Connection.DisconnectedCallback(DisconnectedCallback));
+ OnClientConnected(connection);
ClientConnected?.Invoke(this, new ClientConnectedEventArgs(connection));
- }
- catch
- {
- if (tcpClient.Connected)
- {
- tcpClient.Close();
- }
-
- lock (syncObject)
- {
- connections.Remove(connection);
- }
- }
-
- tcpListener.BeginAcceptTcpClient(new AsyncCallback(AcceptTcpClientCallback), this.tcpListener);
- }
- }
- }
-
- private void DisconnectedCallback(Connection connection)
- {
- lock (syncObject)
- {
- if (connections.Contains(connection))
- {
- connections.Remove(connection);
- }
- }
- OnClientDisconnected(connection);
+ }
+ catch
+ {
+ if (tcpClient.Connected)
+ {
+ tcpClient.Close();
+ }
+
+ lock (syncObject)
+ {
+ connections.Remove(connection);
+ }
+ }
+
+ tcpListener.BeginAcceptTcpClient(new AsyncCallback(AcceptTcpClientCallback), this.tcpListener);
+ }
+ }
+ }
+
+ private void DisconnectedCallback(Connection connection)
+ {
+ lock (syncObject)
+ {
+ if (connections.Contains(connection))
+ {
+ connections.Remove(connection);
+ }
+ }
+ OnClientDisconnected(connection);
ClientDisconnected?.Invoke(this, new ClientDisconnectedEventArgs(connection));
-
- }
- private void DataReceivedCallback(Connection connection, int receivedSize)
- {
+ }
+
+ private void DataReceivedCallback(Connection connection, int receivedSize)
+ {
TotalReceivedBytes += receivedSize;
- OnDataReceived(connection, receivedSize);
- }
- #endregion
-
- protected class Connection : IClient
- {
- #region Properties
- public TcpClient TcpClient { get; private set; }
- public IPEndPoint IPEndPoint { get => TcpClient?.Client?.RemoteEndPoint as IPEndPoint; }
-
- public int BytesToRead { get => _ringBuffer.Count; }
- public long DropBytes { get; private set; } = 0;
+ OnDataReceived(connection, receivedSize);
+ }
+ #endregion
+
+ protected class Connection : IClient
+ {
+ #region Properties
+ public TcpClient TcpClient { get; private set; }
+ public IPEndPoint IPEndPoint { get => TcpClient?.Client?.RemoteEndPoint as IPEndPoint; }
+
+ public int BytesToRead { get => _ringBuffer.Count; }
+ public long DropBytes { get; private set; } = 0;
public long SendedBytes { get; private set; } = 0;
public long ReceivedBytes { get; private set; } = 0;
- #endregion
+ #endregion
- public delegate void DataReceivedCallback(Connection connection, int receivedSize);
- public delegate void DisconnectedCallback(Connection connection);
+ public delegate void DataReceivedCallback(Connection connection, int receivedSize);
+ public delegate void DisconnectedCallback(Connection connection);
- #region Private Members
- private object syncObject = new object();
- private byte[] _buffer;
- private RingBuffer _ringBuffer;
- private DataReceivedCallback _dataReceived;
- private DisconnectedCallback _disconnected;
+ #region Private Members
+ private object syncObject = new object();
+ private byte[] _buffer;
+ private RingBuffer _ringBuffer;
+ private DataReceivedCallback _dataReceived;
+ private DisconnectedCallback _disconnected;
private BaseTcpServer _baseTcpServer;
- #endregion
+ #endregion
- public Connection(BaseTcpServer baseTcpServer, TcpClient tcpClient)
- {
- TcpClient = tcpClient;
- _buffer = new byte[tcpClient.ReceiveBufferSize];
- _ringBuffer = new RingBuffer(tcpClient.ReceiveBufferSize);
+ public Connection(BaseTcpServer baseTcpServer, TcpClient tcpClient)
+ {
+ TcpClient = tcpClient;
+ _buffer = new byte[tcpClient.ReceiveBufferSize];
+ _ringBuffer = new RingBuffer(tcpClient.ReceiveBufferSize);
_baseTcpServer = baseTcpServer;
- }
+ }
- public void BeginRead(DataReceivedCallback dataReceivedCallback, DisconnectedCallback disconnectedCallback)
- {
- _dataReceived = dataReceivedCallback;
- _disconnected = disconnectedCallback;
+ public void BeginRead(DataReceivedCallback dataReceivedCallback, DisconnectedCallback disconnectedCallback)
+ {
+ _dataReceived = dataReceivedCallback;
+ _disconnected = disconnectedCallback;
try
{
TcpClient?.GetStream()?.BeginRead(_buffer, 0, _buffer.Length, new AsyncCallback(ReadCallback), this);
@@ -261,54 +269,54 @@ public void BeginRead(DataReceivedCallback dataReceivedCallback, DisconnectedCal
{
_disconnected?.Invoke(this);
}
- }
-
- private void ReadCallback(IAsyncResult ar)
- {
- if (ar.AsyncState is Connection connection)
- {
- int readSize;
- try
- {
- readSize = connection.TcpClient.GetStream()?.EndRead(ar) ?? 0;
- }
- catch { readSize = 0; }
-
- if (readSize == 0) // client disconnected when readSize is zero
- {
- _disconnected?.Invoke(this);
- }
- else
- {
- int writeBytes = _ringBuffer.Write(_buffer, 0, readSize);
- if(writeBytes < readSize)
- {
- DropBytes += (readSize - writeBytes);
- }
+ }
+
+ private void ReadCallback(IAsyncResult ar)
+ {
+ if (ar.AsyncState is Connection connection)
+ {
+ int readSize;
+ try
+ {
+ readSize = connection.TcpClient.GetStream()?.EndRead(ar) ?? 0;
+ }
+ catch { readSize = 0; }
+
+ if (readSize == 0) // client disconnected when readSize is zero
+ {
+ _disconnected?.Invoke(this);
+ }
+ else
+ {
+ int writeBytes = _ringBuffer.Write(_buffer, 0, readSize);
+ if (writeBytes < readSize)
+ {
+ DropBytes += (readSize - writeBytes);
+ }
ReceivedBytes += readSize;
- _dataReceived?.Invoke(this, readSize);
- BeginRead(_dataReceived, _disconnected);
- }
- }
- }
-
- public int Read(byte[] buffer, int offset, int count)
- {
- return _ringBuffer.Read(buffer, offset, count);
- }
-
- public byte[] ReadExisting()
- {
+ _dataReceived?.Invoke(this, readSize);
+ BeginRead(_dataReceived, _disconnected);
+ }
+ }
+ }
+
+ public int Read(byte[] buffer, int offset, int count)
+ {
+ return _ringBuffer.Read(buffer, offset, count);
+ }
+
+ public byte[] ReadExisting()
+ {
return _ringBuffer.ReadExisting();
- }
+ }
- public int ReadByte()
- {
- return _ringBuffer.ReadByte();
- }
+ public int ReadByte()
+ {
+ return _ringBuffer.ReadByte();
+ }
- public void Write(byte[] buffer, int offset, int count)
- {
+ public void Write(byte[] buffer, int offset, int count)
+ {
try
{
lock (syncObject)
@@ -327,12 +335,12 @@ public void Write(byte[] buffer, int offset, int count)
{
_disconnected?.Invoke(this);
}
- }
-
- public override string ToString()
- {
- return IPEndPoint?.ToString();
- }
- }
- }
+ }
+
+ public override string ToString()
+ {
+ return IPEndPoint?.ToString();
+ }
+ }
+ }
}
diff --git a/SimpleTcp/SimpleTcp.csproj b/SimpleTcp/SimpleTcp.csproj
index 610ab08..3f76e5a 100644
--- a/SimpleTcp/SimpleTcp.csproj
+++ b/SimpleTcp/SimpleTcp.csproj
@@ -9,9 +9,9 @@
https://github.com/akon47/SimpleTcp
SimpleTcp Tcp Client Server Socket
Write a class summary, fixed some bug
- 1.0.3.0
- 1.0.3.0
- 1.0.3
+ 1.0.4.0
+ 1.0.4.0
+ 1.0.4
logo.png
Kim Hwan