I have an application in C# that is a TCP server listening to a port. GPS devices connect to this port. The application is accepting the TCP client and creating a new thread for each client. The client ID in maintained in a hash table that is updated when a client is connected. this was all working fine until around 400 units. Once the number of units increased, the server was unable to handle all connections. The connections are being continuously dropped and once in awhile leads eating up the server CPU and memory and brings it down. Work around was to open another instance of the TCP server listening to a different port and diverted some units to that port. Currently some 1800 units are somehow running in 8 different ports. The server is extremely unstable and units are still unable to stay connected. Facing too many issues on a daily basis. Also using remoting to send settings via the remoting port - this is working only sometimes.
Please help by giving a solution for TCP socket/threading/thread pooling etc. that is both scalable and robust and can in a single port.
This TCP server is running in Windows server 2008 R2 Enterprise with IIS7 and SQL server 2008.
Processor: Intel Xenon CPU E3-1270 V2 #3.50GHz
RAM: 32GB
System: 64-bit operating system
Thanks
Jonathan
Basically, don't use a thread per socket; use one of the async APIs (BeginReceive / ReceiveAsync), or some kind of socket polling (Socket.Select for example, although note that this is implemented in a very awkward way; when I use this, I actually use P/Invoke to get to the raw underlying API). Right at this moment, I have > 30k sockets per process talking to our web-sockets server (which is implemented via via Socket). Note that for OS reasons we do split that over a few different ports - mainly due to limitations of our load-balancer:
One thread per connection is not a really good idea specially when you have to handle 100s of client concurrently.Asynchronous is the way to go with some buffer pooling/managing. If you are looking for something to start with asynchronous sockets have a look at this basic implementation if you are looking for something complete Take a look at this(explanation: Here)
If you are willing check this out too.
In C# you can go with classical BeginXXX/EndXXX methods. Microsoft also have a High Performance Socket API which can be leveraged using XXXAsync methods. A few articles which explain the High Performance Socket API Here and Here
Related
In my project I have a cloud hosted virtual machine running a C# application which needs to:
accept TCP connection from several external clients (approximately 500)
receive data asynchronously from the connected clients (not high frequency, approximately 1 message per minute)
do some processing on received data
forward received data to other actors
reply back to connected clients and possibly do some asynchronous sending (based on internal time-checks)
The design seems to me quite straightforward. I provide a listener which accepts incoming TCP connection, when a new connection is establhised a new thread is spawned; that thread runs in loop (performing activities points from 2 to 5) and check for associated socket aliveness (if socket is dead, the thread exits the loop and would eventually terminate; later a new connection will be attempted from the external client the socket belonged to).
So now the issue is that for limited amount of external clients (I would say 200/300) everything runs smoothly, but as that number grows (or when the clients send data with higher frequency) the communication gets very slow and obstructed.
I was thinking about some better design, for example:
using Tasks instead of Threads
using ThreadPool
replace 1Thread1Socket with something like 1Thread10Socket
or even some scaling strategies:
open two different TCP listeners (different port) within the same application (reconfiguring clients so that half of them target each listener)
provide two identical application with two different TCP listeners (different port) on the same virtual machine
set up two different virtual machines with the same application running on each of them (reconfiguring clients so that half of them target each virtual machine address)
Finally the questions: is the current design poor or naive? do you see any major criticality in the way I handle the communication? do you have any more robust and efficient option (among those mentioned above, or any additional one)?
Thanks
The number of listeners is unlikely to be a limiting factor. Here at Stack Overflow we handle ~60k sockets per instance, and the only reason we need multiple listeners is so we can split the traffic over multiple ports to avoid ephemeral port exhaustion at the load balancer. Likewise, I should note that those 60k per-instance socket servers run at basically zero CPU, so: it is premature to think about multiple exes, VMs, etc. That is not the problem. The problem is the code, and distributing a poor socket infrastructure over multiple processes just hides the problem.
Writing high performance socket servers is hard, but the good news is: you can avoid most of this. Kestrel (the ASP.NET Core http server) can act as a perfectly good TCP server, dealing with most of the horrible bits of async, sockets, buffer management, etc for you, so all you have to worry about is the actual data processing. The "pipelines" API even deals with back-buffers for you, so you don't need to worry about over-read.
An extensive walkthrough of this is in my 3-and-a-bit part blog series starting here - it is simply way too much information to try and post here. But it links through to a demo server - a dummy redis server hosted via Kestrel. It can also be hosted without Kestrel, using Pipelines.Sockets.Unofficial, but... frankly I'd use Kestrel. The server shown there is broadly similar (in terms of broad initialization - not the actual things it does) to our 60k-per-instance web-socket tier.
I have the same dilemma as the one who posted this topic, Real-time communication with WCF
except that my problem is not about games programming. I would like to know what's the best method to use to be able to have a real time communication in between two windows applications (server-client). I am using visual c++/c# to date and i would like to be able to display all the Feeds that are being received by my server to the client in real time.
I have started trying to use .NET remoting but in my continuous research, it appears that it will use SOAP-http, and might affect the speed of the communication. My server and client will communicate using the internet and .NET remoting does not permit the use of TCP Channel when communicating in between a firewall or the internet.
Your inputs will be greatly appreciated.
I guess it depends on your escenario, if you want "real-time" and you are willing to lose some packages in the process you are better with UDP, take a video conferencing tool for example, by the time you recover your slow packages you will have to move and display the next frame in the video or audio; that is a good example for the use of UDP. This is the reason why UDP is much faster than TCP.
If however, you are not willing to lose a single bit of your message, then TCP was made for you because if you lost a package the protocol will request it again to have your complete message as complete as possible.
Additionally it depends on the way the communication is being sustained, is the information flowing from one to many?, from many to many?, one to tone?
Take NetNamedPipeBinding for instance, this will be much faster process, but is only deployed in a single machine but accross processes. Whereas NetMsmqBinding will help you to build queues and it will be amazingly reliable and scalable for scenarios where your load will be a massive number of connections.
In the end, it all boils down to your concrete escenario and your business goals.
Hope it helps
If you are willing to do your own message parsing, you can use standard TCP sockets with the TcpClient and TcpListener classes. If your data is already a serializable object, you could serialize it into a text stream and just send it over the socket, deserializing it on the client side.
To get it to work over the internet, the server needs to have the port forwarded on your router, the client would just attach to the server's public IP. You would obviously need to add an exception in your firewall for this port as well.
The biggest problem with WCF and large data is setting up the streaming, by default WCF sends everything at once, which isn't practical for large files.
When I was experimenting with C# and WCF one of the things I kept reading about was how unscalable it is to have clients with a constant current connection to the server. And although WCF allows that it seems that the recommended best practise is to use 'per call' as opposed to 'per session' for instance management if you want to have any kind of decent scalablity. (Please correct me if Im wrong)
However from what I understand IRC uses constant client connections to the server and IRC servers (well networks of servers) are servicing hundreds of thousands of clients at any given time. So in that case is there nothing actually 'bad' about keeping constant client connections to the server?
As long as you don't follow the one-thread-per-connection architecture, a server can support quite a large number of concurrent TCP connections.
IRC doesn't require much per connection state, beyond the TCP send and receive windows.
If you need real-time duplex communication (IRC is a chat protocol), then keeping a TCP connection alive is a relevant option. However, TCP connection brings network overhead and operating systems have practical limits on the number of concurrent open TCP connections. WCF is commonly used in SOAP/HTTP/RPC contexts where duplex communication is not required, but certainly it offers suitable bindings and channels for that as well. To answer your question, there is nothing bad in keeping the connection open if you have real-time, duplex requirements for your communication.
Yes, such architecture is feasible, but... The "ping? pong!" thing was invented for a reason - to let both parties know that the other party is still there. You cannot actually tell if a client is idle, because it does not have much to say or because it is actually disconnected and you are waiting for a TCP timeout.
UPD: "hundreds of thousands of clients" is possible on IRCnet only because of server networks. For a single machine, the C10K problem is still an issue.
Users in field with PDA's will generate messages and send to the server; users at the server end will generate messages which need to be sent to the PDA.
Messages are between the app and server code; not 100% user entered data. Ie, we'll capture some data in a form, add GPS location, time date and such and send that to the server.
Server may send us messages like updates to database records used in the PDA app, messages for the user etc.
For messages from the PDA to server, that's easy. PDA initiates call to server and passes data. Presently using web services at the server end and "add new web reference" and associated code on the PDA.
I'm coming unstuck trying to get messages from the the server to the PDA in a timely fashion. In some instances receiving the message quickly is important.
If the server had a message for a particular PDA, it would be great for the PDA to receive that within a few seconds of it being available. So polling once a minute is out; polling once a second will generate a lot of traffic and, maybe draim the PDA battery some ?
This post is the same question as mine and suggests http long polling:
Windows Mobile 6.0/6.5 - Push Notification
I've looked into WCF callbacks and they appear to be exactly what I want however, unavailable for compact framework.
This next post isn't for CF but raises issues of service availability:
To poll or not to poll (in a web services context)
In my context i'll have 500-700 devices wanting to communicate with a small number of web services (between 2-5).
That's a lot of long poll requests to keep open.
Is sockets the way to go ? Again that's a lot of connections.
I've also read about methods using exchange or gmail; i'm really hesitant to go down those paths.
Most of the posts i've found here and in google are a few years old; something may have come up since then ?
What's the best way to handle 500-700 PDA CF devices wanting near-instant communication from a server, whilst maintaing battery life ? Tall request i'm sure.
Socket communication seems like the easiest approach. You say you're using webservices for client-server comms, and that is essentially done behind the scenes by the server (webservice) opening a socket and listening for packets arriving, then responding to those packets.
You want to take the same approach in reverse, so each client opens a socket on its machine and waits for traffic to arrive. The client will basically need to poll its own socket (which doesnt incur any network traffic). Client will also need to communicate its ip address and socket to the server so that when the server needs to communicate back to the client it has a means of reaching it. The server will then use socket based comms (as opposed to webservices) to send messages out as required. Server can just open a socket, send message, then close socket again. No need to have lots of permanently open sockets.
There are potential catches though if the client is roaming around and hopping between networks. If this is the case then its likely that the ip address will be changing (and client will need to open a new socket and pass the new ip address/socket info to the server). It also increases the chances that the server will fail to communicate with the client.
Sounds like an interesting project. Good luck!
Ages ago, the CF team built an application called the "Lunch Launcher" which was based on WCF store-and-forward messaging. David Kline did a nice series on it (here the last one, which has a TOC for all earlier articles).
There's an on-demand Webcast on MSDN given by Jim Wilson that gives an outline of store-and-forward and the code from that webcast is available here.
This might do what you want, though it got some dependencies (e.g. Exchange) and some inherent limitations (e.g. no built-in delivery confirmation).
Ok, further looking and I may be closer to what I want; which I think i a form of http long poll anyway.
This article here - http://www.codeproject.com/KB/IP/socketsincsharp.aspx - shows how to have a listener on a socket. So I do this on the server side.
Client side then opens a socket to the server at this port; sends it's device ID.
Server code first checks to see if there is a response for that device. If there is, it responds.
If not, it either polls itself or subscribes to some event; then returns when it's got data.
I could put in place time out code on the server side if needed.
Blocking on the client end i'm not worried about because it's a background thread and no data is the same as blocking at the app level; as to CPU & batter life, not sure.
I know what i've written is fairly broad, but is this a strategy worth exploring ?
I am about to develop a Network measurement tool. The objective is to make a tool, which can measure the responsetime in between a client and a server machine (from the client side). It is s side-application to a main application - If the main applicaiton experiences that the responsetime from the server is above a certain threshold, the tool will be kicked alive, and performs network connectivity tests, to determine of the client server connection is stable (it might be unstable, due to the network being wireless etc.)
The tests I need to perform are not just ping operations, but also transmitting packages of different size.
I have however very little experience in communications technology.
Is ICMP protocol the way to go? and if yes, is it possible to send packages of differnet sizes (to measure if the network is able to transfer eg. 2 MB of data in a reasonable time)?
I have a second concern. What should I look out for in regards to firewalls? It would be a shame to develop an application which works fine on my local network, but as soon as it is used out in the real life, it fails misserably because the tests are blocked by a firewall.
I hope my questions aren't too noobish, but know that any help is much appreciated.
All the best
/Sagi
To keep clear of firewalls, you should do a test using the same protocol and port you use, and create inside of your application a new type of message that should be responded as soon as it is read by the server: You should program your ping measures.
Then the client would measure the times spent in travel traveled and compute your ping and relay it back to your server. This also gives a better reading when in case of some ISPs that give a ICMP protocol packets a huge advantage over other packages on their QoS server, artificially creating(faking) lower latency. And also, you would not have to worry about the firewall not allowing your ICMP packets, because you would have to be allowed to conect on the standart port you use.
Also, most games work this way (Half-Life, Age Of Empires etc.) , and not by sending standard Ping packets.