Giter Site home page Giter Site logo

jchristn / supersimpletcp Goto Github PK

View Code? Open in Web Editor NEW
413.0 12.0 91.0 430 KB

Simple wrapper for TCP client and server in C# with SSL support

License: MIT License

C# 99.77% Batchfile 0.23%
tcp rpc messaging client server ssl tcp-client tcp-server simpletcp ssl-support

supersimpletcp's Introduction

supersimpletcp

SuperSimpleTcp

Simple wrapper for TCP client and server in C# with SSL support

NuGet Version NuGet

SuperSimpleTcp provides simple methods for creating your own TCP-based sockets application, enabling easy integration of connection management, sending, and receiving data.

I would highly encourage you to fully understand what message framing is and why it's important before using this library: https://blog.stephencleary.com/2009/04/message-framing.html

New in v3.0.x

  • Breaking change, allocation-free receive (thank you @joreg)
  • Configurable sync vs async for firing DataReceived events (thank you @TheNybbler)
  • More configurability around certificate validation checks (thank you @ATS-CE)
  • Better catch client timeouts during TLS establishment (thank you @ATS-CE)
  • Add NoDelay to settings (thank you @huangjia2107)
  • Fix for PollSocket method, thank you @zllvm @Energiz0r @Espen-Kalhagen-Element-Logic
  • Added server-side NoDelay property in settings, thank you @QTPah

Special Thanks

A special thanks to the community of people that have contributed to or otherwise improved this project!

@tinohager @u1035 @cmeeren @pha3z @opnop @kopkarmecoindo @simonhaines @matt1tk @lukeacat @exergist @maynardsi @sector13371 @loganwoodxyz @jwfxpr @IanPNewson @EGirardi @redrabbit007 @eatyouroats @joreg @CetinOzdil @tautvilis @ATS-CE @TheNybbler @huangjia2107 @zllvm @Energiz0r @Espen-Kalhagen-Element-Logic @MarkBreedveld @QTPah @olifer @KimEoJin @BrandenEK @Somfic

Help or Feedback

Need help or have feedback? Please file an issue here!

Simple Examples

Server Example

using SuperSimpleTcp;

void Main(string[] args)
{
  // instantiate
  SimpleTcpServer server = new SimpleTcpServer("127.0.0.1:9000");

  // set events
  server.Events.ClientConnected += ClientConnected;
  server.Events.ClientDisconnected += ClientDisconnected;
  server.Events.DataReceived += DataReceived;

  // let's go!
  server.Start();

  // once a client has connected...
  server.Send("[ClientIp:Port]", "Hello, world!");
  Console.ReadKey();
}

static void ClientConnected(object sender, ConnectionEventArgs e)
{
  Console.WriteLine($"[{e.IpPort}] client connected");
}

static void ClientDisconnected(object sender, ConnectionEventArgs e)
{
  Console.WriteLine($"[{e.IpPort}] client disconnected: {e.Reason}");
}

static void DataReceived(object sender, DataReceivedEventArgs e)
{
  Console.WriteLine($"[{e.IpPort}]: {Encoding.UTF8.GetString(e.Data.Array, 0, e.Data.Count)}");
}

Client Example

using SuperSimpleTcp;

void Main(string[] args)
{
  // instantiate
  SimpleTcpClient client = new SimpleTcpClient("127.0.0.1:9000");

  // set events
  client.Events.Connected += Connected;
  client.Events.Disconnected += Disconnected;
  client.Events.DataReceived += DataReceived;

  // let's go!
  client.Connect();

  // once connected to the server...
  client.Send("Hello, world!");
  Console.ReadKey();
}

static void Connected(object sender, ConnectionEventArgs e)
{
  Console.WriteLine($"*** Server {e.IpPort} connected");
}

static void Disconnected(object sender, ConnectionEventArgs e)
{
  Console.WriteLine($"*** Server {e.IpPort} disconnected"); 
}

static void DataReceived(object sender, DataReceivedEventArgs e)
{
  Console.WriteLine($"[{e.IpPort}] {Encoding.UTF8.GetString(e.Data.Array, 0, e.Data.Count)}");
}

Connect With Retries

The ConnectWithRetries method on SimpleTcpClient can be used instead of Connect to continually attempt to establish connections with the server for a given period of time. Like Connect, ConnectWithRetries will throw a TimeoutException if it is unable to successfully establish a connection.

client.ConnectWithRetries(10000); // try for up to 10000 milliseconds

Additional Configuration Options

Both SimpleTcpClient and SimpleTcpServer have settable values for:

  • Logger - method to invoke to send log messages from either SimpleTcpClient or SimpleTcpServer
  • Settings.MutuallyAuthenticate - only used if SSL is enabled, demands that both client and server mutually authenticate
  • Settings.AcceptInvalidCertificates - accept and allow certificates that are invalid or cannot be validated
  • Keepalive - to enable/disable keepalives and set specific parameters (disabled by default)

