Code Monkey home page Code Monkey logo

watsontcp's Introduction

dotnet/dotnet - Home of the .NET VMR

This repository is a Virtual Monolithic Repository (VMR) which includes all the source code and infrastructure needed to build the .NET SDK.

What this means:

  • Monolithic - a join of multiple repositories that make up the whole product, such as dotnet/runtime or dotnet/sdk.
  • Virtual - a mirror (not replacement) of product repos where sources from those repositories are synchronized into.

In the VMR, you can find:

Just like the development repositories, the VMR will have a release branch for every feature band (e.g. release/8.0.1xx). Similarly, VMR's main branch will follow main branches of product repositories (see Synchronization Based on Declared Dependencies).

More in-depth documentation about the VMR can be found in VMR Design And Operation. See also dotnet/source-build for more information about our whole-product source-build.

Goals

  • The main purpose of the dotnet/dotnet repository is to have all source code necessary to build the .NET product available in one repository and identified by a single commit.
  • The VMR also aims to become the place from which we release and service future versions of .NET to reduce the complexity of the product construction process. This should allow our partners and and 3rd parties to easily build, test and modify .NET using their custom infrastructure as well as make the process available to the community.
  • Lastly, we hope to solve other problems that the current multi-repo setup brings:
    • Enable the standard down-/up-stream open-source model.
    • Fulfill requirements of .NET distro builders such as RedHat or Canonical to natively include .NET in their distribution repositories.
    • Simplify scenarios such as client-run testing of bug fixes and improvements. The build should work in an offline environment too for certain platforms.
    • Enable developers to make and test changes spanning multiple repositories.
    • More efficient pipeline for security fixes during the CVE pre-disclosure process.

We will achieve these goals while keeping active coding work in the separate repos where it happens today. For example: ASP.NET features will continue to be developed in dotnet/aspnetcore and CLR features will be continue to be developed in dotnet/runtime. Each of these repos have their own distinct communities and processes, and aggregating development into a true mono-repo would work against that. Hence, the "virtual" monolithic repo: the VMR gives us the simplicity of a mono-repo for building and servicing the product, while active development of components of that product stays in its various existing repos. The day to day experience for typical contributors will not change.

Limitations

This is a work-in-progress. There are considerable limitations to what is possible at the moment. For an extensive list of current limitations, please see Temporary Mechanics.
See the Unified Build roadmap for more details.

Supported platforms

  • 8.0
    • source-build configuration on Linux
  • 9.0+ (WIP)
    • source-build configuration on Linux
    • non-source-build configuration on Linux, Mac, and Windows

For the latest information about Source-Build support for new .NET versions, please check our GitHub Discussions page for announcements.

Code flow

For the time being, the source code only flows one way - from the development repos into the VMR. More details on this process:

We expect the code flow to start working both ways in the .NET 9 timeframe. See the Unified Build roadmap for more details.

Contribution

At this time, the VMR will not accept any changes and is a read-only mirror of the development repositories only. Please, make the changes in the respective development repositories (e.g., dotnet/runtime or dotnet/sdk) and they will get synchronized into the VMR automatically.

Dev instructions

Please note that this repository is a work-in-progress and there are some usability issues connected to this. These can be nuisances such as some checked-in files getting modified by the build itself and similar. For the latest information about Source-Build support, please watch for announcements posted on our GitHub Discussions page.

Prerequisites

The dependencies for building can be found here. In case you don't want to / cannot prepare your environment per the requirements, consider using Docker.

Building

  1. Clone the repository

    git clone https://github.com/dotnet/dotnet dotnet-dotnet
    cd dotnet-dotnet
  2. Build the .NET SDK

    Choose one of the following build modes:

    • Microsoft based build

      For Unix:

      ./build.sh --clean-while-building

      For Windows:

      .\build.cmd -cleanWhileBuilding
    • Building from source

      # Prep the source to build on your distro.
      # This downloads a .NET SDK and a number of .NET packages needed to build .NET from source.
      ./prep-source-build.sh
      
      # Build the .NET SDK
      ./build.sh -sb --clean-while-building

    The resulting SDK is placed at artifacts/assets/Release/dotnet-sdk-9.0.100-[your-RID].tar.gz (for Unix) or artifacts/assets/Release/dotnet-sdk-9.0.100-[your-RID].zip (for Windows).

  3. (Optional) Unpack and install the .NET SDK

    For Unix:

    mkdir -p $HOME/dotnet
    tar zxf artifacts/assets/Release/dotnet-sdk-9.0.100-[your-RID].tar.gz -C $HOME/dotnet
    ln -s $HOME/dotnet/dotnet /usr/bin/dotnet

    For Windows:

    mkdir %userprofile%\dotnet
    tar -xf artifacts/assets/Release/dotnet-sdk-9.0.100-[your RID].zip -C %userprofile%\dotnet
    set "PATH=%userprofile%\dotnet;%PATH%"

    To test your built SDK, run the following:

    dotnet --info

