By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,046 Members | 2,058 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,046 IT Pros & Developers. It's quick & easy.

Finding server with broadcast

P: n/a
I need some code that gets the address from a server. I read somewhere
that you could do this by starting some broadcast server using UDP. The
client should send an broadcast message, and when the server answering
the client gets the address. But how do I implement this?

I did this simple quick-hack:

Server:
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
server.Bind( new IPEndPoint( IPAddress.Any, 48000 ) );

while(true)
{
byte[] buffer = new byte[1000];
server.Receive(buffer);

Console.Write("Server got: " + buffer[0]);
//Next line crash cause some permission error.
server.SendTo( new byte[] {2},
new IPEndPoint( IPAddress.Broadcast, 48000 ) );
}

Client:
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
client.Connect(new IPEndPoint( IPAddress.Broadcast, 48000 ));

Console.Write("Client send: 1");
client.Send( new byte[] {1} );

byte[] buffer = new byte[1000];
client.Receive(buffer);
Console.Write("Client got: " + buffer[0]);

client.Close();

To my surprise the code almost worked :-). The server receive the
message from the client, but it fails when sending data. And even if it
did it doesn't help the client cause will not know who send the
message.

I'm thankful for any ideas. What I'm looking for is a way to find the
address of a server. It doesn't need to be perfect, it will just give
the users a hint which address to use for the real application.

Nov 17 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
pe*****@home.se wrote:
I did this simple quick-hack:
see below
Server:
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
server.Bind( new IPEndPoint( IPAddress.Any, 48000 ) );

while(true)
{
byte[] buffer = new byte[1000];
server.Receive(buffer);
use ReceiveFrom here. this will give you an IPEndPoint with the address of
the sending client.
Console.Write("Server got: " + buffer[0]);
//Next line crash cause some permission error.
server.SendTo( new byte[] {2},
new IPEndPoint( IPAddress.Broadcast, 48000 ) );
don't send the response back by broadcast. you can send it directly to the
client using the above IPEndPoint.
}

Client:
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
client.Connect(new IPEndPoint( IPAddress.Broadcast, 48000 ));
not sure if Connect should be used for a connectionless (UDP) socket. I
think it should work, but I always prefer the SendTo and ReceiveFrom
functions for UDP. also you might want to use port 0 for the client. this
way some free source port will be allocated automatically. in your case, if
client and server are running on the same system, they will both access
port 48000, which might fail.

Console.Write("Client send: 1");
client.Send( new byte[] {1} );

byte[] buffer = new byte[1000];
client.Receive(buffer);
Console.Write("Client got: " + buffer[0]);

client.Close();


hth,
Max

Nov 17 '05 #2

P: n/a
Markus Stoeger wrote:
not sure if Connect should be used for a connectionless (UDP) socket. I
think it should work, but I always prefer the SendTo and ReceiveFrom
functions for UDP. also you might want to use port 0 for the client. this
way some free source port will be allocated automatically. in your case, if
client and server are running on the same system, they will both access
port 48000, which might fail.


Thank you, I followed your instructions and now the code works. I also
tried to use port 0 on the client, but then the server didn't received
any message (btw, should I use bind on the server?).

This is the code that have so far. Works pretty well:

Server:
//Start server
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
Console.Write("Running server..." + Environment.NewLine);
server.Bind( new IPEndPoint( IPAddress.Any, 48000 ) );

while(true)
{
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint tempRemoteEP = (EndPoint)sender;
byte[] buffer = new byte[1000];
//Recive message from anyone.
server.ReceiveFrom(buffer, ref tempRemoteEP);

Console.Write("Server got '" + buffer[0] +
"' from " + tempRemoteEP.ToString() +
Environment.NewLine);

Console.Write("Sending '2' to " + tempRemoteEP.ToString() +
Environment.NewLine);

//Replay to client
server.SendTo( new byte[] {2},
tempRemoteEP );
}

Client:
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp);

IPEndPoint AllEndPoint = new IPEndPoint( IPAddress.Broadcast, 48000 );

//Allow sending broadcast messages
client.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.Broadcast, 1);

//Send message to everyone
client.SendTo( new byte[] {1}, AllEndPoint );
Console.Write("Client send '1' to " + AllEndPoint.ToString() +
Environment.NewLine);

IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint tempRemoteEP = (EndPoint)sender;
byte[] buffer = new byte[1000];

string serverIp;

try
{
//Recieve from server. Don't wait more than 3000 milliseconds.
client.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout, 3000);
client.ReceiveFrom(buffer, ref tempRemoteEP);
Console.Write("Client got '" + buffer[0] + "' from " +
tempRemoteEP.ToString()+ Environment.NewLine);

//Get server IP (ugly)
serverIp = tempRemoteEP.ToString().Split(":".ToCharArray(), 2)[0];
}
catch
{
//Timout. No server answered.
serverIp = "?";
}

Console.Write("ServerIp: " + serverIp + Environment.NewLine);

Nov 17 '05 #3

