Hi, please HELP me find a working solution for discovering all PCs on the local subnet, those serve http (on a specific port, let’s say: 88 ! )
Sending http(s) requests one by one and wait 2-3000ms is not a good solution.
(Especially on 10.x.x.x )
So I guess:
- sending a Broadcast, (to 255.255.255.255)
- and wait for ALL answers in a separate thread
- while putting the results in a thread-safe list (I know how to do that)
would be the good approach for this.
But I haven’t found a working solution (full code) for this yet.
So how do I create a TCPlistener or something similar under Unity to catch all http answers at the same time within 3000ms?
THANK YOU very much!
PS: I’ve also red here while looking at the questions similar to this, that Android-networking can be tricky? (Not implemented?)
You can’t use broadcasts with the TCP protocol. TCP is a connection based protocol. It doesn’t support broadcast or multicast as a TCP connection is always unicast. A TCP listener does only react to connection request packets which can’t be multi / broad cast. So in order to check all possible hosts you have to test them one-by-one.
Next thing is that you can’t really “test” if a TCP connection uses HTTP or if it uses some other protocol. You only know that it’s TCP after you send a valid HTTP request and you got a valid HTTP response (note that “valid” doesn’t necessarily mean a positive response. A 404 is also a valid response).
Finally all ports below 1025 are standardised well-known-ports. The main point is that a certain port number indicates a certain service. If an URL uses the http://
scheme it directly translates to port 80 while https://
translates to port 443. Of course it’s possible for any protocol type to use any arbitrary port, but the (mis-) usage of well-known ports is not recommended. Port 88 is reserved for the kerberos authentication system.
The IP protocol supports many different encapsulated protocols where UDP and TCP are just two of them. Only UDP and TCP are using the same kind of “port number”. Another very common protocol is the ICMP (Internet Control Message Protocol) which has several features the most user-known feature is an eche-request also known as ping. Commonly a ping was used to determine if there is any host at the specified IP address. However nowadays it’s very unreliable as pings has been abused for DoS attacks and echo requests often are silently swallowed / discarded by a lot systems and even hardware.
Most lan discovery is done using a “listening” UDP socket on all machines that should be able to be discovered and to send a broadcast UDP packet from the discovering host. All those hosts should then respond back to the requester. However that requires all your hosts to actually run such a service.
If you just want to find any host that is serving an HTTP server on a specific port there’s no way around manually trying to connect to all possible addresses. Note that a private local area network doesn’t need to be a class C network. So an exhaustive search on a class B or class A network is not feasible.
We can’t really recommend one method over the other without more details about your actual case. Some networks / routers / firewalls might see a systematical scan as abusive.
Dear @Bunny83 Thank you VERY VERY much for the detailed answer. 
1.)
“You can’t use broadcasts with the TCP protocol”
I didn’t know that! Now I understand why I couldn’t find a solution for this.
2.) Sorry for the port=88 example, of course I don’t use anything under 1025.
Should have wrote for example: port=1888
3.) Yes, I know ping isn’t reliable
But is there ANY possible way to find all PC available on the subnet with that specific port open via Broadcast?
… Maybe via sockets?
- Tipically there would be max 2-5 PCs responding from the possible 254 IPs in local restaurants,
- but in my 10.1.x.x VPN segment ca 500 PCs from the possible 65K addresses
(because I need to overview all of them)
- so it would be MUCH easier to create parallel max 2-200 TCP direct connections to check, if they are REALLY responding to my HTTP request. (Not 65000 1by1.)
I wrote a simple code to create 254 Treads to test.
But it’s not working… does anyone see where’s the error in this?
public static MultiThreadValues.ThreadSafeInt _found = new MultiThreadValues.ThreadSafeInt(); // how many servers responded
public static MultiThreadValues.ThreadSafeList<string> _addresses = new MultiThreadValues.ThreadSafeList<string>(); // each IP with server, who responded
btnSearchAddress.Click += delegate {
...
var task = Task.Run(() => _FIND()); // Create 254 threads to test simultaniously
task.Wait(TimeSpan.FromMilliseconds(3100));
for (int j = 0; j < _addresses.Count; j++) {
_Pzz.AddLog2List(_addresses[j]); }
}
public static void _FIND() {
_found.Value = 0;
_addresses.Clear();
string p = _Pzz._myIPstring;
if (p == "") return;
const Char _dot = '.';
StringBuilder str192 = new StringBuilder(64);
Int16 dots = 0;
for (int c = 0; c < p.Length; c++) {
if ( p
== _dot) dots++;
str192.Append(p[c]);
if (dots == 3) break; // found 3. "." = 192.168.1.
}
string str192168 = str192.ToString();
for (int i = 1; i < 255; i++) {
var tmp_thread = new Thread(new ThreadStart(() =>
{
var host0 = str192168 + i;
string url_txt = WebCall.CreateTestURL(host0, WebCall.PRF_.Port) ;
URL myUrl = new URL (url_txt);
bool success = false;
try {
HttpURLConnection urlc = (HttpURLConnection)myUrl.OpenConnection ();
urlc.RequestMethod = "GET"; //OR huc.setRequestMethod ("HEAD");
urlc.SetRequestProperty("Connection", "close");
urlc.ConnectTimeout = 2000;
urlc.Connect();
success = (urlc.ResponseCode == HttpStatus.Ok);
//success = (urlc.ResponseMessage == "OK");
}
catch (Exception) {}
if (success) {
_found.Add1();
_addresses.Add(host0);
}
}));
}
} //void _FIND()