Note

Run ./build.sh --help (for Unix) or .\build.cmd -help (for Windows) to see more information about supported build options.

Building using Docker

You can also build the repository using a Docker image which has the required prerequisites inside. The example below creates a Docker volume named vmr and clones and builds the VMR there.

docker run --rm -it -v vmr:/vmr -w /vmr mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream9
git clone https://github.com/dotnet/dotnet .

# - Microsoft based build
./build.sh --clean-while-building

# - Building from source
./prep-source-build.sh && ./build.sh -sb --clean-while-building

mkdir -p $HOME/.dotnet
tar -zxf artifacts/assets/Release/dotnet-sdk-9.0.100-centos.9-x64.tar.gz -C $HOME/.dotnet
ln -s $HOME/.dotnet/dotnet /usr/bin/dotnet

Codespaces

You can also utilize GitHub Codespaces where you can find preset containers in this repository.

Building from released sources

You can also build from sources (and not from a context of a git repository), such as the ones you can acquire from a dotnet/dotnet release. In this case, you need to provide additional information which includes the original repository and commit hash the code was built from so that the SDK can provide a better debugging experience (think the Step into.. functionality). Usually, this means the dotnet/dotnet repository together with the commit the release tag is connected to.

In practice, this means that when calling the main build script, you need to provide additional arguments when building outside of a context of a git repository.
Alternatively, you can also provide a manifest file where this information can be read from. This file (release.json) can be found attached with the dotnet/dotnet release.

Synchronizing code into the VMR

Sometimes you want to make a change in a repository and test that change in the VMR. You could of course make the change in the VMR directly (locally, as the VMR is read-only for now) but in case it's already available in your repository, you can synchronize it into the VMR (again locally).

To do this, you can either start a dotnet/dotnet Codespace - you will see instructions right after it starts. Alternatively, you can clone the repository locally and use the vmr-sync.sh or vmr-sync.ps1 script to pull your changes in. Please refer to the documentation in the script for more details.

List of components

The full list of components synchronized into the VMR is here (Components.md).

The repository also contains a JSON manifest listing all components in a machine-readable format.

Filing Issues

This repo does not accept issues as of now. Please file issues to the appropriate development repos. For issues with the VMR itself, please use the source-build repository.

Useful Links

.NET Foundation

.NET Runtime is a .NET Foundation project.

License

.NET is licensed under the MIT license.

watsontcp's People

Contributors

bendablegears avatar brudo avatar cbarraco avatar cee-sharp avatar denisbalan avatar fisherman6v6 avatar jchristn avatar jeverz avatar jyck avatar karstennilsen avatar marek-petak avatar markashleybell avatar mikkleini avatar mrmikejj avatar ozrecsec avatar thechosensausage 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

watsontcp's Issues

Feature request - async-friendly send/flush and idle/poll operations

This is not a bug report, but a feature request. I may help implement it, on my own time, but no promises!

Currently, WatsonTcp and WatsonCluster perform nicely for the basic use case of a simple peer-to-peer cluster with limited messaging. However, internally, the library uses methods like Flush() that block the calling thread when sending messages, instead of non-blocking awaitable equivalents like FlushAsync(). (Although non-blocking code is already used to Connect and Receive messages.)

Likewise, when looping and polling, the present code uses blocking calls such as Thread.Sleep(ms) and Task.Delay(ms).Wait() instead of non-blocking variations based on await Task.Delay(ms) which would unschedule the present Task, and release the thread back to the thread pool to be reused.

Use of blocking code, even with short-interval delays and sending on a known-healthy connection, limits scalability and capacity to support concurrent operations in applications leveraging WatsonCluster for internal messaging. At least in theory, some calls to WatsonTcp will tie up threads from the thread pool even when WatsonTcp is idling or waiting for an IO operation to complete, whereas other async Tasks running on the thread pool could be making use of those threads.

So far it does not seem to be hitting any limits in my present use case, as I can mostly fire-and-forget messages to a partner instance using something like Task.Run(()=>cluster.IsHealthy() && cluster.Send(...)), but the library would be more versatile if this were implemented. Nothing preventing you from continuing to provide the current blocking Send() as well as a non-blocking async Task<bool> SendAsync(...[, cancelToken]).

Integer must be between....

Greetings again,
After re-writing my methods due to the breaking changes of V3.0 , i encountered an issue (That may be already been before an issue , just without this message)

-Integer must be between 0 and 9999.- at WatsonTcp.Message.WatsonMessage.IntegerToBytes(Int32 i)

I dug around a bit , and think its related to the site of the data i want to send?
Is the Metadata limited in some way , eather in size or format ?

The situation:
When my clients connecting to the server, the server is sending a dictionary with
FileLocations as Keys ( string ) and FileHashes ad Values (string) ( String KeyValuePairs casted to object for sending ofc) .

