I am developing a LAN-based database application. It involves a central "server" app to house the database, along with many "client" applications that access it.
The "server" will be a simple C#-based HTTP server that responds to GET and POST requests. However, since it is designed to be able to run from any laptop on the network, I am wondering how to establish the connection between clients and the server without knowing the IP address.
I suppose I could ping every IP address from 192.168.0.0 to 192.168.0.255, and then test those that responded to see if any are my server. But I would only do that if there is no better way. Any suggestions?
Many of these types of discovery services run by putting out some kind of beacon on either the subnet broadcast address (for 192.168.0.0/24 it would be 192.168.0.255) or by putting out a beacon on a multicast address.
Multicast is particularly interesting because in a properly configured network, it allows hosts to find the service even across subnets. Routers and switches won't generally forward broadcast packets across subnet boundaries, but multicast packets will.
The beacon would have information in it such as the port the service is running on, what type of service it is, whatever is needed to start using the service.
To head you in the right direction, what you should do is have the database server running on a specified port. Then send out a broadcast to that port from the client (the system needing to connect to the database). When the database server receives this, it will be able to respond to the sender, allowing a handshake to occur.
Of course, you will need to validate the database server's authenticity (to make it secure, unless you aren't worried about that). This can be as simple as having the client display 4 numbers which then need to be typed into the database, so that the database can send the 4 numbers back to the client proving it is the right computer (how the iTunes remote works), or you can use certificates (but that is too complex a topic for me to cover correctly).
After that the two computers will know each others IPs, and you're set!
Related
When I send data using socket in C# on LAN, everything works fine, but how do I send my data over the internet. How to send while the sever I create uses the ip from my compute (private ip)
Can someone suggest on how can I achieve this, basically I should be able to send data anywhere over the internet, not just on LAN.
These days most computers have a router with a firewall between them. Routers, via secreuity design, stop direct access to the computers behind them and their local network.
Yes you will either have to
configure the router to map through a specific port to one of your computers.
Or, the more common way to do this is using a central hub, ie a Web service as an intermediary. This way no firewall are needed as both computers are only connecting one way (out). You could use a wcf service or Web api or many technologies to achieve this and usually you'd use a database to store you game state which makes it persistent
Many questions relating to port 80 being used have answers saying that there are many programs that use it as their default port. This post mentions some: Skype, IIS, Apache...
Since only one application can listen on any one port at a time - How can that be? And if the answer is that that's only their default port - how will an application know it has to send information to a different port? For example - if iis will listen on port 81 because Skype is listening on 80 - how will anyone requesting a web page know to send the request to theip:81 as opposed to theip:80?
My goal is to have a robust way of setting up a connection between programs, when any hard coded port might fail due to some application already listening on it. The port will only need to be used once in order to communicate what dynamic port will be used for the rest of the session. This is a problem for both network connections and for connecting several applications on the same computer.
Registering with IANA is not always possible, and won't even necessarily solve the problem - someone might still be listening on a registered port. And obviously the solution of "hope for no collisions" - just doesn't cut it.
(I do understand that a connection has two sockets (and a protocol) and therefore one socket can have multiple connections. My question is about listening on a socket in order to establish the connection.)
What I would expect, is there to exist some service on the OS (Windows) that I could register my application with, and receive all incoming traffic with some signature - even if it's simply some magic string. Or perhaps some port where multiple applications can listen concurrently - and all would get every incoming message. But I haven't found anything like that so far.
How can that be? Simply...it's not. Only one application will listen on each port. – Adriano Repetti
Right. When Skype listens on those ports before I start my web-server, the server fails. It took me a while to find out why.
Only one app can listen on a socket in a sane way. The OS allows multiple apps to listen on the same port if you specify special options but that's insane. Accepted connections are then dispatched to different applications in an unspecified (i.e. random) way.
IIS can run multiple web-apps on the same port because it opens the port once in kernel mode and dispatches connections to its worker processes.
I do not believe it is ever possible for multiple sockets to listen on the same (TCP) port. If you try to bind a socket to a port that is already open, you will get an error.
I believe Skype gets around the problem you describe by using their own servers as a rendezvous point. The simple explanation being:
Alice starts her client, connects to the central server, and informs it of what port she is listening on.
Bob starts his client and likewise informs the central server.
Now, Alice wants to connect to Bob, but doesn't know which port to send packets to.
Alice will then query the central server for Bob's port number.
With this information, a direct connection is then established with Bob using that port.
The logic can of course extend to learning the other party's IP address as well as even obtaining public keys.
Note that there's actually a bit more involved with most modern peer-to-peer applications, Skype being no exception. The problem being that most computers are now behind at least one NAT router. Getting two devices each behind their own router to connect to each other is known as NAT traversal - the most common technique having a central coordinating server instruct both clients to simultaneously connect to each other. For more information on this, I recommend Steve Gibson's Security Now!, episode #42
on the port forwarding setup page i just put a comma and add an other port to open. it wont allow you to set up an additional rule with listen port 80 but it will allow you to trigger multiple ports with that one listen port
For TCP, you can only have one application listening on a single port
at one time. Now if you had 2 network cards or created a virtual
interface, you could have one application listen on the first IP and
the second one on the second IP using the same port number.
For UDP (Multicasts), multiple applications can subscribe to the same
port.
one application listening on a single port that's the reason why ports exist. To allow multiple applications to share the network without conflicts.
But there are ways to do what you requested:
You could write a master process, which possesses the port and notifies slave processes using some separation logic.
On Linux and BSD you can set up remapping rules that redirect packets from the visible port to different ones(such as listener app), again by using some separation logic(e.g. redirect according to network origin etc.).
Note: For TCP, you multiple applications can listen on the same socket by using SO_REUSEADDR option before binding but what this does is redirect the incoming connection to only one of the listeners.
Please actually read my post before placing it on hold!!
Let me start by saying I've been searching for a solution all afternoon and so far I have seen plenty of examples for WCF but none that would do what I need.
I have developed an application in c# that will be installed on customer servers and accesses a sql server on the customer's local network. The application also has the ability to control network relays on the customer's local network and records the status of these in sql. I am trying to figure out a way to have the customer's server establish a connection to our datacenter and be able to issue commands back to the customer's server (retrieve datasets from sql, control the network relays, etc). I have found plenty of ways to have a client call classes on a server but have so far been unsuccessful in finding the reverse. One consideration was writing a web service as part of the application on the customer's server but need a way to establish this connection for customers with dynamic IP addresses and without having to publish through firewalls, etc.
Have you considered using
VPN - Virtual private network
or
Configuring a Port Forwarding redirect on the ADSL modem, and using a solution like www.noip.com ?
If I understand correctly you want to get information from the customer's database, which is behind a firewall and has no known static ip, in addition there might be several hundred customers so a dedicated VPN to the customer is not viable.
First of all: you should not contact the customer database directly. Databases are not designed for this scenario and would probably be left open to attack if exposed directly to the internet.
So you need a service on top of the database. There are two main options you can use for this service:
Polling service
The service is actually a client calling some web service on your network and asking for instructions.
Benefits: easy to implement and deploy.
Downsides: With polling there is always the cost-benefit of scalability/bandwidth use vs. speed of service. There are also some considerations in selecting the time to poll to prevent all the client polling at the same time.
The service is a tcp-server
This can be a usual web service (or RESTfull service) or some other service. The only difference is that it needs to advertise itself. For that you need to have a known directory server. When the service starts it then connects to the directory service and tells it the port it can be contacted on (the directory knows the ip from the connection). It will then need to periodically contact the directory to let it know it is still alive and so any change in IP is detected.
A client on your network would now query the directory to find the address of the client and connect directly to it to issue commands.
Benefit: Scalable and bandwidth efficient.
Downside: More difficult to implement. Requires firewall traversal solutions (UPNP or firewall exceptions).
I am currently working on a little chat utility in C#.
The problem is I can't figure out how to scan the network for a specific port on all machines. I am currently using this method
IPGlobalProperties network = IPGlobalProperties.GetIPGlobalProperties();
IEnumerable<IPEndPoint> connections = network.GetActiveTcpListeners()
.Where(x => x.Port == ConstParams.iPort);
where ConstParams.iPort is the port I want to scan (6910 here).
The problem is that the returned values are only local ports and the "0.0.0.0" ip address...
How can I scan for all open ports (6910) on the current network?
Rather than using port scanning, I suggest you to implement a simple discovery mechanism based on multicast/broadcast communication.
During the startup the application should broadcast/multicast its IP/Port information. All running instances should respond to this message with their IP/Port information. This kind of a discovery mechanism is easy to implement, and it is both faster in runtime and more dynamic than the port scanning approach.
You should consider multicast, but rather than rolling your own, rely on an existing standard with library support, like mDNS:
http://en.wikipedia.org/wiki/Multicast_DNS
Or, since you said C#, using one of its native solutions:
http://msdn.microsoft.com/en-us/library/system.net.peertopeer.aspx
Scanning ports is a poor choice, you will most likely trigger firewalls on machines in the network to display your machine as an attacker. Any Intrusion detection systems on the networks could potentially be triggered as well. It's a lot of overhead for what you need.
I would recommend doing a broadcast using UDP or a multicast to discover other clients
http://www.codeproject.com/Articles/1705/IP-Multicasting-in-C
Another option would be to have a centralized server, either on a web server (php script, asp.net page, etc) or a web service (REST) which the chat client would connect to on start up, POSTing it's listening IP/Port, and then in turn would receive a list of all recently announced IP/Ports of the other clients on the network. You'd probably want some keep alive here, IE: the client would POST to the page every 5 minutes, if an IP does not POST for 10 minutes, it would be removed from the list.
To get the public IP of the machine, you could check out this page:
http://www.whatismyip.com/faq/automation.asp
You'd just need to send a web request to it to retrieve the IP. If you want to get the non 0.0.0.0/127.0.0.1 IP of the local interface, you can check out these posts:
Get local IP address
How do I get the Local Network IP address of a computer programmatically? (C#)
GetIPGlobalProperties only returns info about your local machine (see http://msdn.microsoft.com/en-us/library/system.net.networkinformation.ipglobalproperties.getipglobalproperties.aspx ).
To find out which other machines on the network have that port open, you'd have to iterate through the a range of IPs, attempting to connect on that port. There is no central repository to query on this.
This article describes an approach: http://www.dijksterhuis.org/building-a-simple-portscanner-in-c/
For practical purposes, what SqlDataSourceEnumerator does is find all instances of SQL server running on the various PCs on a LAN.
Is there an equivalent for finding running instances of an arbitrary application?
Edit: OK, so this only works because these apps have a pre-defined method of cooperation. Is there a straightforward way of determining if a given file (the exe, say) exists on some machine on the LAN even if the app itself itself is not running at the time? Understood that permissions must be taken into account.
What SQL enumeration does it broadcasts an UDP packet (port 1434) on the entire lan segment (subnet mask). The SQL Browser Agent service running on various hosts listens for this packet and responds with the list of local instances. So for the enumeration to happens, a number of ducks are already aligned for you:
there is a well know protocol for SQL isntance discovery, the UDP 1434 broadcast and response
there is a service listening for this broadcast, installed by SQL Server setup
there is a client library to implement the broadcast request formatting and response parsing which you leverage
For an arbitrary application to behave the same, the said application would have to implement these missing parts. Discovering arbitrary processes running on arbitrary hosts in a subnet segment is basically impossible for all practical means.
The difference is that SqlDataSourceEnumerator finds all instances "that it can see" on a LAN. If the server process is configured not to respond to that request, then it won't be seen.
Along that same line, you can scan for any application that has some way of making its presence known remotely. At its simplest, the application would be listening for and responding to connections. The application could, for example, bind to a TCP port and listen for any request and send back a response saying that it's alive and running, and hosts on a network can be scanned for those replies.
As for "an arbitrary application" however, most applications don't have such a mechanism for network discovery. If you control the arbitrary application then you can build that functionality into it. But if you do not then you'll need some way to look for that application on any given host, which means it'll need some kind of network interaction.
No, there isn't.
The reason that works for SQL server is that SQL server has a listener that listens on the network for "discovery" requests. An app can then send out a broadcast message on the network and listen for responses to that request to discover SQL server instances.
I suppose you could write a program that would do this generically though - It could listen for discovery requests, use some windows API functions to enumerate the processes running on that computer, and respond if the requested program is running.