SimpleTcpServer also has:

  • Settings.IdleClientTimeoutSeconds - automatically disconnect a client if data is not received within the specified number of seconds

Additionally, both SimpleTcpClient and SimpleTcpServer offer a statistics object under SimpleTcpClient.Statistics and SimpleTcpServer.Statistics. These values (other than start time and uptime) can be reset using the Statistics.Reset() API.

Local vs External Connections

IMPORTANT

  • If you specify 127.0.0.1 as the listener IP address, it will only be able to accept connections from within the local host.
  • To accept connections from other machines:
    • Use a specific interface IP address, or
    • Use null, *, +, or 0.0.0.0 for the listener IP address (requires admin privileges to listen on any IP address)
  • Make sure you create a permit rule on your firewall to allow inbound connections on that port
  • If you use a port number under 1024, admin privileges will be required

Testing with SSL

A certificate named simpletcp.pfx is provided for simple testing. It should not expire for a really long time. It's a self-signed certificate and you should NOT use it in production. Its export password is simpletcp.

Disconnection Handling

The project TcpTest (https://github.com/jchristn/TcpTest) was built specifically to provide a reference for SuperSimpleTcp to handle a variety of disconnection scenarios. The disconnection tests for which SimpleTcp is evaluated include:

Test case Description Pass/Fail
Server-side dispose Graceful termination of all client connections PASS
Server-side client removal Graceful termination of a single client PASS
Server-side termination Abrupt termination due to process abort or CTRL-C PASS
Client-side dispose Graceful termination of a client connection PASS
Client-side termination Abrupt termination due to a process abort or CTRL-C PASS
Network interface down Network interface disabled or cable removed Partial (see below)

Additionally, as of v2.1.0, support for TCP keepalives has been added to SimpleTcp, primarily to address the issue of a network interface being shut down, the cable unplugged, or the media otherwise becoming unavailable. It is important to note that keepalives are supported in .NET Core and .NET Framework, but NOT .NET Standard. As of this release, .NET Standard provides no facilities for TCP keepalives.

TCP keepalives are disabled by default. To enable them:

server.Keepalive.EnableTcpKeepAlives = true;
server.Keepalive.TcpKeepAliveInterval = 5;      // seconds to wait before sending subsequent keepalive
server.Keepalive.TcpKeepAliveTime = 5;          // seconds to wait before sending a keepalive
server.Keepalive.TcpKeepAliveRetryCount = 5;    // number of failed keepalive probes before terminating connection

Some important notes about TCP keepalives:

  • Keepalives only work in .NET Core and .NET Framework
  • Keepalives can be enabled on either client or server, but are implemented and enforced in the underlying operating system, and may not work as expected
  • Keepalive.TcpKeepAliveRetryCount is only applicable to .NET Core; for .NET Framework, this value is forced to 10
  • Your mileage may vary; please remember that these are managed by the underlying operating system and not by this library

Running under Mono

.NET Core is the preferred environment for cross-platform deployment on Windows, Linux, and Mac. For those that use Mono, SimpleTcp should work well in Mono environments. It is recommended that you execute the containing EXE using --server and after using the Mono Ahead-of-Time Compiler (AOT).

mono --aot=nrgctx-trampolines=8096,nimt-trampolines=8096,ntrampolines=4048 --server myapp.exe
mono --server myapp.exe

Version History

Please refer to CHANGELOG.md.

supersimpletcp's People

Contributors

ats-ce avatar brandenek avatar cmeeren avatar djtrumpdaddy avatar jchristn avatar joreg avatar jwfxpr avatar markbreedveld avatar microm8 avatar mvelayati avatar redrabbit007 avatar sector13371 avatar somfic avatar tautvilis avatar tinohager avatar u1035 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

supersimpletcp's Issues

TcpClient.Connect throws NullReferenceException if called again after timeout

I need to try to connect repeatedly until successful. I instantiate TcpClient, set Connected, Disconnected, and DataReceived, and then call client.Connect(). If an exception is raised while connecting, I try again. However, if the first Connect call throws TimeoutException, the next calls to Connect will throw NullReferenceException.

I assume the reason is that SimpleTcp disposes the client after timeout:

https://github.com/jchristn/SimpleTcp/blob/db6ef1f8f6dea17c911a4777685f1b31acce4ccc/SimpleTcp/TcpClient.cs#L202

[Question] Handle reconnect

Hello again. What is the proper way to do a reconnect with your library? I currently have the following

private void ServerDisconnected(object sender, EventArgs e)
{
    WriteToChat("Server disconnected, Retrying in 5 seconds");
    new Thread(TryReconnect).Start();
}

private void TryReconnect()
{
    Thread.Sleep(5000);
    while (!client.IsConnected)
    {
        client.Connect();
        Thread.Sleep(5000);
    }
}

But I'm getting the error
System.Net.Sockets.SocketException: 'A connect request was made on an already connected socket'
This topic HERE talks about setting the socket as reusable and disconnecting the socket on the client side, but I don't see a disconnect option in the TcpClient or options to set it as reusable

Thanks again

.net Core 5 support

Hi,
I was just wandering if there is any plans to support .net core version 5 ?
Thanks in advance!

Support for domains

I think a good addition to this would be to add support for domains.

I'm currently dong

if (!IPAddress.TryParse(serverAddr, out IPAddress ipAddress))
{
    ipAddress = Dns.GetHostEntry(serverAddr).AddressList[0];
}
client = new TcpClient(ipAddress.ToString(), serverPort, false, null, null)

but might make sense to move that logic into the library maybe?

Thanks

IsConnected variable not changed

Hello!
I'm trying to use this library as client, and have a small issue.

I'm connecting to server with code like this:

_client = new SimpleTcpClient(host, port);
_client.Logger = Logger;
_client.Events.DataReceived += Events_MessageReceived;
_client.Events.Connected += Events_ServerConnected;
_client.Events.Disconnected += Events_ServerDisconnected;
_client.Connect();

And first thing I need to do - is send "handshake" to server (server is not mine).
I do it in Events_ServerConnected() callback, but _client.Send() fails with exception "Not connected to the server; use Connect() first.".

I debugged inside SimpleTcp code, and found that it checks _IsConnected variable, and throws exception when it's false.
But seems that nobody sets _IsConnected to true...
I tried to add _IsConnected = true; to end of both Connect() and ConnectWithRetries() before event calling,
and it started working.

Use events instead of callbacks

Is there any reason why this library is using Func callbacks instead of events? Events would be the idiomatic .NET tool for this job, and give a more pleasant dev experience.

Is it perhaps related to the callbacks returning Task, and that SimpleTcp must for some reason await callback completion? If so, why?

Always times out

Hey itยดs me again,

Now im having the issue that when i try to connect to the TCP server i just time out:

System.TimeoutException
  HResult=0x80131505
  Nachricht = Timeout connecting to (IP Adress)
  Quelle = SimpleTcp
  Stapelรผberwachung:
   at SimpleTcp.SimpleTcpClient.Connect()

The server is running with Mono on a RPI Zero W
Please help me!

Greetings,
Fischchen

Client disconnects after some time if he is not in the same network

If I use my program in a local network (same PC or PCs in the same network) it works without any problems.
But when I connect from a PC in another network the PC/Client disconnects after some time (sometimes after a few second and sometimes after 1-2 minutes). The program runs (correctly) into the disconnected event handler and if I debug the sender object (the SimpleTcpClient object) the received and sent bytes are always about 50-60 bytes.

Code to start the server:

_server = new SimpleTcpServer("0.0.0.0", Convert.ToInt32(tb_Port.Text));

_server.Keepalive.EnableTcpKeepAlives = true;
_server.Keepalive.TcpKeepAliveInterval = 10;
_server.Keepalive.TcpKeepAliveTime = 10;
_server.Keepalive.TcpKeepAliveRetryCount = 10;

_server.Events.ClientConnected += Events_ClientConnected;
_server.Events.ClientDisconnected += Events_ClientDisconnected;
_server.Events.DataReceived += Events_DataReceived;

_server.Start();

Code to connect the client:

_client = new SimpleTcpClient(tb_serverIP.Text, Convert.ToInt32(tb_port.Text));

_client.Keepalive.EnableTcpKeepAlives = true;
_client.Keepalive.TcpKeepAliveInterval = 10;
_client.Keepalive.TcpKeepAliveTime = 10;
_client.Keepalive.TcpKeepAliveRetryCount = 10;

_client.Events.Connected += Events_Connected;
_client.Events.Disconnected += Events_Disconnected;
_client.Events.DataReceived += Events_DataReceived;

_client.Connect();

What can I try to fix this issue?

IdleClientDisconnect appears to be broken

I haven't had a chance to create a minimum test scenario. I apologize, I've been swamped. But I Imagine this will be pretty easy to track down.

I set the IdleClientTimeoutSeconds property when I create a TcpServer instance and get the following result:
A client connects.
The TimeoutSeconds time passes.
The server reports that the client disconnected... Reason: Timeout.

It behaves as if data received from the client is not resetting the timeout timer (which is probably exactly what the bug is).

  • James

Stop listening?

Hello! How can I make the server stop listening for X amount of seconds or permanently without a .dispose();?
Thanks in advance!
EDIT: Server MUST not be disposed at any point in the code.

demo error

when i copy the demo in readme.md to run, here occur err:
// once a client has connected...
server.Send("[ClientIp:Port]", Encoding.UTF8.GetString("Hello, world!")); //cannot convert from 'string' to 'byte[]'

this state should be:
server.Send("[ClientIp:Port]", "Hello, world!");

Feature Request - IdleClientTimeoutSeconds

Would like to see IdleClientTimeoutSeconds added to Simple TcpServer.

I'd mark this as an enhancement, but I don't know how to add labels or that kind of thing on Github. I googled for it briefly but couldn't find a straight forward explanation.

Compatible python package

Is there any compatible python package or is there any encryption I have to think of when using the build in python package to communicate with this?

[Question] How to keep the connection for a client forever?

Hello,

I'm using the client example, but as soon as the server sends a message to the client, I get an exception.
I commented out the code in while (_RunForever) and replace Console. with Debug. because this is a winform application.
Everytime my Server send a message it throws the exception.

image

I'm new to c# and network programming, so ty for any help.

IsConnected doesn't seem to be updating on disconnect

I might be doing something wrong, or there is a race condition going on but I have a check right before I send a packet to client.IsConnected but when the server disconnects it still shows IsConnected as true and the packet fails because its been disconnected

IsConnected

Thanks

Delimiter?

Hello again! I'm sending multiple strings from my client to my server with different methods(programmatical term)
How can I set the server to recognize where each string message ends? eg: Environment.Newline(); at the end of each string means that there is no string within that request.
Here's my problem visually to make it more clear:
DoLogin(CurrentUser);
RequestUsersList(CurrentUser);
RequestStatus(CurrentUser);
all 3 methods have a Server.Send(string); function in them. If they get called at the aforementioned row what happens is one "big"
Server.Send(DoLogin.string + RequestUsersList.string + RequestStatus.string) command. Essentially all the strings get sent at once.
I tried Thread.Sleep(i); And it doesn't really change anything. I haven't tried asigning the tasks to different threads yet if that's a solution. Thanks in advance and I hope my issue was clear enough! ๐Ÿ‘ You guys rock

EDIT: I restructured my client and made it work. However this would still be a nice addition to have!

Cancellationtoken info

Not a bug but I think more info is needed in the docs on what the cancellationtoken actually is. It's not used by the examples so I'm not even sure what it's purpose is. Is the entire send buffer cleared when this special "cancellation token" is added to the buffer?

Error : System.Net.Sockets.SocketOptionName 0x3 is not supported at TCP level on RPI zero W

Hey, everybody
so i currently installed Mono on a Raspberry pi zero and tryed to use Tge SimpleTCP libary, but i get this error:

System.Net.Sockets.SocketOptionName 0x3 is not supported at TCP level

Unhandled Exception:
System.Net.Sockets.SocketException (0x80004005): Protocol option not supported
  at System.Net.Sockets.Socket.SetSocketOption (System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, System.Int32 optionValue) [0x0002f] in <3d97dda773a54430b892e1d794e5d921>:0
  at SimpleTcp.SimpleTcpClient.EnableKeepalives () [0x0002f] in <54f7a22dc9584671b228d6e0bd950d09>:0
  at SimpleTcp.SimpleTcpClient.InitializeClient (System.Boolean ssl, System.String pfxCertFilename, System.String pfxPassword) [0x00042] in <54f7a22dc9584671b228d6e0bd950d09>:0
  at SimpleTcp.SimpleTcpClient..ctor (System.String serverIpOrHostname, System.Int32 port, System.Boolean ssl, System.String pfxCertFilename, System.String pfxPassword) [0x000b1] in <54f7a22dc9584671b228d6e0bd950d09>:0
  at Node_01.TCP_Client..ctor (System.String ip, System.Int32 port) [0x00006] in <d3afab1ed095498092cd3b3817de050c>:0
  at Node_01.Program.Main (System.String[] args) [0x00048] in <d3afab1ed095498092cd3b3817de050c>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.Net.Sockets.SocketException (0x80004005): Protocol option not supported
  at System.Net.Sockets.Socket.SetSocketOption (System.Net.Sockets.SocketOptionLevel optionLevel, System.Net.Sockets.SocketOptionName optionName, System.Int32 optionValue) [0x0002f] in <3d97dda773a54430b892e1d794e5d921>:0
  at SimpleTcp.SimpleTcpClient.EnableKeepalives () [0x0002f] in <54f7a22dc9584671b228d6e0bd950d09>:0
  at SimpleTcp.SimpleTcpClient.InitializeClient (System.Boolean ssl, System.String pfxCertFilename, System.String pfxPassword) [0x00042] in <54f7a22dc9584671b228d6e0bd950d09>:0
  at SimpleTcp.SimpleTcpClient..ctor (System.String serverIpOrHostname, System.Int32 port, System.Boolean ssl, System.String pfxCertFilename, System.String pfxPassword) [0x000b1] in <54f7a22dc9584671b228d6e0bd950d09>:0
  at Node_01.TCP_Client..ctor (System.String ip, System.Int32 port) [0x00006] in <d3afab1ed095498092cd3b3817de050c>:0
  at Node_01.Program.Main (System.String[] args) [0x00048] in <d3afab1ed095498092cd3b3817de050c>:0

Please help me!

Greetings,
Fischchen

Missing .pfx-file

I'm hoping to use this little library and cloned the repo and tried to build it. During build in VS 2016.1.2 I get an error about missing .pfx-file in both the TestNetFramework-projects.

I couldn't see anything in the Readme about this. Did you forget to commit the file (it's in the .gitignore-file), or is it intentional?