I thought it would make more sense to send them via the metadata as it already defines a dictionary. / Before the breaking changes i did send all that info as normal message as 1 big string and used JsonDeserialize at the endpoint myself . Worked all fine.

Some help here would be nice :p Thanks

Busy wait loop uses excessive CPU when sending / receiving bytes.

I tried to implement WatsonCluster in one of our applications. It worked fine to detect whether the cluster was healthy or not, indicating the firewall is configured properly. However, a message sent from one instance did not arrive on the partner instance, and I noticed the CPU got pegged at 100% on the partner machine. I believe this may be due to a busy wait loop using Sleep() in WatsonTcp, in DataReceiver / MessageRead, which may be causing threads to block and eventually exhausting the thread pool.

Can this be changed to use Task.Delay rather than Thread.Sleep to prevent blocking threads, or better yet read the message and/or wait for data availability asynchronously?

New feature: implement SendRequest

hi jchristin,
I'm new to github, I've found your library very useful for my next project.
It's very easy to use and works very good.
I would like see in your WatsonTcpClient class an implementation of a method like this

byte[] SendRequest(Dictionary<object,object>, string data)

When the client sends this message it will wait for the response and then provide the response as return value.

When the server receives the Request it fires an event and after event management sends the response to the client.

Who manages the server event must set the response in a property of eventargs. Also the server have to respond very quickly :-)

I think that in this case the communication between the client and the server will be synchronous, i cannot send to server other requests until the current has no response.

I don't know if this is a good idea but this implementation makes the TCP calls more similar to method calls.

let me know what do you think about

Thanks

Ozrecsec

Handlebars Request: Remove "ReadDataStream"

It would be very nice to remove ReadDataStream as public property.
Let the consumer just set StreamReceived or MessageReceived events.

In the setter for the events, you can change whatever field is represented by ReadDataStream so the internal operation remains the same.

Also, if you want to only allow StreamReceived and MessageReceived events to be used mutually exclusively, you can handle that in the setter as well.
Have a flag indicating whether either one of the setters has been called.
When a setter gets called, if the flag already says one setter was called, throw an WatsonConfigurationException (Or whatever exception name you're using for watson exceptions) with a message explaining that only one of the events can be set.

Simplifies configuration. Would have saved me 10 minutes of troubleshooting. It's a footgun.

how to set TcpNoDelay true?

Hi.
finally i can use your library in vb.net.
i used it for my game server.and i need to set TcpNoDelay to true .
how can i do that?
thanks

SyncResponse data always null?

Greetings!
The new Syncresponse seems pretty usefull to me,
to send message only data as supposed to bigger file transfer over streams.
So i can split them , and not use only the one method for everything.
But i encounter now one problem.
Any Syncresponse.Data is null for me, client + serverside.
Am i doing something wrong?

try
            {
                SyncResponse resp;

                resp = client.SendAndWait(5000, "StringToSend");
                var data = resp.Data;
                if (data != null)
                {
                    var answer = Encoding.UTF8.GetString(resp.Data);

                    .......
                }
                else
                {
                    .......
                }
            }
            catch
            {
              .......
            }

Bit unclear how to connect from another PC

Hi @jchristn . I have one documentation suggestion. It's not very clear how to setup WatsonTcpServer so it can be connected by external clients (not just localhost clients). For that a null or string.Empty has to be used as listenerIp argument in constructor.
But maybe write it in the examples and add it to the constructor comment?

At least on Linux (RPi) if i use "127.0.0.1" then i can't connect from Windows client.

Client detects disconnection, but server doesn't

My WatsonTcp client randomly detects a disconnection, but my WatsonTcp server doesn't say it has been disconnected until I close the application.

I'm sending a lot of information back and forth non-stop (5Kbps+), could this be a possibility?

Start() is fire and forget?

client.Start() is void Fire-and-Forget synchronous style.

What happens if the client throws an exception? It looks like the exception will not reach the main execution thread.

Can you add StartAsync() method

Hello Joel!

Can you add StartAsync() method as I would like to use watson from an async environment.
Nowadays, I need to use await Task.Run(()-> WatsonTcp()) ...

for example:
public Task StartAsync()
{
if (_Mode == Mode.Tcp)
{
Log("Watson TCP server starting on " + _ListenerIp + ":" + _ListenerPort);
}
else if (_Mode == Mode.Ssl)
{
Log("Watson TCP SSL server starting on " + _ListenerIp + ":" + _ListenerPort);
}
else
{
throw new ArgumentException("Unknown mode: " + _Mode.ToString());
}

        return AcceptConnections();
    }

Thanks,
Csaba

SocketException

Greetings,
As may expected with the debug Logs now at hand, i got the exception message finally.
But still, dont know how to solve it .
After spending already hours on it , ill try to ask for help with it ,

Basicly i know from where the issue comes... - sending the stream with a dictionary as metadata.
If i remove the metadata, or, send a almost empty dictionary, it works fine...
Maybe im overlooking something obvious..

The exception :

Message build from stream exception:
System.Net.Sockets.SocketException (0x80004005): The operation completed successfully
   at WatsonTcp.Message.WatsonMessage.<ReadFromNetwork>d__47.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at WatsonTcp.Message.WatsonMessage.<BuildStream>d__40.MoveNext()

And the currently used method to send:

public async Task UploadFileAsync(string zipfile)
       {
           
           var metadata = InputDictionary(); 
           using (FileStream source = new FileStream(zipfile, FileMode.Open, FileAccess.Read))
           { 
               
              await client.SendAsync(InputDictionary(), source.Length, source);
           }
       }
       
       private static Dictionary<object, object> InputDictionaryT()
       {
           Dictionary<object, object> ret = new Dictionary<object, object>();
           if (filemissD.Count > 0)
           {
               foreach (var x in filemissD)
               {
                   ret.Add(x.Key, x.Value);
                  
               }
           }
           return ret;
       }

Is it scalable?

Hi. I am interested in this lib. I want to know whether it is capable to server 10K+ connections?

Thanks

Intellisense not showing Comments

I had mentioned this on the other discussion, but I'm just adding it here as an item for you to look into.

I double-checked. I've added Watson via Nuget, and Intellisense comments don't show up for any of the Watson types or methods. Other Nuget libraries in my project seems to be working fine.

Server rejects new connections after a bad connect

Hi,
After a bad connect, the server rejects all new connections. This can be replicated by using the SSL server and then connecting to it with putty.
Simple fix though :)

