So the simple thing is that your client will send a message saying:
The server will respond with:
Or something like that. Feel free to use different messages. The xxx is the TCP port that the server is listening on which is different from the port that it listens for broadcast clients on.
Now, the hard part. First, you have to use UDP instead of TCP to do this, because you don't know where the servers are, only that they should be listening on a certain port. If you knew where they were, you wouldn't be trying to find them. TCP requires that you open a connection to send a message and you can't open a connection until you find the server. However, using UDP is easy. As described in the lab, you use SOCK_DGRAM to create the socket and then use sendto and recvfrom to send and receive. The first thing you should do is make sure that is working for you. UDP has other uses as well, but it is a bare-bones message-oriented protocol (not byte-oriented like TCP) and does no error checking.
OK, so maybe the hard part is broadcasting but you have already tried that out and know that it works. What you have to do is enable broadcasting on the socket, and then use the broadcast address when you send instead of the address of a specific host. One thing you should do is create a function for opening broadcast sockets:
struct sockaddr_in BroadcastSocket (int port_number, int b_address)
You might also want to consider a function that will broadcast a message and return a list of the hosts that respond, or maybe just the host that is chosen as the favored server.
int FindServers /* Returns an error code */
(b_address, port, message, timeout, host_list)
where b_address is the broadcast address to use, port is the port the servers should listen on, message is the message to send, timeout is the maximum time to wait and host_list is a list of hosts that respond. You could also use a service name here, but for your usage, that probably isn't very practical since you won't be broadcasting to any standard services.
One thing that should be obvious is that once a client broadcasts, it can't wait forever for servers to respond. This can be fixed with a timer which will generate a signal that allows you to end the process. That's the reason for the timeout value. In this case, ignore the timeout and have your client die when it hears from some number of servers, or you can kill it manually.
Finally, why does the server return a port number? In some cases, the server listens on one port for clients that are searching for servers, but then has a TCP port that it uses to handle client requests once they have identified a server. So the server has two sockets, one for clients to use to find the server, and the other to respond to requests for information. The question is "how does the server know which recv to execute - on the UDP or the TCP socket? This question will be taken up in the next program.
You should turn in a listing showing the messages exchanged between the clients and servers and the client should print a list of servers that responded. You should be running at least three servers to see if everything is working correctly. Note that your server doesn't have to do anything. The problem of figuring out when to listen for clients and when to respond to requests (for random numbers for example) is somewhat complicated.