I guess I could create it again with the command in the certificate-instructions.txt file.

Server receiving data out of order

Hey Joel,

I have an external system that I have no control over sending data to my TCP Server. I had to build the Server to conform to the client system pattern.

The client is supposed to send what it calls "blocks" of data and a complete sequence of blocks forms a complete message. Each block is prefixed with 2 bytes that indicate the block length. Max block size is 65536. If a block prefix says the length will be 65536, then at least one more block will follow. When a prefix says block size is less than 65536, then its the last block. Putting all the blocks together in order establishes the entire message.

The problem I'm having is that parts of the blocks are not always triggering the DataReceived method in correct order. Sometimes I receive a piece of a block in the byte[] from DataReceived.
Then I receive start of the block when DataReceive triggers again.... and finally the end of the block. I have no way of knowing which order the blocks go in to properly assemble them.

I can't tell what's going on closer to the raw TCP stack, which is quite a problem. What I expected is that the existing client app would break a block into TCP packets to send them, and Simple TCP Server would put the packets together in the correct order (even if they were received out of order) so that I'm guaranteed to at least get packets (and thereby parts of blocks) in order.

Do you have any inkling what might be going wrong? Have I made incorrect assumptions about what Simple Server should do?

Data receiver terminated

I'm using version 2.2.1.1. When I test my code locally on my own pc, I have no issues at all. As soon as I run it on a server on the internet, there seem to be random disconnects and this turns up in the logs:

[SimpleTcp.Server] data receiver terminated for client xxx.xxx.xxx.xxx:yyyyy

(to be clear: this error doesn't appear locally)

Any advice?

[Question] Unnecessary loop at SimpleTcpClient

Hello, I am learning socket programming. I would like to ask why is there an infinite while (true) loop at line 577 of the SimpleTcpClient class after awaiting the read, writing into the MemoryStream, and converting to an array? Since the read array is returned immediately after the conversion, the loop would not iterate.

     private async Task<byte[]> DataReadAsync(CancellationToken token)
        {  
            byte[] buffer = new byte[_Settings.StreamBufferSize];
            int read = 0;

            if (!_Ssl)
            { 
                using (MemoryStream ms = new MemoryStream())
                {
                    while (true)
                    {
                        read = await _NetworkStream.ReadAsync(buffer, 0, buffer.Length, token).ConfigureAwait(false);

                        if (read > 0)
                        {
                            await ms.WriteAsync(buffer, 0, read, token).ConfigureAwait(false);
                            return ms.ToArray();
                        }
                        else
                        {
                            throw new SocketException();
                        }
                    }
                } 
            }

Create a Websockets Server?

Hey Joel, your vast experience and knowledge has been really helpful in the past so I'm asking about this rather than going down a rabbit hole of failed experiments first!

So far I have not been able to find a simple C# websocket Server library that is cross-platform, future-proof, and lightweight.

Lightweight websocket libs have historically depended on httpListener, but httpListener was deprecated. It looks like Microsoft has pretty much abandoned lightweight http support in favor of bigger full-framework solutions like Kestrel + ASP.

I found this:
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_server

It uses TcpListener and shows you how to receive a GET request and escalate to a websocket connection. I haven't tried it yet. I notice its extremely barebones and almost looks "too easy"?? It's clearly not going to have the bells and whistles of a full http listener, but I probably don't even need that.

The purpose of my investigation is to build a c# application that uses websockets for IPC connection to a webview frontend. I want to maintain UI state within the c# application and do very minimal lifting inside the webview. The webview would only have some javascript to establish a websocket connection to the c# application. The webview javascript would have some utility functions for DOM manipulation and event binding, but all of that would be driven from within the C# app where the state can be tracked.

I've seen some other developers looking for solutions like this, and many of them don't know where to look. There is so much over-engineered junk that depends on Asp.net, razor, blazor, electron, or other alphabet soup libraries.

The nice thing about the approach I want to build is that you could make it work within almost any framework. It could be used with Electron easily, but you could also use it with native webviews and windows. Ideally, it would be usable on Android and iOS which is one of the reasons I ended up looking at TcpListener and doing a low-level implementation of websockets that would work on both Mono and .NET Core 5 and be somewhat future proof.

What are your thoughts on this?
Does the Mozilla example doc I linked oversimplify the needs of a simple one-client/localhost-server scenario?
Is there a lightweight mono and .net core compatible websocket server lib somewhere that I just haven't come across yet?

If nothing exists, would it make sense to try to use SimpleTcp to be the foundation for a cross-plat websocket server?

Looking forward to your thoughts!!! Thanks for your time in advance!!

Always times out

My Client cant connect to my Server. The client is on another pc in the same wlan network. I added permit rules for the port 9000 for in and out on both pcs and checked if they allow tcp connections.
This is my code for the client:
Client.txt

This is my code of the server:
Server.txt

I started the server with the ip: 0.0.0.0 and the client with the ip copied from the ipconfig of the server. I deactivated my virusdetections and started the server with administrator privileges. The timeout is configured to be 60 seconds.
I always get the following error: "Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeit nicht richtig reagiert hat, oder die Verbindung fehlerhaft war, da der verbundene Host nicht reagiert hat. [ip-adress of server:9000].

If i connect with the client on the same pc it works completly fine.

How to properly close the client connection on the application exiting?

Given a client that is connected to the server like this:

var client = new SimpleTcpClient(ipAddress, port);
client.Connect();

I would like to close the tcp connection when the application is shutting down. Should I call both client.Disconnect() and client.Dispose() or just client.Disconnect() is enough?

MonitorForIdleClientsTask: System.NullReferenceException

Hi @jchristn, this turned up in my logs during testing of the 2.04 nuget package:

Jun 24 03:39:43: Exception in MonitorForIdleClientsTask: System.NullReferenceException: Object reference not set to an instance of an object.
Jun 24 03:39:43:    at SimpleTcp.ClientMetadata.Dispose()
Jun 24 03:39:43:    at SimpleTcp.TcpServer.DisconnectClient(String ipPort)
Jun 24 03:39:43:    at SimpleTcp.TcpServer.MonitorForIdleClients()
Jun 24 06:31:54: Exception in MonitorForIdleClientsTask: System.NullReferenceException: Object reference not set to an instance of an object.
Jun 24 06:31:54:    at SimpleTcp.ClientMetadata.Dispose()
Jun 24 06:31:54:    at SimpleTcp.TcpServer.DisconnectClient(String ipPort)
Jun 24 06:31:54:    at SimpleTcp.TcpServer.MonitorForIdleClients()

The code seems to be null-safe. The only thing I can think might cause this is concurrent access where one of the TokenSource/SslStream/NetworkStream/TcpClient is disposed and nulled from another thread. I'll try and produce some better instrumentation.

asynchronous get responses

This is some piece of code from https://github.com/Phyyl/ObooltNet/blob/master/Source/ObooltNet/NetConnection.cs
Is it possible to add SendAndWait function to SimpleTcp ?
SimpleTcp is more stable and powerful.

        private void CheckServerUsedAsClient()
        {
            if (listener != null)
            {
                throw new InvalidOperationException("Cannot use a server connection as a client");
            }
        }

        private void CallOnDataReceived(TcpClients connection, byte[] data)
        {
            if (OnDataReceived != null)
                OnDataReceived(this, connection, data);
        }

        private async Task<byte[]> ReceiveFromAsync( int timeout = 5000)
        {
            try
            {
                _Client.ReceiveTimeout = timeout;
                NetworkStream stream = _Client.GetStream();
                byte[] buffer = new byte[8193];
                MemoryStream ms = new MemoryStream();
                int bytesRead = 0;
                while (_Client.Connected)
                {
                    if (bytesRead > 0)
                    {
                        return buffer.Take(bytesRead).ToArray();
                    }
                    bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
                    ms.Write(buffer, 0, bytesRead);
                    if (!stream.DataAvailable)
                    {
                        CallOnDataReceived(_Client, ms.ToArray());
                        ms.Seek(0, SeekOrigin.Begin);
                        ms.SetLength(0);
                    }
                }
            }
            catch
            {

            }
            return null;
        }

        public async Task<byte[]> SendAndReceiveData(byte[] data, int timeout = 5000)
        {
            CheckServerUsedAsClient();
            _Client.GetStream().Write(data, 0, data.Length);
            var tskReceive = await ReceiveFromAsync( timeout);
            return tskReceive;
        }

        public byte[] SendAndWait(byte[] Data, int timeout = 5000)
        {
            Task<byte[]> testTask = SendAndReceiveData(Data, timeout);
            testTask.Wait();
            return testTask.Result;
        }

        //private async Task<bool> AwaitTimeoutTask(Task task, int timeout)
        //{
        //    return await Task.WhenAny(task, Task.Delay(timeout)) == task;
        //}

client.Connect () freezes the interface.

If a connection cannot be established to the ip address entered by the user, ethernet.Connect (); command freezes the interface for about 5 seconds.

Could the reason be that EthernetConnect runs on the same thread as the ui? How can I fix the problem.

DataReceived never goes off & more

I'm making a simple chatapp with TCP.

Connected was fired perfectly, and I could send my JSON.

I was finished with the backend, and I added some stuff to DataReceived, but it didn't fire even though I know I'm sending json.

Also, I sent a bunch of disconnects, then connnects. They after a second of doing this stacked up and became from {hello:info} to this {hello:info}{hello:info}{hello:info}

Thanks for maintaining!,
Luke.

Feature request: throttling mechanism?

Just thinking out loud here... I'm currently using your library to simulate a slow modem connection. I'm doing this by using a timer and sending out one character at a time, which makes the characters appear slowly on the other side. This, however, requires me to create my own in/out buffers inside my program, on top of those that exist in simpletcp.

I'm not sure if I'm the only one with this need but some kind of throttling mechanism that limits the speed of the data that is being transferred would be a cool addition to simpletcp (something like: "limit output to 100 bytes per second" or so...)

Version confusion

FYI, the name of this project matches exactly the WRONG Nuget package. So, I search that name and found the other one. Similar but not the same.

Fortunately, having installed SuperSimpleTcp instead, all appears to be working.

Server not starting.

Upon starting basic project I am unable to connect to the started server. (see code below) When scanning my open ports, it is not listed (see screenshot attached), although if I start a TcpListener as shown in the code (commented) it does. I also tested with your given examples to no avail.

` static void Main(string[] args) {
// TcpListener s = new TcpListener(63534);
// s.Start();
server = new SimpleTcpServer("127.0.0.1", 63534);

    server.Events.ClientConnected += Server_ClientConnected;
    server.Events.DataReceived += Server_DataRecieved;
    server.Events.ClientDisconnected += Server_ClientDisconnected;
    server.Logger += Logger;

    Start();
    Console.WriteLine(server.IsListening);
    Console.ReadLine();
}`

Screen Shot 2020-12-17 at 10 51 52 PM

What is the correct way to write in a non-blocking manner?

So I know you mentioned in a discussion about Watson that SendAsync() is important because if you write to the NetworkStream synchronously, you can have problems where NetworkCongestion or OS behavior (Or something??) can block further code execution until the NetworkStream is flushed.

Am I understanding correctly?

If yes, what is the correct way to use SimpleTCP if I anticipate potential issues with that?

On a personal project, I'm creating a game that will stream a lot of text data to many hundreds of connected users. Writes to multiple users will be extremely frequent -- possibly almost constant in some cases.

On a class that represents a user connection, I've created a byte[] buffer that I can write data to. And then I can call a custom Flush() method to write buffered data to the NetworkStream.

All of the main logic is built in a complete synchronous manner and writing to the byte[] buffer is part of that synchronous behavior. This is by design because its crucial that everything happen in a controlled order of events.

Since I've got the buffer, I can call Flush() and write to the NetworkStream in a non-synchronous fashion. But what I'm wondering is... what's the best way to go about doing that?

I could fire an individual Task to write to the NetworkStream and use a monitoring mechanism to track whether or not the task has completed. This would result in all connections getting individual Tasks fired every single time data needs to be flushed to their respective NetworkStreams. Is this the best way to do something like this?

Clearly, I can't just run a background worker to sequentially flush each user's buffer to stream, because then I'd be back to the same blocking issue. If a single stream blocked, it would need to finish before any other user streams could be written.

Or am I completely wrong about how this works? If at any time one NetworkStream blocks, does it mean the entire Network output is blocked, so all NetworkStreams are also going to be blocked?

Is there a book or some information somewhere to help explain the lower level details of this?

Server not disconnect the client after not send over IdleClientDisconnect

Hi,
I have created TCP server with rules that client must be send message periodically to indicate that client is connected to the server. and use parameter IdleClientDisconnect to disconnect the client if the client not send any data. but the server not disconnect the client after the client not send data.

is my understanding wrong about IdleClientDisconnect? please your advice

How to avoid graphics refresh in newly opened window?

Hello,

I have a graph with a home screen. I want to open this chart in new window. I can open the chart in a new window, but as data comes to the chart on the home page, the data in the window I just opened is refreshed.

If I don't click on the chart, the renewal doesn't occur. When I click on any point of the graph with the mouse, it prints the data on the main screen.

How can I prevent this? The code I use to open in a new window is as follows.

var AxisX_Copy = HpsvAxisX_Graphic.plt.Copy();
AxisX_Copy.Ticks(dateTimeX: true, dateTimeFormatStringX: ("HH.mm.ss"));
AxisX_New_Window = new WpfPlotViewer(AxisX_Copy);
AxisX_New_Window.Show();

Is it nearly impossible to write a Port Forwarder that works?

So I wrote a port forwarding application using Simple Tcp. I test it with a custom client connecting to the port forward app, which forwards packets to a custom server (also for testing). When the server receives a packet, it echos the data back to the port forward app which relays it back to the originating client app. This way I can verify that the data receives and comes back as the same data.

It works. But when I try to use this with real applications (such as Sql client to connect to a Sql Server), I get spotty results. It half-works but some applications throw errors about unexpected data/messages and other things like that.

Am I wrong in thinking that port forwarding is as simple as putting a middle-man application in between to 2 endpoints to marshal packets from A to B and from B to A? Is there something else necessary to make this work?

Combine both web socket server and client

Hello:
I have one special request, I need some help.
I need some kind of web socket relay program. I have one very fast web socket data source, the server is not in my control. But the external web socket server generates huge amount of text data, I can write one web socket client to receive the huge amount of data, but less than 10% of the data is needed. As the external web socket server generates too much data, my web socket client is always freeze, yet less than 10% of the data is useful.
I want to write a web socket relay program, which is one web socket client for the external web socket server, but at the same time, acts as one internal web socket server, send only those 10% useful data to another web socket client.
Another web socket client can process all the useful data. In this design, the web socket relay program will be busy to process all the web socket data, but another web socket client will not be freeze to process only 10% of total data received.
Let me know if my thinking is practical, if yes, can you provide some code example.
Thanks,

ConnectTimeoutSeconds not working as expected

If a client cannot connect to a server a SocketException (ConnectionRefused) is thrown within 2 seconds of initiating the connection process regardless of the ConnectTimeoutSeconds value.

public void TimedConnect()
{
	client.Settings.ConnectTimeoutSeconds = 60;
	try
	{
		client.Connect();
	}
	catch (Exception ex)
	{
                MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
	}
}

Basically client.Settings.ConnectTimeoutSeconds = 60; doesn't seem to be honored in the above example.

Please see relevant discussion for additional information.

Connecting to multiple servers from one computer

Hello, I will connect to multiple servers from one computer. I should save the data I received from these servers to the list after a mathematical process.

Is there any way to know the server with which ip address the data is coming from?

// In this way, I can find out which one is triggered, but properties such as ip address and port come as non-static properties.
private void EthernetDataReceived(object sender, DataReceivedFromServerEventArgs e) { SimpleTcpClient client = (SimpleTcpClient)sender; }

Also, is it right to use only one EthernetDataReceived for each server?

client.Events.DataReceived += EthernetDataReceived;

Is there an example of multi connection? If available, can you share?

Server receiving data out of order (DataReceived method triggers out of order)

Hey Joel,

I have an external system that I have no control over sending data to my TCP Server. I had to build the Server to conform to the client system pattern.

The client is supposed to send what it calls "blocks" of data and a complete sequence of blocks forms a complete message. Each block is prefixed with 2 bytes that indicate the block length. Max block size is 65536. If a block prefix says the length will be 65536, then at least one more block will follow. When a prefix says block size is less than 65536, then its the last block. Putting all the blocks together in order establishes the entire message.

The problem I'm having is that parts of the blocks are not always triggering the DataReceived method in correct order. Sometimes I receive a piece of a block in the byte[] from DataReceived.
Then I receive start of the block when DataReceive triggers again.... and finally the end of the block. I have no way of knowing which order the parts go in to properly assemble a complete block. (If the block parts happen to come in the right order, I have no trouble putting the blocks together to get the entire message.)

I can't tell what's going on closer to the raw TCP stack, which is quite a problem. What I expected is that the existing client app would break a block into TCP packets to send them, and Simple TCP Server would put the packets together in the correct order (even if they were received out of order) so that I'm guaranteed to at least get packets (and thereby parts of blocks) in order.

Do you have any inkling what might be going wrong? Have I made incorrect assumptions about what Simple Server should do?

ConnectWithRetries generates multiple connections from a single client instance

If I perform the following I get multiple client connections between one client instance and one server instance:

  1. Create client instance
  2. Initiate client connection (attempt) via ConnectWithRetries
  3. Wait a few seconds (something less than value given to ConnectWithRetries)
  4. Create server instance
  5. Initiate server listening via Start

Here are the results for my simple client-server example:
image
As you can see there are seemingly TWO client connections with the server, even though the intent was to have only ONE client connection. If I start the server prior to initiating a client connection via ConnectWithRetries, there is only ONE client connection made as expected.

For reference here is my code for initiating a client connection with the server:

private void btnConnect_Click(object sender, EventArgs e)
{
	try
	{
		client.ConnectWithRetries(10);
		btnConnect.Enabled = false;
	}
	catch(Exception ex)
	{
		MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
		btnConnect.Enabled = true;
	}
}

... and here is my code for updating the server UI after making a client connection:

private void Events_ClientConnected(object sender, ClientConnectedEventArgs e)
{
	this.Invoke((MethodInvoker)delegate
	{
		txtInfo.Text += $"{e.IpPort} connected.{Environment.NewLine}";
		lstClientIP.Items.Add(e.IpPort);
		btnSend.Enabled = true;
		btnDisconnect.Enabled = true;
	});
}

Is this behavior expected?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.