|
Implementing UDP: Let’s get quizzical
The C# Column - Yashawant Kanetkar
Unlike
the TCP protocol, the UDP protocol is connectionless. Here there
is no setting up of connections needed, instead the data is sent
in packets. The .NET framework provides the UdpClient class for
connectionless transmission. Like TcpListener and TcpClient, UdpClient
also wraps the Socket class. The UdpClients Send( ) and Receive(
) methods invoke the SendTo( ) and ReceiveFrom( ) methods of the
Socket( ) class respectively.
To demonstrate the usage of the connectionless
service we have created two applicationsQuizmaster and Player.
The idea is basically to conduct an online quiz, where the quizmaster
would ask questions to two players on two different machines. The
player who responds with a correct answer first wins. Create a Windows
application named Quizmaster and design the form as shown below.
The
quizmaster asks a question by typing it in the Post a Question
text box named que. He is also supposed to provide an answer to
crosscheck the answers supplied by the players in the Correct
Answer text box named ans. Then he should specify the names
of the computers on which the Player application is
executing. We have allowed two players to play at one time. These
names should be supplied in the Computer 1 and Computer
2 text boxes named pcname1 and pcname2. On receiving the answers,
they would get displayed in the messages list box.
Let us first take a look at the Quizmaster
application. After typing the question-answer along with the computer
names, the quizmaster clicks the Send button. This invokes
the following handler:
private void sendbut_Click(object sender, System.EventArgs e)
{
string question;
byte[] senddata;
question = que.Text + @ + Dns.GetHostName();
answer = ans.Text ;
senddata = Encoding.ASCII.GetBytes(question);
try
{
client.Send(senddata, senddata.Length, pcname1.Text, 201);
}
catch
{
MessageBox.Show (Cannot send to + pcname1.Text);
}
try
{
client.Send(senddata, senddata.Length, pcname2.Text, 201);
}
catch
{
MessageBox.Show(Cannot send to + pcname2.Text);
}
}
In this handler we have first collected the question
as well as the answer in the strings question and answer respectively.
We have made answer a data member of the class because we will need
it in another method to crosscheck the answers provided by the players.
Next we have appended the question with the computer name separating
them with an @. The GetHostName( ) method of the Dns
class returns a string containing the host name of the machine.
Then we have encoded the data in an array of bytes called senddata.
The data is sent using the Send( ) method of the UdpClient class.
For this we have added a data member called client of the type UdpClient
to the Form1 class. The Send( ) method takes four parameters-an
array of bytes to be sent, the length of the array of bytes, the
computer name where we wish to send the data and the port number
to which the data would be sent. We chose the port number to be
201 (you can choose any other). Now the Quizmaster application should
be ready to accept answers from the players. The player who first
sends the correct answer wins. This calls for waiting for a packet
to arrive at the specified port. For this we have started a different
thread from the constructor of the Form1 class. This thread would
start waiting for a packet as soon as the application starts. The
following code written inside the constructor launches a separate
thread.
Thread svthread = new Thread(new ThreadStart(startserver));
svthread.IsBackground = true;
svthread.Start();
The startserver() method is given below
public void startserver()
{
// 1-Create an IPEndPoint to receive messages
IPEndPoint recvpt = new IPEndPoint ( IPAddress.Any, 0 ) ;
byte[] data;
string str, from;
int index;
while(true)
{
// 2-Receive data
data = server.Receive(ref recvpt);
str = Encoding.ASCII.GetString (data);
index = str.LastIndexOf(@);
from = str.Substring(index + 1);
messages.Items.Add(str);
str = str.Remove(index, str.Length - index);
// 3-Check the answer
string result;
if(str.CompareTo(answer)==0)
{
result = Correct! your rank is + rank + @ + HostName();
rank += 1;
}
else
result = Your answer is wrong! + @ + Dns.GetHostName();
if(rank == 3)
rank = 1;
// 4-Send the result
byte[] senddata;
senddata=Encoding.ASCII.GetBytes(result);
try
{
client.Send ( senddata, senddata.Length, from, 201 ) ;
}
catch
{
MessageBox.Show ( Cannot send result ) ;
}
}
}
Here, we have firstly created an object
of the IPEndPoint class. We need it to receive messages from the
client. To the constructor of the IPEndPoint class we have passed
a default IPAddress using the Any Filed of the IPAddress class.
The Any field specifies that the server should listen for client
activity on all network interfaces. We have also passed a port number
0 to indicate that it should pick any available port.
The player sends his answer to the quizmaster
in packets. To receive the packet we have called the Receive( )
method of the UdpClient class. We have added server as a data member
of the Form1 class as shown below.
UdpClient server=new UdpClient(200);
The Receive( ) method returns an array
of bytes containing the answer, which we have after converting into
string displayed in the list box. The player would send his answer
along with the computer name separated with @. To check
whether the answer is correct or not we must first separate the
answer and computer name.
The correctness of answer is checked using
the CompareTo( ) method of the String class.
If the answer is correct we have constructed
a string result containing a rank. We have added rank as an integer
data member of the Form1 class and initialised it to 1. If the answer
does not match then we have stored a string saying that the answer
is wrong. If the answer is right, the rank is also incremented by
1 so that whoever replies next will be ranked 2nd. If the rank exceeds
2 we have reset it to 1 because there are only two players.
Next we have sent the result string using
the Send( ) method of the UdpClient class.
Separating the string, checking the answer
and sending the result should be carried out every time a packet
is received. So, we have done them in a while loop.
Now let us take a look at the Player
application. The Player is a very simple application.
Its form contains a label named question. We have changed the font
size of the text that would get displayed in the label to 11 and
changed its style to bold. All the player needs to do is type in
the answer and click the Send button.
We chose 201 as the port number where the
player would receive packets and 200 as the port number for sending
the packets. In the player application too we have started a new
thread in the constructor of the Form1 class that waits for a packet
to arrive, as shown below.
Thread svthread=new Thread(new ThreadStart(startplayer));
svthread.IsBackground=true;
svthread.Start();
The startplayer() method is given below
public void startplayer()
{
IPEndPoint recvpt = new IPEndPoint(IPAddress.Any, 201);
byte[] data;
string str;
int index;
while (true)
{
data=server.Receive(ref recvpt);
str=Encoding.ASCII.GetString(data);
index=str.LastIndexOf(@);
from=str.Substring(index+1);
str=str.Remove(index, str.Length - index);
question.Text=str ;
}
}
Here also we have created an object of
the IPEndPoint class and collected its reference in recvpt. After
receiving the question we have separated the question and the computer
name in str and from respectively. server (a reference of UdpClient
instance) and from (a reference to a string) have been added to
the Form1 class as data members. Then we have displayed the question
on the label named question.
As soon as the player receives a question
he has to type in the correct answer and click the Send
button. This would invoke the following handler.
private void sendbut_Click ( object sender, System.EventArgs
e )
{
byte[ ] senddata ;
string answer ;
answer = ans.Text + @ + Dns.GetHostName(
) ;
senddata = Encoding.ASCII.GetBytes ( answer ) ;
try
{
client.Send ( senddata, senddata.Length,
from, 200 ) ;
}
catch
{
MessageBox.Show ( Error sending data
) ;
}
}
Here we have collected the answer provided
by the player in a string called answer and appended it with an
@ followed by the host name of the player machine. After
encoding it in a byte array we have again used the Send( ) method
of the UdpClient class to send the data. client has been added as
the data member of the Form1 class.
Now that both the applications are ready,
we can enjoy quizzing!
 |
Yashavant Kanetkar, one of the first
Express Computer columnists, is an established software expert,
speaker and author with several best-sellers to his credit,
including titles like “Let Us C” and the “Fundas” series. Contact
him at kanet@nagpur.dot.net.in |
|