Replace all the occurrences of "return" with "continue" in the while loop of AcceptConnections.
thanks
Mike

Showing SendAsync Upload/Download Progress

Greetings,
Me again haha.
So far, everything worked fine, and now also as i want it.
Already made a bunch of updates with my tool.

Now im at optimizing, and improving the user experience.
A bit portion of that is to show the user whats going on.
Got quite a few reports that it seemed like the program would " freeze "
where, in reality it just uploaded the file still.
is there any way to get a progress report when using client.sendasync method?

I rather not use just a different upload method, as so far everything is pretty much contained and uses the same api , don't want to start mixing things up.

Here my example code were i would need such ability.

public async Task UploadFileAsync(string zipfile)
        {
            var metadata = new Dictionary<object, object>
            {
                {xxx, xxx}
            };
            using (var source = new FileStream(zipfile, FileMode.Open, FileAccess.Read))
            {
                await client.SendAsync(metadata, source.Length, source);
            }
          }

Message is not received fully

When I sent a xml file from telnet then i am not receiving the data in the TCP server side.

Then i checked the code and came to know that THIS TCP SERVER CODE ONLY WORK WITH WATSON TCP CLIENT.

Is there any way to use this WaTSON TCP SERVER code with outside work TCP client apps ( telnet, tera term other TCP client code?

please advise..

How to stop the server?

hey. In my opinion, the Dispose method should

  1. Disconnect all clients
  2. Close the TcpListener

but it's not like that

SSL

I'm unable to get Test Client to connect with the Test Server with SSL enabled. The Server and Client options are given below. The certificate test.pfx exists in the same directory as the Test Server executable.

The Client throws an exception:
System.Security.Authentication.AuthenticationException: 'The remote certificate is invalid according to the validation procedure.'

Server IP: [127.0.0.1]
Server port: [9000]
Use SSL: [y/N]? y
Certificate file: [test.pfx]
Certificate password: [password]
Accept invalid certs: [Y/n]? n
Mutually authenticate: [y/N]? n
Command [? for help]:

Server IP: [127.0.0.1]
Server port: [9000]
Use SSL: [y/N]? y
Supply SSL certificate: [y/N]? n
Accept invalid certs: [Y/n]? n
Mutually authenticate: [y/N]? n

All connections/clients crash when one disconnects

I have multiple clients running instances of my application. I cap the amount of instances each client is allowed to run, but whenever someone goes over the allowed amount, all instances on the same machine all crash. Server says it's a normal disconnect, and clients say to use Connect() practically meaning it was disconnected.

Here is my setup,

Server

SocketServer = new WatsonTcpServer(null, 1337, "server.pfx", "password") {
 PresharedKey = "presharedkey",
  MutuallyAuthenticate = true,
  AcceptInvalidCertificates = true,
  IdleClientTimeoutSeconds = TimeSpan.FromMinutes(5).Seconds
};

Client

SocketClient = new WatsonTcpClient(ClientAddress, 1337, "client.pfx", "password") {
 MutuallyAuthenticate = true,
  AcceptInvalidCertificates = true,
  Logger = delegate(string s) {
   Log.Debug("[{system}] {s}", "WatsonTcp", s);
  }
};

What does SendAsync() actually do?

Now that I've had to do a lot of digging on the implications of Async(), I've got more questions.

According to the MSDN doc on TcpClient, all you need to do to send data is write to the NetworkStream. The document does not explicitly state this...BUT: that should be a non-blocking operation, because the client itself should be reading on a separate thread.

That being said... what value is there in a SendAsync() method? I would expect Watson's send method does nothing more than write to the underlying network stream. There shouldn't be any reason to do that asynchronously because there's no need to await such a fast operation.

Is my understanding of the mechanics incorrect?

How to get the ipPort of client

Hi,

thanks for this project. It works well.
Only one thing is how can I get the ipPort value of client which send me the message ?
In message received event I only have the data and I dont want to transfer this ipPort in the data[]

Feature request: Disconnect Idle Clients

I think this is a standard base-level feature you'd want in any TCP Server. I'm implementing this in my own abstraction for Watson. It'd be nice if it was just built-in.

Suggested implementation:
Consumer configures Watson Server with a ClientMaximumIdle time and if no data is received from a client for that period of time, server disconnects the client.

Different TargetFrameworks

Hi,
I was looking at this project again, came across an inconsistancy, just wanted to make you aware of it.

All the original projects target
netstandard2.0 and net452

The new test projects - TestServerStream and TestClientStream target
netcoreapp2.2

On a separate note, i have applied a some of the Roslyn, FxCopAnalyzers and StyleCop.Analyzers to my branch of this and a few other things. Can send a pull request if you would like the changes. Have a flick through, lot of commits, all are pretty small.
https://github.com/MrMikeJJ/WatsonTcp/commits/master

8th July did the analysers stuff, 9th July, bits of refactoring.

thanks
Mike

Feature request: Disconnect Reason

So the idle disconnect appears to be working. :) :)