P: n/a
pe*****@home.se wrote:
Thank you, I followed your instructions and now the code works. I also
tried to use port 0 on the client, but then the server didn't received
any message
I think you have to bind the port on the client side also. Then it should
work with port 0 (haven't tried it right now though).
(btw, should I use bind on the server?).


Yes you have to, otherwise it doesn't know where to listen for the
broadcast.

Have you tested this code on a system with multiple network interfaces yet?
I did something like that a while ago and as far as I remember such a
broadcast is only sent out on one interface, not on all. You have to lookup
the network interface addresses and send a broadcast on each of them. You
can use the Dns functions to resolve your computers hostname, that should
give you all available local network interface addresses.

Max

Nov 17 '05 #4

P: n/a
Markus Stoeger wrote:
I think you have to bind the port on the client side also. Then it should
work with port 0 (haven't tried it right now though).
I added a bind call in the client code. It failed, as expected, cause
two programs where listening on port 48000 at the same time. I then
changed to port 0. No program crashed, but the client didn't find the
server.
Have you tested this code on a system with multiple network interfaces yet?
I did something like that a while ago and as far as I remember such a
broadcast is only sent out on one interface, not on all. You have to lookup
the network interface addresses and send a broadcast on each of them. You
can use the Dns functions to resolve your computers hostname, that should
give you all available local network interface addresses.


Good point. I could get all addresses by calling:
string hostname = System.Net.Dns.GetHostName();
IPHostEntry allLocalNetworkAddresses = Dns.Resolve(hostname);

But how do I use that information? Creating EndPoint like this:

foreach(IPAddress ip in allLocalNetworkAddresses.AddressList)
{
IPEndPoint AllEndPoint = new IPEndPoint( ip, Port );

will only make the client call it self to find the server. In the
original code I do this:

IPEndPoint AllEndPoint = new IPEndPoint( IPAddress.Broadcast, Port );

How do I get the broadcast address for each network?

PEK

Nov 17 '05 #5

P: n/a
pe*****@home.se wrote:
Markus Stoeger wrote:
Good point. I could get all addresses by calling:
string hostname = System.Net.Dns.GetHostName();
IPHostEntry allLocalNetworkAddresses = Dns.Resolve(hostname);

But how do I use that information?


I don't have the source code here right now, but I think you have to create
one socket for each ip address that you get from Dns.Resolve. Then bind the
sockets to these addresses (instead of binding them to IPAddress.Any).
When you call SendTo, use IPAddress.Broadcast as destination.
This way it will be sent out as broadcast on exactly the interface you have
bound the socket to. You'll also have to call ReceiveFrom on each socket.
I think you have to bind the port on the client side also. Then it should
work with port 0 (haven't tried it right now though).


I added a bind call in the client code. It failed, as expected, cause
two programs where listening on port 48000 at the same time. I then
changed to port 0. No program crashed, but the client didn't find the
server.


It should work.. maybe there is another problem? Take a look at the Bind
description on MSDN: http://tinyurl.com/cqoce
It says "If you do not care which local port is used, you can create an
IPEndPoint using 0 for the port number. In this case, the service provider
will assign an available port number between 1024 and 5000."

hth,
Max

Nov 17 '05 #6

P: n/a
Markus Stoeger wrote:
I don't have the source code here right now, but I think you have to create
one socket for each ip address that you get from Dns.Resolve. Then bind the
sockets to these addresses (instead of binding them to IPAddress.Any).
When you call SendTo, use IPAddress.Broadcast as destination.
This way it will be sent out as broadcast on exactly the interface you have
bound the socket to. You'll also have to call ReceiveFrom on each socket.
Yes, of course. I should have figured out that myself.

It should work.. maybe there is another problem? Take a look at the Bind
description on MSDN: http://tinyurl.com/cqoce
It says "If you do not care which local port is used, you can create an
IPEndPoint using 0 for the port number. In this case, the service provider
will assign an available port number between 1024 and 5000."


My mathematical knowledge tells me that 48000 > 5000 :-). Changing to
port 4800 solved the final problem. To those that are interested, this
is the code:

Server:
//Start server
const int Port = 4800;
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
Console.Write("Running server..." + Environment.NewLine);
server.Bind( new IPEndPoint( IPAddress.Any, Port ) );

while(true)
{
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint tempRemoteEP = (EndPoint)sender;
byte[] buffer = new byte[1000];
//Recive message from anyone.
//Server could crash here if there is another server
//on the network listening at the same port.
server.ReceiveFrom(buffer, ref tempRemoteEP);

Console.Write("Server got '" + buffer[0] +
"' from " + tempRemoteEP.ToString() + Environment.NewLine);

Console.Write("Sending '2' to " + tempRemoteEP.ToString() +
Environment.NewLine);

//Replay to client
server.SendTo( new byte[] {2},
tempRemoteEP );
}

Client:
const int Port = 4800;
string serverIp = "?";

//Get all addresses
string hostname = System.Net.Dns.GetHostName();
IPHostEntry allLocalNetworkAddresses = Dns.Resolve(hostname);

//Walk thru all network interfaces.
foreach(IPAddress ip in allLocalNetworkAddresses.AddressList)
{
Socket client = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);

//Bind on port 0. The OS will give some port between 1025 and 5000.
client.Bind( new IPEndPoint( ip, 0 ) );

//Create endpoint, broadcast.
IPEndPoint AllEndPoint = new IPEndPoint( IPAddress.Broadcast, Port );

//Allow sending broadcast messages
client.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.Broadcast, 1);

//Send message to everyone on this network
client.SendTo( new byte[] {1}, AllEndPoint );
Console.Write("Client send '1' to " + AllEndPoint.ToString() +
Environment.NewLine);

try
{
//Create object for the server.
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint tempRemoteEP = (EndPoint)sender;
byte[] buffer = new byte[1000];

//Recieve from server. Don't wait more than 3000 milliseconds.
client.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout, 3000);

//Recive message, save wherefrom in tempRemoteIp
client.ReceiveFrom(buffer, ref tempRemoteEP);
Console.Write("Client got '" + buffer[0] + "' from " +
tempRemoteEP.ToString()+ Environment.NewLine);

//Get server IP (ugly)
serverIp = tempRemoteEP.ToString().Split(":".ToCharArray(), 2)[0];

//Don't try any more networkss
break;
}
catch
{
//Timout. No server answered. Try next network.
}
}

Console.Write("ServerIp: " + serverIp + Environment.NewLine);
Thanks for your excellent support Max!

PEK

Nov 17 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.