Code archives/Networking/LAN Network Searching
This code has been declared by its author to be Public Domain code.
Download source code
| All around I see people who have written great examples of networked programs. However they all have a weakness. In order for the client to connect to the server, the program needs to know the server's IP address. Basically, nobody has written a way to enumerate servers running on a LAN network and find out their IP addresses.|
[Several months ago...]
After trawling the web, I concluded that nobody has written some good code for finding the IP addresses of hosts over a LAN network. I was creating a simple Networked Chat program at the time. I basically had no choice but to use the horrible, confusing DirectPlay dialog in order to find Networked Chat rooms running over the network. I decided to write my own code to bypass it.
How to use the functions:
For Server (When 'Displaying' Server on Network):
- Call SetupServer() before anything else!!
- Once every loop or decided amount of time call MakeVisible(RoomName$) where roomname is the name of the room to send to any clients trying to find your server.
- Call CloseServer() when finished.
For Client (When Searching for Server):
- Call InitialiseQuerying() first!!
- Every second or so call QueryGames()
- Around 5 times a second (or some reasonable rate) call ListenForGames()
- After calling ListenForGames(), new types are created that hold information about the servers currently visible over the network (see below for type def.)
- When done, call EndQuerying()
Type definition for Networked Game searching:
NetGames\ServerIP is the integer IP address of the server.
NetGames\Name$ is the RoomName$ parameter passed into the function called by the server.
You can modify the code used to ensure that both programs are the same (e.g. in the code at the moment one computer sends "Join Networked Chat" over the network with the other listening for this. You can change this string to whatever you want. If it is only used in one program, other programs using the same functions will not show up on the network.)
Edit: I've made the string used for enumeration (default "Join Networked Game") into a constant defined at the start of the code so that it is easier to modify. So that a program of one type doesn't find a program of a different type with this code (in the unlikely event that both are running at once), modify this to something specific to your program.
Const SearchingMessage$ = "Join Networked Game" Global ServerStream Global GameInfoStream Global SearchStream Global ListenStream Type NetGames Field ServerIP Field Name$ End Type Function InitialiseQuerying() ListenStream = CreateUDPStream(41110) End Function Function EndQuerying() CloseUDPStream ListenStream End Function Function QueryGames() SearchStream = CreateUDPStream() For MyIPs = 1 To CountHostIPs("") MyIP = HostIP(MyIPs) IP = MyIP BinIP$ = Bin$(MyIP) For X = 1 To Len(BinIP$) IP = IntIP(Left$(BinIP$, Len(BinIP$) - X) + String$("1",X)) WriteLine SearchStream, SearchingMessage$ SendUDPMsg SearchStream, IP, 41112 Next Next CloseUDPStream SearchStream End Function Function ListenForGames() WaitTime = MilliSecs() Repeat ReceiveIP = RecvUDPMsg(ListenStream) If ReceiveIP Then AlreadyFound = False For NetGame.NetGames = Each NetGames If NetGame\ServerIP = ReceiveIP Then AlreadyFound = True : Exit Next If Not AlreadyFound Then NetGame.NetGames = New NetGames NetGame\ServerIP = ReceiveIP NetGame\Name$ = ReadLine$(ListenStream) If DottedIP$(NetGame\ServerIP) = "127.0.0.1" Then Delete NetGame EndIf EndIf Until MilliSecs() - WaitTime > 1000 Or ReceiveIP = 0 End Function Function SetupServer() ServerStream = CreateUDPStream(41112) GameInfoStream = CreateUDPStream(41113) End Function Function CloseServer() CloseUDPStream ServerStream CloseUDPStream GameInfoStream End Function Function MakeVisible(GameName$) If Not ServerStream Then ServerStream = CreateUDPStream(41112) EndIf If Not GameInfoStream Then GameInfoStream = CreateUDPStream(41113) EndIf If ServerStream And GameInfoStream Then ReceiveIP = RecvUDPMsg(ServerStream) If ReceiveIP Then If ReadLine$(ServerStream) = SearchingMessage$ Then WriteLine GameInfoStream, GameName$ SendUDPMsg GameInfoStream, ReceiveIP, 41110 EndIf EndIf EndIf End Function Function IntIP(BinString$) ActualIP = 0 Multiplier = 1 For X = Len(BinString$) To 1 Step -1 ActualIP = ActualIP + (Int(Mid$(BinString$,X,1)) * Multiplier) Multiplier = Multiplier * 2 Next Return ActualIP End Function
| is this|
the same thing???
| I didn't find this code before. However it is different in two ways:|
First of all - this is the reason why I like my code - it will only work on networks where the subnet mask is 255.255.255.0
Although most networks use this as there subnet mask, there are some that dont - mainly larger ones - and my code will work for any network without needing to find out the subnet mask. Basically, it does this by trying out every subnet mask possible. Although semar's code will work almost all of the time, if the subnet mask is not 255.255.255.0 it will not work.
Secondly, my code is more 'lightweight'. This is my better sounding way of saying that semar's code is more comprehensive. However, mine is designed for direct calls of functions for use in a game whereas semar's is a seperate, self-running program which needs to be adapted before use.
Also, one possible problem with semar's code is that if the UDP stream port on one computer doesn't match the broadcasting point specified by the other then the recognition will not work. However, my code gets around this by failing if it doesn't work :P.
My code will work on ALL networks, which is why I favour it above anything I've seen on the web (for BB at least). Although it achieves this by trying out 32 different possible broadcast IP addresses, it works and still runs far faster than required. When using my code however, make sure that you follow my guidelines as to the amount of calls of different functions per second as if you call them too frequently, you will not achieve anything except severe lag.
| Forgive my noobish questions, but what's the relevance of the relationship between (I'm assuming they are) port numbers:|
say, 41110 to 4112?
If I were to modify this to allow for the port to be entered as a parameter, should I maintain the same differences, or does it not matter, so long as I at least make sure that i I substitute, say, 4112 with 4000, then EVERY occurrence of 4112 MUST be 4000?
Sorry too if this doesnt make sense...
However it is different in two ways
And it's not (Super)Strict... ack. :-/
| As far as I know, one could consider ports as an index for connections. If one program on one computer is listening on port 25000, Windows will know to send any messages sent to the port to the program.|
If a program on the server is listening on port 25000 and the program on the client computer is sending information to port 25000 at the server's IP address, the program running on the server will be able to read that information because it has told the OS to tell it any messages that are sent to that port.
However, if the program on the server listens on port 25000 but messages are sent to port 25001 then the OS of the server will not convey the information to the program.
Basically, ports allow the OS to send the correct messages to the correct programs. Without them, programs could be intercepting messages - by accident or on purpose - which are meant for other programs. Wouldn't it be bad if Windows Update got some of its data from a webpage you were loading in Internet Explorer?
I hope this answers your question. Sorry about my horrible, lengthy explanations!
| Yep., I pretty much get what the oports are for, but I was cocnerned about the use of (in the example posted) port 4110 in some situations and 4112 / 44113 in others.|
Of course, it would be required that the receiver should be LISTENING on the same port as the TRANSMITTER is sending on, but is it important to use
PortNumber + 2 for GameInfoStream
or PortInfo+ 3 for Server Stream etc.?
Or can the numbers used be pretty much anything (that don't conflict with other known ports of course) provided the 'sending' and 'receiving' are matched>?
I hope this is clearer than my previous attempt ;)
| Yeah they can be just about anything Malice - sorry I misunderstood your question. I just chose those ports to look nice. |
| Great! Thanks a lot, Serpent - This will come in very useful! |
Code Archives Forum