Shown here, server running in top window and client in bottom window. Client is using my own autoReconnect logic.

image

But, now that I see it in operation, on the server side it's disconcerting to not know WHY a client disconnected. Most applications I've ever worked in say a reason like "Idle Disconnect" or something so you know whether the client intentionally disconnected or timed out. Even a basic chat app or game would have this expectation of knowing a reason.

I think the cleanest way to address this is to add a a second parameter to the ClientDisconnected event handler. ClientDisconnected(string ipPort, DisconnectReason reason)

where DisconnectReason is an enum with options:
ClientDisconnected
ClientIdleTimeout

Let me know what you think.

Performance question

Hello,

Could you or someone else post a performance documentation. I am about to go prod, and kinda unable to reproduce the expected load. Nothing fancy, like "average payload size is x, with y connection per sec is okay, no drama,
usual response time is z, above ... we started to have problems" or something like this.

Thank you in advance,
Csaba

SSL client certificate authentication?

Can you confirm, does the new SSL support include client certificate Authentication? If so, can you document how that is configured? If not, can it be implemented as a feature request?

ListClients() exposes a List instead of IReadOnlyCollection or IEnumerable

I hadn't implemented usage of this yet, or I would have noticed and commented sooner.

Watson returns a List when ListClients() is accessed. This is generally not good practice for a library. You should always return the most abstracted collection you can possibly return.

Returning a List says to the consumer "Hey, you can add items to this." I don't think that's what you want at all. If somebody wants to alter the connected clients, they should be doing it via the other library calls.

IReadOnlyCollection would be a much better return type if your goal is to allow Indexing.

Bear in mind, it also only makes sense to return an Indexable collection if you are guaranteeing the same ordering every time you provide it. Otherwise, indexing is pretty much useless to the Consumer. If same ordering is not guaranteed, switch to an IEnumerable

There are other benefits about this to you as the library maintainer. For instance, if you return an IReadOnlyCollection or an IEnumerable, you can use any kind of backing collection underneath that supports those types. So if your clients are stored in a Dictionary, then you can return the Dictionary.Values collection without converting it to a List first. This will perform much faster than having to write to a List first.

--- Of course, if there's some specific reason you opted to return a List, you can enlighten me. :)

Client Disconnection

Hey! Excellent project. I just want to get a question. Should I create a task to check if a client is still logged in? Given that if I force the client to shut down the server does not detect the disconnect.

Message received not triggered on server or client

WatsonTcpServer never triggers/displays received data from server.

to reproduce:

  1. clone project
  2. open in VS, set TestServer as StartpuProject
  3. run the app
  4. connect client - detected by server OK
  5. send message to client - WORKS
  6. send message to server- does not work

Problems with setting used hooks.

Greetings.
So far it worked all fine, the new methods helped me out a lot,
Made a custom "CurrentClient" class with additional info to be send with the metadata.

But as i went to test run the first time i got some problems. Here a small recording, - explains better then words http://dmt.ovh/images/webm/kloyZ.webm

Also . - is there any way to enable both methods?
Stream with metadata And Message received ?
in current code i used the Message received method as a sort of callback, as i only had a small string to send and no bigger stream or metadata.

Thanks

error in vb.net

i used watsontcp in vb.net but when run this error occurd.i can i fix it.
mycode:
Dim server As New WatsonTcpServer("192.168.1.5", 2992, AddressOf ClientConnected, AddressOf ClientDisconnected, AddressOf MessageReceived, False)

