I have a .NET 3.5 server application that usually has about 8 clients. I'm using System.Net.Sockets for all the networking.
I've been told that if a client is running on the same box, it should use localhost:<port> or 127.0.0.1:<port> instead of the machine's ip or name for better performance. Several people at work have said that this skips some layers of the tcp stack.
But I'm not able to see any performance difference at all in testing (timing how long it takes to get a ping packet from server to client using System.Diagnostics.Stopwatch).
Should there really be better performance in theory?
No, performance is same in both cases. If you are using your local device ip address, your operating system kernel don't transport your packets data to your network device and this data don't be was sended anywhere then you don't have any ISO layers calculations (encapsulation, decapsulation etc).
I belive the OS will see this is a local device and you treat it like it was 127.0.0.1. So in fact both will have the same effect.
I suppose it's possible that there will be an extremely tiny performance boost in using 127.0.0.1 (though I doubt it), but with 8 clients you'll never notice it. That performance difference would have to be aggregate over A LOT of traffic to become at all noticeable.
The larger concern would be which value is better from a maintenance perspective. If the application is always looking at localhost for external dependencies, it won't do well if run on another host. But if it's looking for a more universally understood address for those dependencies, it'll find them from anywhere on the network.
Related
I have a task where I need to understand the technical feasibility to setup a remote monitoring scenario for a HVAC solution which uses Bacnet/IP. I need to setup a .NET client that gets the telemetry and sends it to Azure IoT Hub. My current concern is to understand how can I connect to a Bacnet/IP network.
I don't have that much information information about the hardware installed besides the fact that it has sensors for pressure and humidity on the network and a DDC controller (EBCON - Delta Controls). As I was told, I don't need to care about the actually sensors since they are sending the telemetry to the controller, so I only to care about the controller and connect to it.
Yet based on what I have read so far, I have some doubts about this information, but I don't have the technical knowledge to support it. It seems that based on the information that I have read Bacnet communication is done by UDP listening on a port (which seems to go against the above information that I need to connect to a controller), if this is true and I listen on a UDP port, will all devices broadcast the telemetry on the network and I only need to be listening? What is the controller role then? Can I ignore it?
Any explanation or pointers can could help me understand this from a programmer PoV would be appreciated.
BACnet does indeed communicate via UDP. The scenario you describe, while possible, is quite a dangerous approach. Very few BACnet products offer any sort of BACnet protocol security, so to make a secure connection you will need to VPN into your site. Once on the VPN, then the VPN itself will most likely block broadcasts, so you will need to use BACnet "Foreign Device Registration" to connect. However most VPNs do a NAT translation too, so the BACnet server on site will have to supply "BACnet BBMD with FD with NAT" support. Quite rare. An alternative is to get a box on your site supplying connectivity from the site to the Azure IoT site. There are a few companies that offer this type of product, but it seems you want to program your own. This will not be trivial, and then you will have to do the "BACnet Object" to "whatever-data-format-you-need-on-Azure" mapping, which will need a rather deep understanding of the BACnet specification, which, on paper, is about 2.5 inches thick. You could ignore the VPN approach, port forward port 47808 (BACnet default, but it can be different per site config) to the controller. This is how some rather large companies have had their HVAC systems hacked. If you do pursue this approach, you will still need a BACNet Client-to-Azure mapping/transfer agent. You have not chosen a trivial project here. ;) Or you could purchase an off-the-shelf product (box) that does this all already.
And just by the way, there is a FOSS C# BACnet Client you can use for reference: https://sourceforge.net/projects/yetanotherbacnetexplorer/
For the benefit of others, if not also for yourself; there is the more BACnet-ty aspect of your question that I don't think has been addressed.
You have to be a bit more proactive with BACnet - you might have the presence of new devices (or at least devices that have just come online again) broadcast to you, but otherwise you have to actively read all the properties (/telemetry) values - at least the ones of interest.
There is the facility for subscribing for CoV (Change of Value) changes/values but at least in the past (if still not now) the concern was that this could flood the network, as well as possibly burden the device in having to keep sending updates to possibly many clients or just too-too often (above & beyond its primary job of monitoring & controlling the building for comfort and health & safety).
The standard does provide an 'object list' (upon 'device'-type objects), and a 'property list' upon every object, but you'll probably find that the 'property-list' is never supported/implemented despite it been a mandatory property (!?!).
So this is where you have to take an interest in every physical device - at least it's IP address & possibly MAC address too, along with all it's (relevant) objects & object-properties, for which you'll most likely have to sit with one/two/more engineers first to agree & understand as to what information that will actively be exposed (for you to monitor) & how (- e.g. the measurement units that a value is conveyed in).
In some cases (- e.g. maybe for small buildings), you might have to talk to all the devices individually, but in other cases you'll have points (/point 'object's) upon a gateway device that will represent all the devices that sit behind it.
So all in all, whether you direct to up to say 300 devices, or you interrogate 300 objects upon a gateway device - each one representing a physical device, you still might have a few properties of interest that you're interested in - under the guise of your telemetry, so 300 x 3 (for example), it adds up quite quickly, and then there's the error handling and complexity of the standard as a whole (- an uphill learning curve / you have to buy-in to understanding the foundations at least).
I'd recommend you also take a look at the (advanced & free) VTS (Visual Test Shell) tool.
Not sure if this helps but it was worth pointing out; underestimate BACnet at your own peril (!!). ;)
I'm looking to create some kind of a gateway that sits between a server and a client.
The so called gateway is supposed to filter some packets sent by the client and forward 99% of them.
Here are my questions:
Client opens a new socket to the gateway, i open a socket to the server from the gateway and store it in a list for further use. However, in one situation, all the connections will come from the same IP, thus leaving me with limited options on choosing the socket that should forward the packet to the server. How can i differentiate between opened sockets?
From previous situations, i'm expecting about 500 clients sending a packet every second. Performance wise, should i use a multithread model, or stick with a single thread application?
Still a performance question :I have to choose between C# and Python. Which one should give better performance?
Socket addresses are a host and port, not just a host. And different connections from the same host will always have different ports. (I'm assuming TCP, not UDP, here.)
Or, even more simply, you can just compare the file descriptors (or, in Python, the socket objects themselves) instead of their peer addresses.
Meanwhile, for performance, on most platforms, 500 is nearing the limits of what you can do with threads, but not yet over the limits, so you could do it that way. But I think you'll be better off with a single-threaded reactor or a proactor with a small thread pool. Especially if you can use a preexisting framework like twisted or gevents to do the hard part for you.
As for the language, for just forwarding or filtering packets, the performance of your socket multiplexing will be all that matters, so there's no problem using Python. Pick a framework you like from either language, and use that language.
Some last side comments: you do realize that TCP packets aren't going to match up with messages in your higher level protocol(s), right? Also, this whole thing would probably be a lot easier to do, and more efficient, with a Linux or BSD box set up as a router so you don't have to write anything but the filters.
I'm building a tool that transfers very large streaming data sets (possibly on the order of terabytes in a single stream; routinely in the tens of gigabytes) from one server to another. The client portion of the tool will read blocks from the source disk, and send them over the network. The server side will read these blocks off the network and write them to a file on the server disk.
Right now I'm trying to decide which transport to use. Options are raw TCP, and HTTP.
I really, REALLY want to be able to use HTTP. The HttpListener (or WCF if I want to go that route) make it easy to plug in to the HTTP Server API (http.sys), and I can get things like authentication and SSL for free. The problem right now is performance.
I wrote a simple test harness that sends 128K blocks of NULL bytes using the BeginWrite/EndWrite async I/O idiom, with async BeginRead/EndRead on the server side. I've modified this test harness so I can do this with either HTTP PUT operations via HttpWebRequest/HttpListener, or plain old socket writes using TcpClient/TcpListener. To rule out issues with network cards or network pathways, both the client and server are on one machine and communicate over localhost.
On my 12-core Windows 2008 R2 test server, the TCP version of this test harness can push bytes at 450MB/s, with minimal CPU usage. On the same box, the HTTP version of the test harness runs between 130MB/s and 200MB/s depending upon how I tweak it.
In both cases CPU usage is low, and the vast majority of what CPU usage there is is kernel time, so I'm pretty sure my usage of C# and the .NET runtime is not the bottleneck. The box has two 6-core Xeon X5650 processors, 24GB of single-ranked DDR3 RAM, and is used exclusively by me for my own performance testing.
I already know about HTTP client tweaks like ServicePointManager.MaxServicePointIdleTime, ServicePointManager.DefaultConnectionLimit, ServicePointManager.Expect100Continue, and HttpWebRequest.AllowWriteStreamBuffering.
Does anyone have any ideas for how I can get HTTP.sys performance beyond 200MB/s? Has anyone seen it perform this well on any environment?
UPDATE:
Here's a bit more detail on the performance I'm seeing with TcpListener vs HttpListener:
First, I wrote a TcpClient/TcpListener test. On my test box that was able to push 450MB/s.
Then using reflector I figured out how to get the raw Socket object underlying HttpWebRequest, and modified my HTTP client test to use that. Still no joy; barely 200MB/s.
My current theory is that http.sys is optimized for the typical IIS use case, which is lots of concurrent small requests, and lots of concurrent and possibly large responses. I hypothesize that in order to achieve this optimization, MSFT had to do so at the expense of what I'm trying to accomplish, which is very high throughput on a single very large request, with a very small response.
For what it's worth, I also tried up to 32 concurrent HTTP PUT operations to see if it could scale out, but there was still no joy; about 200MB/s.
Interestingly, on my development workstation, which is a quad-core Xeon Precision T7400 running 64-bit Windows 7, my TcpClient implementation is about 200MB/s, and the HTTP version is also about 200MB/s. Once I take it to a higher-end server-class machine running Server 2008 R2, the TcpClient code gets up to 450MB/s, while the HTTP.sys code stays around 200.
At this point I've sadly concluded that HTTP.sys is not the right tool for the job I need done, and will have to continue to use the hand-rolled socket protocol we've been using all along.
I can't see too much of interest except for this Tech Note. It might be worth having a fiddle with MaxBytesPerSend
If you're going to send files over the LAN then UDP is the way to go, because TCP's overhead is a waste in that case. TCP provides rate limiting to avoid too many lost packets, whereas with UDP the application has to sort that out by itself. NFS would do the job, were it not that you're stuck with windows; but I'm sure there must be ready made UDP stuff. Also use the tool "iperf" (available on linux, probably also windows) to benchmark the network link irrespective of the protocol. Some network cards are plain crap and rely on the CPU too much, which will limit your speed to 200mbit. You want a proper network card with its own processors (don't know the exact terms to put this).
I'm thinking like the methods games like Counter Sstrike, WoW etc uses. In CS you often have just like 50 ping, is there any way to send information to an online MySQL database at that speed?
Currently I'm using an online PHP script which my program requests, but this is really slow, because the program first has to send headers and post-information to it, and then retrieve the result as an ordinary webpage.
There really have to be any easier, faster way of doing this? I've heard about TCP/IP, is this what I should use here? Is it possible for it to connect to the database in a faster way than indirectly via the PHP script?
TCP/IP is made up of three protocols:
TCP
UDP
ICMP
ICMP is what you are using when you ping another computer on a network.
Games, like CounterStrike, don't care about what you previously did. So there's no requirement for completeness, to be able to reconstruct what you did (which is why competitors have to tape what they are doing). This is what UDP is used for - there's no guarantee that data is delivered or received. Which is why lag can be such a problem - you're already dead, you just didn't know it.
TCP guarantees that data is sent and received. Slower than UDP.
There are numerous things to be aware of to have a fast connection - less hops, etc.
Client-to-server for latency-critical stuff? Use non-blocking UDP.
For reliable stuff that can be a little slower, if you use TCP make sure you do so in a non-blocking fashion (select(), non-blocking send, etc.).
The big reason to use UDP is if you have time-sensitive data - if the position of a critter gets dropped, you're better off ignoring it and sending the next position packet rather than re-sending the last one.
And I don't think any high-performance game has each and every call resolve to a call to the database. It's more common to (if a database is even used) persist data occasionally, or at important events.
You're not going to implement Counterstrike or anything similar on top of http.
Most games like the ones you cite use UDP for this (one of the TCP/IP suite of protocols.) UDP is chosen over TCP for this application since it's lighter weight allowing for better performance and TCP's reliability features aren't necessary.
Keep in mind though, those games have standalone clients and servers usually written in C or C++. If your application is browser-based and you're trying to do this over HTTP then use a long-lived connection and strip back the headers as much as possible, including cookies. The Tornado framework may be of interest to you there. You may also want to look into HTML5 WebSockets however widespread support is still a fair way off.
If you are targeting a browser-based plugin like Flash, Java, SilverLight then you may be able to use UDP but I don't know enough about those platforms to confirm.
Edit:
Also worth mentioning: once your networking code and protocol is sufficiently optimized there are still things you can do to improve the experience for players with high pings.
I'm developing a server in C#. This server will act as a data server for a backup service: a client will send data, a lot of data, continuously, specifically will send data chunk of files, up to five, in the same tcp channel. I'll send data to the server slowly, i don't want to kill customer bandwidth, so i didn't need to speed up at max data send and, for this reason, i can use a single tcp channel for everything.
Said this, actually the server uses BeginReceive method to acquire data from client and, on windows, this means IOCP. My questions is: how BeginReceive will perform on linux/freebsd trough mono? On windows, i've read a lot of stuff, will perform very well but this software, the server part, will run on linux or freebsd trough mono and i don't know how these methods are implemented on it!
More, to try to reduce continue allocations of an Async State object for the (Begin|End)Receive method i mantain one for the tcp connection and in the BeginReceive callback i copy out data before reuse it (naturally i don't clear data in because i know how much read trough EndReceive return value). Buffer is set on 8kb so i'll at max copy out 8kb of data, it shouldn't kill resoruces.
My target is to get up to 400/500 connections at max. It isn't so much, but the server (machine), in the meantime, will handle files trough an own filesystem (developed using fuse first in C# and later in C) on LVM+Linux Software Raid Mirror and antivirus check using clamav so the software must be light as can!
EDIT: I forgot to say that the machine will be (probably) a Intel Core 2 Duo 2.66+ GHz (3 MB L2 - FSB 1066 MHz) with 2 GB of ram and the SO using 64 bits.
Is mono using epoll (libevent) or kqueue (on freebsd)? And I should do something specific to try to maximize performances? Can I do something more to don't kill resources receiving data packets?
I know it's a little late, but I just found this question...
Mono is able to handle the number of connections that you need and much more. I regularly test xsp2 (the Mono ASP.NET standalone server) with over 1k simultaneous connections.. If this is going to be a high load situation, you should play a bit with setting MONO_THREADS_PER_CPU until you find the right number of threads for the ThreadPool.
On linux, Mono uses epoll when available (which is always these days).
I can't speak specifically about the performance of that one function on mono, but in general mono performs very well these days. 4-500 connections is as you say, not very many, so I doubt you'd have any issues.
In saying that, it shouldn't be very hard to set a test for this kind of thing up. I think that's probably the only way you'll get a conclusive answer for your situation.