Code archives/Networking/LAN Network Searching

This code has been declared by its author to be Public Domain code.

Download source code

LAN Network Searching by Serpent2010
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:

[code]Type NetGames
Field ServerIP
Field Name$
End Type[code]

NetGames\ServerIP is the integer IP address of the server.
NetGames\Name$ is the RoomName$ parameter passed into the function called by the server.


Additional Notes:
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

Comments

Nate the Great2010
is this
http://www.blitzbasic.com/codearcs/codearcs.php?code=2592#comments
the same thing???


Serpent2010
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.


_PJ_2010
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...


Brucey2010
However it is different in two ways

And it's not (Super)Strict... ack. :-/


Serpent2010
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!


_PJ_2010
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 ;)


Serpent2010
Yeah they can be just about anything Malice - sorry I misunderstood your question. I just chose those ports to look nice.


_PJ_2010
Great! Thanks a lot, Serpent - This will come in very useful!


Code Archives Forum