error:
An unhandled exception of type 'System.TypeLoadException' occurred in System.Windows.Forms.dll

Additional information: Could not load type 'WatsonTcp.WatsonTcpServer' from assembly 'WatsonTcp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

Sending additional info with stream?

Greetings!
Ive been using WatsonTCP now for a while, and it has served me great so far.
Just started working with the new version, as mine was pretty old.

Now i got some problems, i did setup everything so far that a file transfer
client->server , works fine. My Problem is , that i have to assign all of the files their proper filename.
I tried it already with merging 2 streams together to append some string containing additional infos, but that only ends up in a mess that most likely will throw exceptions in normal usage of the users.

Is there mabe some overload method or some other way to add something to send within the same message?

Thanks-

Support for .NET Core, .NET Standard and other

Hey,
I tested your library - is perfect and I love it (on .NET Core)
Because I am on work PC, i can't make a pull request for you :(

Would be nice to add other framework support.

Regards,
TheAifam5

Client connection doesn't close at server side

When client disconnects some client worker thread stays working with 100% load in WatsonTcpServer. If i disconnect four times on my 4-core PC then my CPU load goes 100%.

VS thread debug window shows that those threads are here:
System.Net.Sockets.dll!System.Net.Sockets.SocketAsyncEventArgs.DoOperationReceiveSingleBuffer

Server ClientDisconnected event/callback isn't firing either.
Client is WatsonTcpClient which i just dispose (because there's no method to stop/disconnect).

Using latest version v2.0.2.

Empty PSH/ACK sent by client before sending actual data?

I am attempting to use Watson Server to receive connections from a 3rd party TCP Client.

When I use Watson Client to connect to Watson Server, Data Receive events on the server work fine. But when the 3rd-party TCP Client connects and sends data to Watson Server, Watson's Data Receive event appears to never fire.

So I got out Wireshark and noticed something different in the packet traffic. When I send data from Watson Client, it first sends a PSH, ACK packet to the server, and the server responds with an ACK.... and THEN it sends the actual data packet. The 3rd party TCP client does not do the precursor packet transaction. The 3rd party just sends its data as soon as it wants to.

So Question 1: Why does Watson Client send an empty packet with a PSH,ACK and wait for a response before sending the actual data? This already seems like an unnecessary round trip.

Question 2: Is Watson Server depending on this behavior? If so, that would explain why its not alerting me when it gets an unexpected data packet from the other system's client.

Stuck on 64KB+ data

Hi Joel,

I hit one issue when transmitting data (messages) larger than TCP maximum (over 64KB) from server to client. It's in the same place as issue #31 . There's a while (true) loop in WatsonMessage.cs:

while (true)
{
	read = await _NetworkStream.ReadAsync(buffer, 0, buffer.Length);
	if (read == count)
	{
		ret = new byte[read];
		Buffer.BlockCopy(buffer, 0, ret, 0, read);
		break;
	}
	if (read == 0)
	{
		throw new SocketException();
	}
}

In my case server response (and therefore buffer.Length) is 256KB but sometimes the ReadAsync function returns less data (64KB). Basically it returns data in frames. In such case this loop stucks forever.

Please check this post, there's a fix and link to explanation:
https://stackoverflow.com/a/55755530/4370728

I haven't checked how if same issue is on server side also...

SendAndWait TimeoutException with 4.0.0 version

Hi,
today i've updated WatsonTcp library in my projects from 3.1.4 to 4.0.0 version and the SendAndWait calls throws always a Timeoutexception.

I've created a minimal example project to check if i did something wrong but the problem is in the library and the Expiration field in header message (i think is the string format of datetime with the Z).

enabling debug messages and log i can see the server trashes the message immediatly after receiving it:

11:46:13.450 --> [WatsonTcpServer] Starting on 0.0.0.0:23456
11:46:22.981 --> [WatsonTcpServer] Starting data receiver for 10.10.3.12:38387
11:46:22.981 --> [WatsonTcpServer] Accepted connection from 10.10.3.12:38387
Client connected: 10.10.3.12:38387
11:46:31.952 --> [WatsonMessage] ReadHeaders found header demarcation
11:46:32.122 --> [WatsonMessage] ReadHeaders header processing complete {"Status":"Normal","SyncRequest":true,"SyncResponse":false,"Expiration":"2020-04-10T09:47:01.7335196Z","ConversationGuid":"8d201325-9be4-44d2-bd08-162f4101f14f" ,"ContentLength":24,"Metadata":{}}    
11:46:32.123 --> [WatsonTcpServer] Expired synchronous request received and discarded from 10.10.3.12:38387

this is the client log:

11:46:22.921 --> [WatsonTcpClient] Connecting to rds-dev:23456
11:46:23.000 --> [WatsonTcpClient] Connected to server
Connected to server
Write 'q' to quit application or 's' to send sync request.
s
11:46:31.732 --> start sync request
11:47:01.798 --> System.TimeoutException: A response to a synchronous request was not received within the timeout window.
   at WatsonTcp.WatsonTcpClient.GetSyncResponse(String guid, DateTime expirationUtc)
   at WatsonTcp.WatsonTcpClient.SendAndWaitInternal(WatsonMessage msg, Int32 timeoutMs, Int64 contentLength, Stream stream)
   at WatsonTcp.WatsonTcpClient.SendAndWaitInternal(WatsonMessage msg, Int32 timeoutMs, Byte[] data)
   at WatsonTcp.WatsonTcpClient.SendAndWait(Dictionary`2 metadata, Int32 timeoutMs, Byte[] data)
   at WatsonTcp.WatsonTcpClient.SendAndWait(Int32 timeoutMs, String data)
   at Client.Program.Main(String[] args) in C:\Users\xxxxx\Source\Repos\WatsonTCP\TestSyncCall\Client\Client\Program.cs:line 33
Write 'q' to quit application or 's' to send async request.

this is the server file:

class Program
{
    static string clientIpPort;
    static WatsonTcpServer srv;

    static void Main(string[] args)
    {
        srv = new WatsonTcpServer("", 23456);
        srv.ClientConnected += Srv_ClientConnected;
        srv.ClientDisconnected += Srv_ClientDisconnected;
        srv.MessageReceived += Srv_MessageReceived;
        srv.SyncRequestReceived = SyncRequestReceived;
        srv.Logger = log;
        srv.DebugMessages = true;
        srv.Start();

        Console.ReadLine();
    }

    private static void log(string txt)
    {
        Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + " --> " + txt);
    }

    private static void Srv_MessageReceived(object sender, MessageReceivedFromClientEventArgs e)
    {
        Console.WriteLine($"Message received from {e.IpPort}: {Encoding.UTF8.GetString(e.Data)}");
    }



    private static SyncResponse SyncRequestReceived(SyncRequest req)
    {
        Console.WriteLine($"Syncrequest received from {req.IpPort}: {Encoding.UTF8.GetString(req.Data)}");
        SyncResponse ret;

        System.Threading.Thread.Sleep(5000);
        ret = new SyncResponse(req, "Long work done :-)");

        Console.WriteLine("Syncrequest completed");
        return ret;
    }

    private static void Srv_ClientConnected(object sender, ClientConnectedEventArgs e)
    {
        clientIpPort = e.IpPort;
        Console.WriteLine($"Client connected: {e.IpPort}");
    }
    private static void Srv_ClientDisconnected(object sender, ClientDisconnectedEventArgs e)
    {
        clientIpPort = null;
        Console.WriteLine($"Client DISCONNECTED: {e.IpPort}");
    }
}

This is the client:

class Program
{

    static void Main(string[] args)
    {
        WatsonTcpClient cli = new WatsonTcpClient("rds-dev", 23456);
        cli.ServerConnected += Cli_ServerConnected;
        cli.MessageReceived += Cli_MessageReceived;
        cli.DebugMessages = true;
        cli.Logger = log;
        cli.Start();

        Console.WriteLine("Write 'q' to quit application or 's' to send sync request.");
        string read= Console.ReadLine();

        while (read != "q")
        {
            if (read == "s")
            {
                try
                {
                    log("start sync request");
                    SyncResponse rsp = cli.SendAndWait(30000, "Long execution requested");
                    log($"Response from server: {Encoding.UTF8.GetString(rsp.Data)}");
                }
                catch(Exception ex)
                {
                    log(ex.ToString());
                }
            }

            Console.WriteLine("Write 'q' to quit application or 's' to send async request.");
            read = Console.ReadLine();

        }
    }

    private static void log(string txt) {
        Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + " --> " + txt);
    }

    private static void Cli_MessageReceived(object sender, MessageReceivedFromServerEventArgs e)
    {
        Console.WriteLine($"Message received from server: {Encoding.UTF8.GetString(e.Data)}");
    }

    private static void Cli_ServerConnected(object sender, EventArgs e)
    {
        Console.WriteLine($"Connected to server");
    }
}

thanks for attention :-)
Ozrecsec

MessageReceived and StreamReceived share the same Comment

StreamReceived says "Method to call when a message is received..."
The MessageReceived comment says the same thing.

Need a clear technical difference to know which one to use.

Does streamreceived fire as soon as a single byte is received?
Does it fire when a single packet is fully received?
Does it fire when an entire frame is received?
etc.

And what about Message?

How do disconnect from client?

The examples simply quit and looking through the source I couldn't find a disconnect method. How should a client disconnect? I've used client.dispose() which does the job apparently but it doesn't really seem elegant.

Help/Problem timeout sendandwait

Hello,

I really need help with the Server/Client..
My Configuration of the Server is

public static class AsyncServer
    {
        private static string serverIp = "10.0.0.46";
        public static int ServerPort = 9000;
        private static bool useSsl = false;
        private static WatsonTcpServer server = null;
        private static string certFile = "";
        private static string certPass = "";
        private static bool debugMessages = false;
        private static bool acceptInvalidCerts = true;
        private static bool mutualAuthentication = true;

        public static void ConfigServer()
        {
            server = new WatsonTcpServer(serverIp, ServerPort);
            server.ClientConnected += ClientConnected;
            server.ClientDisconnected += ClientDisconnected;
            server.MessageReceived += MessageReceived;
            server.SyncRequestReceived = SyncRequestReceived;
            // server.PresharedKey = "0000000000000000";
            // server.IdleClientTimeoutSeconds = 10;
            logger.Info("Server configuration done");
        }

        public static void StartServer()
        {
            Task serverStart = server.StartAsync();
        }

My client:

public static class AsyncClient
    {
        public static  string ServerIp { get; set; }
        public static int ServerPort { get; set; }
        private static bool useSsl = false;
        private static string certFile = "";
        private static string certPass = "";
        private static bool debugMessages = false;
        private static bool mutualAuthentication = true;
        private static WatsonTcpClient client = null;
        private static string presharedKey = null;

        public static void ConfigClient()
        {
            client = new WatsonTcpClient(ServerIp, ServerPort);
            client.ServerConnected += ServerConnected;
            client.ServerDisconnected += ServerDisconnected;
            client.MessageReceived += MessageReceived;
            client.SyncRequestReceived = SyncRequestReceived;
        }

        public static void StartClient()
        {
            try
            {
                Task startClient = client.StartAsync();
            }
            catch (Exception ex)
            {
                logger.Error("Could not connect to server: {0} Port: {1}", ServerIp, ServerPort);
            }
        }

I want to SendAndWait:

public static void SendAndWait()
        {
            int timeoutMs = 20000;
            string userInput = "testingstring";
            try
            {
                SyncResponse resp = client.SendAndWait(timeoutMs, userInput);
                if (resp.Metadata != null && resp.Metadata.Count > 0)
                {
                    logger.Info("Metadata:");
                    foreach (KeyValuePair<object, object> curr in resp.Metadata)
                    {
                    }
                }
            }
            catch (Exception e)
            {
            }
        }

At server side

private static SyncResponse SyncRequestReceived(SyncRequest req)
        {
            if (req.Metadata != null && req.Metadata.Count > 0)
            {
                logger.Info("Metadata:");
                foreach (KeyValuePair<object, object> curr in req.Metadata)
                {
                    logger.Info("  " + curr.Key.ToString() + ": " + curr.Value.ToString());
                }
            }
            Dictionary<object, object> retMetadata = new Dictionary<object, object>();
            retMetadata.Add("foo", "bar");
            retMetadata.Add("bar", "baz");

            return new SyncResponse(req,retMetadata, "Here is your response!");
        }

It is the same sample as stored in git.
If i download the current version from git and test ist, everything is fine.
But if i do the same thing with the code above I always get the timeout exception (no msg received after timeout)
If i debug then the server recognize the incomming msg and work and "send" back.

Can anybody help me?

nice greetings phil

Help with multiple uploads

Greetings.
Ok, this is not so much of an issue then rather asking for a bit help.

So far its working all fine, also managed to find a solution for my problem with message/stream received.
( Just assigned streamreceived + streamreceivedwithmeta ) Works .

now im trying to get multiple files over , as i already suspected before , i dont think parallel/multi upload would work here, which is fine.
If i test the whole upload / receive methods on both ends with only 1 file / stream
It works like i wanted. The problem occurs if i try to loop trough all the made signatures i want to upload.
For all else i used a backgroundworker to do stuff in, but for this i also tried static void methods, await tasks ( which i really dont understand well enough ) and some other small changes i tried.
but the closest result i get is , completing of uploading the file, but then the client disconnects suddenly from the server...
this is how it looks :

foreach (var x in Signatures)
            {
                Dictionary<object, object> metadata = new Dictionary<object, object>();
                    metadata.Add(x.Key, x.Value);
                    filecounter++;
                    using (FileStream fss = new FileStream(x.Value, FileMode.Open, FileAccess.Read))
                    {
                        
                        while (!client.SendAsync(metadata, fss.Length, fss).Result)
                        {
                            
                        }

                        // or just bool success = client.SendAsync(metadata, fss.Length, fss).Result
                    }
                    processedFilesCount++;
                    BackgroundWorker4.ReportProgress(i);
                    progressBar1.Value = i;
            }

how many connections can this handle simultaneously

Hi,

If yes, how many max connections can this handle simultaneously?

Because currently I have a TCP server developed using SuperSocket.NET. But having issues in sending Acknowledgement's to the devices.

So if I use this library, how many requests can it handle?

Thanks

When server receives data

I'm sure I am just being stupid here, but when handling byte arrays (non stream), and the server receives data, how do we respond to the client? Working off the test code I can't obviously see how server.messagereceived can ping back an "ok all good" type of message to the client.

Thanks.

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.