Request Server responseport port Client
Transcript of Request Server responseport port Client
Visual C# - Penn P. Wu, PhD. 434
Lecture #14 C# Basic Socket programming
Introduction A C# Server Socket Program running on a computer has a socket that bound to a Port Number
on the same computer and listening to the client's incoming requests. A C# Client Socket
Program has to know the IP Address (Hostname) of the computer that the C# Server Socket
Program resides and the Port Number assign for listening for client’s request. Once the
connection is established between Server and Client, they can communicate (read or write) through their own sockets.
There are two types of communication protocol uses for Socket Programming in C#. They are
TCP/IP (Transmission Control Protocol/Internet protocol) Communication and UDP/IP (User
Datagram Protocol/Internet protocol) Communication.
In order to do communication between two applications in client/server environment, we need
some type of addressing, and mechanism or protocol to do proper communication.
Communication can be done in two ways:
• Connection-oriented: In connection oriented service, we establish a proper connection
between client and server through some sort of handshaking. For this, we have a protocol
or standard called TCP. I.e., TCP provides us service to send data in connection oriented environment.
• Connectionless: In connection less service, we do data transfer without any connection
between client and server. For this, we have a protocol or standard called UDP. I.e., UDP
provides us service to send data without taking care of client activation.
A Socket is an End-Point of To and From (Bidirectional) communication link between two
programs (Server Program and Client Program) running on the same network. You need two
programs for communicating a socket application: a Server Socket Program (Server) and a
Client Socket Program (Client).
C# simplifies the network programming through its namespaces like System.Net and
System.Net.Sockets . The System.Net namespace provides a simple programming interface for
many of the protocols used on networks today. The System.Net.Sockets namespace provides a
managed implementation of the Windows Sockets (Winsock) interface for developers who need to tightly control access to the network. The System.Net.Sockets namespace provides the
TcpClient, TcpListener, and UdpClient classes encapsulate the details of creating TCP and
UDP connections. It also provides the NetworkStream class with methods for sending and
receiving data over Stream sockets in blocking mode.
In order to create client and server application, you need to add the following namespaces:
using System.Net;
using System.Net.Sockets;
TCP
connection
The TcpListener class provides simple methods that listen for and accept incoming connection
requests in blocking synchronous mode.
Creating a TcpListener object starts with creating an object of the IPAddress class which
represents the address of a computer on an IP network. The following initializes a new instance
Server port port Client
Request response
Visual C# - Penn P. Wu, PhD. 435
of the IPAddress class with the specified address. The Parse() method converts an IP address
string to an IPAddress instance. It can create an instance of IPAddress class from an IP address
expressed in dotted-quad notation for IPv4 and in colon-hexadecimal notation for IPv6.
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
If the IP address will be entered through a textbox (named textBox1), you can use:
IPAddress localAddr = IPAddress.Parse(textBox1.Text);
Where port is a TCP port on which the application will use to listen for incoming connection
attempts. In the .NET Framework, a port is a value of Int32 type. The following specifies a port
number 13000.
Int32 port = 13000;
You need to create an instance of the TcpListener class which listens for connections from
TCP network clients. The following initializes a new instance of the TcpListener class that
listens for incoming connection attempts on the specified local IP address and port number.
TcpListener server = new TcpListener(localAddr, port);
or simply
TcpListener server = new TcpListener(localAddr, 13000);
Notice that the localAddr object must be a IPAddress type. In the following, “204.1.9.114” is
considered a regular string, not a IPAddress value, so the statement simply will not work.
TcpListener server = new TcpListener("204.1.9.114", 13000);
Yet, you can create an instance using the following short-hand way.
TcpListener server = new
TcpListener(IPAddress.Parse("127.0.0.1"), 13000);
If you plan to allow connection across the network. Use the IPAddress.Any field which
indicates that the server must listen for client activity on all network interfaces.
TcpListener server = new TcpListener(IPAddress.Any, 13000);
Use the Start method to begin listening for incoming connection requests. Start will queue
incoming connections until you either call the Stop method. For example,
server.Start();
When the server starts listening, you need to use either a TcpClient or a Socket object to
connect with the TcpListener object. For example, you can declare an object using
TcpClient client;
or
Socket sock = new Socket();
This lecture choose to use TcpClient. To create an instance you can use either AcceptSocket
or AcceptTcpClient to pull a connection from the incoming connection request queue. These
two methods will “block” (means it will perform a blocking call to accept requests). For
Visual C# - Penn P. Wu, PhD. 436
example, declare a TcpClient object named “client” and then create an instance using either
AcceptSocket or AcceptTcpClient.
TcpClient client = server.AcceptTcpClient();
or TcpClient client = server.AcceptSocket();
When the clients connect to the server, the transmission between both parties is bilateral (means “two-directions”), as shown below.
The TcpClient type also provides properties to monitor the client’s status. Details are available
at http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient_properties.aspx. For
example,
• Active: Get or set a value that indicates whether a connection has been made.
• Available: Get the amount of data that has been received from the network and is available
to be read.
• Client: Get or sets the underlying Socket.
• Connected: Get a value indicating whether the underlying Socket for a TcpClient is
connected to a remote host.
You can now create a generic socket server as a console or Windows application. A complete
code is available in the learning activity. The following is a functional code, to its minimum,
that can build a TCP server on port 8888. Once a client has connected, it will send the client a
message. In this example, the instructor uses the Connected property to determine if a client has
made the connection.
using System;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
class TCPServer{
public static void Main(){
// setup tcp server
IPAddress localAddr = IPAddress.Parse("127.0.0.1"); //serverIP
TcpListener server = new TcpListener(localAddr, 8888);//port
no.
server.Start(); // start listening
//create an object that represent the client
TcpClient client = server.AcceptTcpClient();
if (client.Connected) {
MessageBox.Show("Server Message: A client connected.");
}
}
}
The above is a simple console code, so it does not need multithreading. When being converted
the GUI-based code needs multithreading support. You need to keep the form and its
components functioning. Meanwhile make sure the application is always listening to the
TcpClient’s call.
Server port port Client
Request response
Visual C# - Penn P. Wu, PhD. 437
When the connection is made, it is necessary to have a buffer for reading data from the client.
For example, you can use the Byte structure represents an 8-bit unsigned integer array. The
following is a Byte array with 256 elements.
Byte[] bytes = new Byte[256];
The buffers can hold data, but the code needs a read-and-write function to send and receive
data. The following use the TcpClient.GetStream() method to return a stream. The stream is a
block of data used by both server and client to send and receive data. The NetworkStream
class provides methods for sending and receiving data over the stream sockets in blocking
mode.
NetworkStream stream = client.GetStream();
The NetworkStream class has many methods. For example, you can use the Read and Write methods to read and write data from the network stream between a client and a server. The
syntax of Read method is:
Read(buffer, offset, size)
where buffer is an array of type Byte that is the location in memory to store data read from the
NetworkStream, offset indicates the location in buffer to begin storing the data to, and size is
the number of bytes to read from the NetworkStream. For example,
int i = Read(bytes, 0, bytes.Length);
You can create a loop to receive all the data sent by the client and specify the responses to the
client. A while loop is a good candidate for this task.
NetworkStream stream = client.GetStream();
while((i = stream.Read(bytes, 0, bytes.Length))!=0) {
// Translate data bytes to an ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
// Process the data sent by the client using ToUpper
data = data.ToUpper();
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
// Send back a response.
stream.Write(msg, 0, msg.Length);
Console.WriteLine("Sent: {0}", data);
}
The Encoding.ASCII property gets an encoding for the ASCII (7-bit) character set and 7-bit
ASCII is the default encoding system. Using ASCII encoding has a drawback. ASCII
characters are limited to the lowest 128 Unicode characters. The following example demonstrates how to read a UTF-8 (Unicode) encoded string from a binary file.
public static void Main(){
String str = "This is message with Pi (\u03a0) and Sigma
(\u03a3).";
String utf8Str = "";
Byte[] Bytes = Encoding.UTF8.GetBytes(str);
Visual C# - Penn P. Wu, PhD. 438
foreach (Byte b in Bytes) {
utf8Str += b + "\n";
}
MessageBox.Show(str);
MessageBox.Show(utf8Str);
}
If you wish to translate data bytes to UTF-8 strings, use:
data = System.Text.Encoding.UTF8.GetString(bytes, 0, i);
The Encoding.GetString method decodes all the bytes in the specified byte array into a string.
The syntax is:
GetString(bytes, index, count)
where bytes is the byte array containing the sequence of bytes to decode, index is the index of
the first byte to decode, and count is the number of bytes to decode. The following translates data bytes sent by the client to an ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
The following use the Write methods of the NetworkStream to send the remote client the
response. A sample code in the learning activity will demonstrate how to send response to
clients.
stream.Write(msg, 0, msg.Length);
The .NET Framework provides the Threading class of the System.Threading namespace to
enable C# program to perform concurrent processing. With this support, you can do more than
one operation at a time.
The System.Threading namespace provides classes and interfaces that support multithreaded programming and enable you to easily perform tasks such as creating and starting new threads,
synchronizing multiple threads, suspending threads, and aborting threads.
To incorporate threading in your C# code, add the System.Threading as reference.
using System.Threading;
You can then create a private Thread object, as shown below, and use it to control a the method that listens to the TcpClient’s call. For example,
private Thread thrListener;
....
thrListener = new Thread(serverListening);
thrListener.Start();
To start listening to the TcpClient’s call, simply stop the Thread object. For example,
thrListener.Abort();
The code that illustrates this implementation is available in the learning activity.
Notice that a TextBox control displays its contents from the first to the last line by default.
When a TextBox control has its multiline property set to true, you can use the
Visual C# - Penn P. Wu, PhD. 439
TextBox.AppendText() method to append text to the text of the textbox. This method will
insert the text and automatically scroll to the last added line.
If you insist on doing it by hand, you can reposition the caret to the end of the textbox if
necessary (first line) and scroll to the caret (second line)
textBox1.SelectionStart = textBox1.Text.Length;
textBox1.ScrollToCaret();
The client application has similar design concept. The TcpClient class provides client
connections for TCP network services. A client applicant can use it for connecting, sending,
and receiving stream data over a network in synchronous blocking mode.
The following initializes a new instance of the TcpClient class and connects to the specified
port on the specified host.
TcpClient client = new TcpClient("127.0.0.1", 13000);
To allow the users to enter the remote server’s IP address, you can create textbox control and
retrieve the user inputs from the textbox. For example,
TcpClient client = new TcpClient(textBox1.Text, 13000);
The Encoding.ASCII property gets an encoding for the ASCII (7-bit) character set. The
Encoding.GetBytes method encodes a set of characters into a sequence of bytes. The following
can then translate the message into ASCII and store it as a Byte array.
Byte[] data = System.Text.Encoding.ASCII.GetBytes("Hello");
The ASCII encoding is usually appropriate for protocols that require ASCII and is functionally
sufficient for English characters.
To send and receive data, use the GetStream method to obtain a NetworkStream. For example,
NetworkStream stream = client.GetStream();
Use the Write and Read methods of the NetworkStream to send and receive data with the
remote host. The following example sends the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
The following example reads the first batch of the TcpServer response bytes.
Int32 bytes = stream.Read(data, 0, data.Length);
You can call the ASCII.GetString method to translate the binary codes to a string of
characters.
ASCII.GetString(data, 0, bytes);
Unlike the server, the client should send request on demand. Each client request is an individual
event. So, you do not need to create a loop.
You can now create a generic socket TCP client as a console application. A complete code is
available in the learning activity. The following is a functional code, to its minimum, that
creates a client application.
using System;
using System.IO;
Visual C# - Penn P. Wu, PhD. 440
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
class TCPClient {
public static void Main(){
try {
TcpClient client = new TcpClient("127.0.0.1", 8888);
Byte[] data = System.Text.Encoding.ASCII.GetBytes("Hi");
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
MessageBox.Show("The client sent \"Hi\", to server!");
client.Close();
}
catch (Exception e) {
String str = e.Message;
}
}
}
The above code can be converted to a GUI-based Windows application. The complete code is
available in the learning activity. One thing that must be addressed is that a generic C#
Windows Form application has one thread by default. This thread executes the code in the
program starting and ending with the Main method. Every command executed by Main--either directly or indirectly--is performed by the default, or primary thread, and this thread terminates
when Main returns.
When you start the server, and then the client. Both client and server application works 100%
as expected when they are running locally. However, if you try to test them with two
computers, the server and client will not connect. Obviously, the problem was that the above
codes used the IP Address “127.0.0.1” for the TCPListener, as shown below.
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
If you want the server to be accessible remotely, then you need to use the remote IP Address of
the computer (e.g. 192.168.0.119). The following is a class that retrieves the actual IP address
of a server. It is a sample solution.
public static IPAddress GetIPAddress() {
IPHostEntry hostEntry =
Dns.GetHostEntry(Environment.MachineName);
foreach (IPAddress address in hostEntry.AddressList) {
if (address.AddressFamily == AddressFamily.InterNetwork)
return address;
}
return null;
}
To use this class, simply make the following call:
IPAddress ipAddr = GetIPAddress();
TcpListener server = new TcpListener(ipAddr, 8888);
Visual C# - Penn P. Wu, PhD. 441
When executing this server application for the first time, you may be asked by the Windows
Firewall to block this program. Be sure to click “Allow access”, so the client application can
access this server application from a remote computer.
Another solution, which is probably better, is to use the IPAddress.Any field which indicates
that the server must listen for client activity on all network interfaces. For example,
TcpListener tcpListener = new TcpListener(IPAddress.Any, 8888);
UDP
connection
UDP is a connectionless transport protocol. You do not need to establish a remote host
connection prior to sending and receiving data. However, you have to make sure the server
exists and will in a later time receive your request.
The UdpClient class provides simple methods for sending and receiving connectionless UDP
datagrams in blocking synchronous mode. You have the option of establishing a default remote
host in one of the following two ways:
• Create an instance of the UdpClient class using the remote host name and port number as
parameters. For example,
UdpClient udpClient = new UdpClient("www.contoso.com",11000);
• Create an instance of the UdpClient class and then call the Connect method. For example,
the UdpClient constructor arbitrarily assigns the local port number.
UdpClient udpClient = new UdpClient(11000);
udpClient.Connect("www.contoso.com", 11000);
The Socket constructor can initialize a new instance of the Socket class using the specified
address family, socket type and protocol. The syntax is:
Socket(addressFamily, socketType, protocolType)
The addressFamily parameter specifies the addressing scheme that the Socket class uses, the
socketType parameter specifies the type of the Socket class, and the protocolType parameter
specifies the protocol used by Socket. The three parameters are not independent. Some address
families restrict which protocols can be used with them, and often the Socket type is implicit in
the protocol.
The following creates a socket object. This is the fundamental device used for network
communications. When creating this object you specify:
• Internetwork: Use the internet communications protocol
• Dgram: Use datagrams or broadcast to everyone rather than send to a specific listener
• Udp: the messages are to be formated as user datagram protocol. Socket sending_socket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
Available values of the AddressFamily enumeration can be found at
http://msdn.microsoft.com/en-us/library/system.net.sockets.addressfamily.aspx. Values of
Visual C# - Penn P. Wu, PhD. 442
SocketType enumeration is available at http://msdn.microsoft.com/en-
us/library/system.net.sockets.sockettype.aspx. Values of ProtocolType enumeration can be
found at http://msdn.microsoft.com/en-us/library/system.net.sockets.protocoltype.aspx
This UDP server is meant to broadcast to UDP clients. You need to create an IPAddress object and use it to specify the IP address of the client. For example,
IPAddress client = IPAddress.Parse("127.0.0.1");
You can specify a subnet and send UDP messages to all the computers in that subnet. In the
following example, this particular address ends in 255 indicates that UDP message will be sent
to all clients with IP address beginning with 192.168.1.n.
IPAddress client = IPAddress.Parse("192.168.1.255");
Create an object of the IPEndPoint class which represents a network endpoint as an IP address
and a port number. The syntax is:
IPEndPoint(IPAddress, Int32 port)
where IPAddress is a Local IP address and port represents a Int32 type of port number. For
example,
IPEndPoint RemoteIpEndPoint = new IPEndPoint(client, 11000);
You can specify with the Any property for the local IP address and 0 for the local port number
if you want the underlying service provider to assign those values for you. Technically
speaking, the Any field is equivalent to 0.0.0.0 in dotted-quad notation. For example, the
following IPEndPoint object will allow us to read datagrams sent from any source.
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
If you choose to do this, you can use the LocalEndpoint property to identify the assigned
information, after the socket has connected.
The following is a generic UDP server code.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
class MyUDPServer {
static void Main(string[] args) {
Socket sendSoc = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
IPAddress client = IPAddress.Parse("127.0.0.1");
IPEndPoint RemoteIpEndPoint = new IPEndPoint(client, 11000);
Console.WriteLine("Enter text to broadcast via UDP.");
string msg = Console.ReadLine();
byte[] send_buffer = Encoding.ASCII.GetBytes(msg);
Console.WriteLine("sending to address: {0} port: {1}",
RemoteIpEndPoint.Address,
RemoteIpEndPoint.Port);
Visual C# - Penn P. Wu, PhD. 443
try {
sendSoc.SendTo(send_buffer, RemoteIpEndPoint);
}
catch (Exception ex) {
string str = ex.Message;
Console.WriteLine("The exception indicates the message was not
sent.");
}
finally{
Console.WriteLine("Message has been sent to the broadcast
address");
}
}
}
You can send to all IP address on your subnet mask. This is known as broadcasting. It is one of the main features of UDP. To send to all clients use IPAddress.Broadcast on the sending and
IPAddress.Any on the receiving. The IPAddress.Broadcast field is equivalent to
255.255.255.255 in dotted-quad notation. The IPAddress.Any field is equivalent to 0.0.0.0 in
dotted-quad notation. For example,
// sending
IPEndPoint groupEP = new IPEndPoint(IPAddress.Broadcast, 11000);
and
// receiving
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 11000);
To use IPAddress.Broadcast you must set the EnableBroadcast property of the Socket object
(e.g. sendSoc) to true. For example,
sendSoc.EnableBroadcast = true;
The following is a simple but complete code of UDP client application.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class MyUDPClient {
private const int listenPort = 11000;
public static int Main() {
bool done = false;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenPort);
string serverMsg;
byte[] byteArr;
try {
while (!done) {
Console.WriteLine("Waiting for broadcast");
byteArr = listener.Receive(ref groupEP);
Console.WriteLine("Received a broadcast from {0}",
groupEP.ToString() );
Visual C# - Penn P. Wu, PhD. 444
serverMsg = Encoding.ASCII.GetString(byteArr, 0,
byteArr.Length);
Console.WriteLine("data follows \n{0}\n\n", serverMsg);
}
}
catch (Exception e) {
Console.WriteLine(e.ToString());
}
listener.Close();
return 0;
}
}
Review
Questions
1. Which can create an instance of IPAddress class? (Assuming the server IP is 204.1.9.114)
A. IPAddress server = "204.1.9.114"; B. IPAddress server = new IPAddress.Parse("204.1.9.114");
C. IPAddress server = IPAddress.Parse("204.1.9.114");
D. IPAddress server = new IPAddress("204.1.9.114");
2. Which initializes a new instance of the TcpListener class that listens for incoming connection
attempts on the specified local IP address 204.1.9.114 and port number 1964?
A. TcpListener server = new TcpListener("204.1.9.114", 1964);
B. TcpListener server = new TcpListener(1964, "204.1.9.114");
C. TcpListener server = new TcpListener((IPAddress) "204.1.9.114", 1964);
D. None of the above
3. Given the following code, which can for the application to begin listening for incoming
connection requests?
TcpListener server = new TcpListener(IPAddress.Any, 13000);
A. server.Connected = true;
B. server.Start();
C. server.Enabled = true;
D. server.Listen();
4. Given the following code, which can determine whether the underlying Socket for a TcpClient is connected to a remote host?
TcpClient client = server.AcceptTcpClient();
A. client.Connected
B. client.Connect()
C. client.Activated
D. client.Socket()
5. Given the following code, which is the correct way to read data from the network stream
between a client and a server?
TcpClient client = server.AcceptTcpClient();
............
Byte[] bytes = new Byte[256];
NetworkStream stream = client.GetStream();
A. Read(bytes, bytes.Length, 0);
B. Read(bytes, 0, bytes.Length);
C. Read(bytes.Length, bytes, 0);
Visual C# - Penn P. Wu, PhD. 445
D. Read(0, bytes.Length, bytes);
6. Given the following statement, which is correct?
data = System.Text.Encoding.ASCII.GetString(bytes, 0, 32);
A. bytes is the byte array containing the sequence of bytes to decode
B. 0 is the index of the first byte to decode
C. 32 is the number of bytes to decode
D. All of the above
7. Which can terminate the following threading object?
Thread thread1 = new Thread(serverListening);
A. thread1.Dispose();
B. thread1.Abort(); C. thread1.Stop();
D. thread1.Terminate();
8. If the remote server has an static IP address of 204.10.1.211, which will allow a remote client
to access it?
A. TcpClient client = new TcpClient("127.0.0.1", 8888);
B. TcpClient client = new TcpClient("204.10.1.211", 8888);
C. TcpClient client = new TcpClient(IPAddress.Any, 8888);
D. TcpClient client = new TcpClient(IPAddress.All, 8888);
9. Which can establish a default remote host of the UdpClient class? A. UdpClient udpClient = new UdpClient("www.contoso.com"); Int port= 11000;
B. UdpClient udpClient = new UdpClient(11000); udpClient.Connect("www.contoso.com",
11000);
C. UdpClient udpClient = new UdpClient(11000, "www.contoso.com");
D. UdpClient udpClient = new UdpClient(11000, "www.contoso.com");
udpClient.Connect(11000);
10. The IPAddress.Broadcast field is equivalent to __ in dotted-quad notation
A. 255.255.255.255
B. 255.255.255.0
C. 255.255.0.0
D. 255.0.0.0
Visual C# - Penn P. Wu, PhD. 446
Lab #14 Building Server and Client Applications
Learning Activity #1: Building a simple TCP server and client (without data transmission)
1. Create the C:\cis218 directory if it does not exist.
2. Launch the Development Command Prompt.
3. Under the C:\cis218 directory, use Notepad to create a new text file named lab14_1.cs with the following
contents.
using System;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Text;
class MyServer {
public static void Main() {
TcpListener tcpListener = new TcpListener(IPAddress.Any, 8888);
tcpListener.Start();
Socket socket = tcpListener.AcceptSocket();
string responseString = "You have successfully connected to me";
//Forms and sends a response string to the connected client.
Byte[] sendBytes = Encoding.ASCII.GetBytes(responseString);
int i = socket.Send(sendBytes);
if (i != 1) {
MessageBox.Show("Connected", "Server");
}
}
}
4. Type csc.exe /t:winexe lab14_1.cs and press [Enter] to compile.
5. Test the program. Click “Allow Access” when you see the following message (or similar sent by your firewall
application).
6. Use Notepad to create a new text file named “lab14_1_client.cs” with the following contents.
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
class TCPClient {
Visual C# - Penn P. Wu, PhD. 447
public static void Main(){
try {
TcpClient client = new TcpClient("127.0.0.1", 8888);
Byte[] data = System.Text.Encoding.ASCII.GetBytes("Hi");
NetworkStream stream = client.GetStream();
stream.Write(data, 0, data.Length);
MessageBox.Show("Sent \"Hi\", to server!", "Client");
client.Close();
}
catch (Exception e) {
String str = e.Message;
}
}
}
7. Type csc.exe /t:winexe lab14_1_client.cs and press [Enter] to compile.
8. Launch lab14_1.exe and keep it running, then launch lab14_1_client.exe. A sample output looks:
and
9. Download the “assignment template”, and rename it to lab14.doc if necessary. Capture a screen shot similar to the above and paste it to the Word document named lab14.doc (or .docx).
Learning Activity #2: Building a simple TCP server
1. Under the C:\cis218 directory, use Notepad to create a new text file named lab14_2.cs with the following
contents. using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
public class Form1 : Form {
TextBox textBox1;
Boolean ServRunning = false;
TcpListener server=null;
TcpClient client;
NetworkStream stream;
// The thread that will hold the connection listener
private Thread thrListener;
public Form1() {
Button button1 = new Button();
button1.Text = "Start Server";
Visual C# - Penn P. Wu, PhD. 448
button1.Location = new Point(10, 10);
button1.Click += new EventHandler(this.button1_Click);
Controls.Add(button1);
Button button2 = new Button();
button2.Text = "Stop Server";
button2.Location = new Point(190, 10);
button2.Click += new EventHandler(this.button2_Click);
Controls.Add(button2);
textBox1 = new TextBox();
textBox1.Multiline = true;
textBox1.Location = new Point(10, 40);
textBox1.Size = new Size(256, 180);
Controls.Add(textBox1);
}
public void button1_Click(Object sender, EventArgs e) {
// TcpListener server = new TcpListener(port);
server = new TcpListener(IPAddress.Any, 8888);
server.Start(); // start listening for client request
ServRunning = true;
textBox1.Text = "Server started...";
thrListener = new Thread(serverListening);
thrListener.Start();
}
private void serverListening() {
while (ServRunning == true) {
Byte[] bytes = new Byte[256]; // buffer for reading data
try {
// perform a blocking call to accept requests
client = server.AcceptTcpClient();
textBox1.AppendText(Environment.NewLine + "> Client connected!");
String data = null;
// get a stream object for reading and writing
stream = client.GetStream();
int i = stream.Read(bytes, 0, bytes.Length);
// translate data bytes to an ASCII string
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
textBox1.AppendText(Environment.NewLine + ">> " + data);
// translate a string message to bytes
byte[] msg = System.Text.Encoding.ASCII.GetBytes("Welcome");
stream.Write(msg, 0, msg.Length); // send client the message
// log the message on the textbox
textBox1.AppendText(Environment.NewLine + ">> Server response: \"Welcome\".");
client.Close();
}
catch(Exception ex) {
String str = ex.Message;
}
}
}
Visual C# - Penn P. Wu, PhD. 449
public void button2_Click(Object sender, EventArgs e) {
try {
stream.Close();
client.Close();
server.Stop();
thrListener.Abort(); //Stopping thread
ServRunning=false;
}
catch(Exception ex) {
String str = ex.Message;
}
finally {
textBox1.Text = "Server stop...";
}
}
[STAThread]
public static void Main() {
Application.Run(new Form1());
}
}
2. Type csc /t:winexe lab14_2.cs and press [Enter] to compile. Test the program. Click “Allow Access” if
the following (or similar message) appears.
3. Launch lab14_2.exe, click “Start Server”, and keep this program running. You can use the lab14_1_client.exe
file to test this server. A sample output looks:
and
4. Click “Stop Server” to stop the server, and then click “Start Server” to restart it. Test with the client application
again.
5. Capture a screen shot similar to the above and paste it to the Word document named lab14.doc (or .docx).
Learning Activity #3: Building a simple TCP client
1. Under the C:\cis218 directory, use Notepad to create a new text file named lab14_3.cs with the following
contents. using System;
using System.IO;
Visual C# - Penn P. Wu, PhD. 450
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
public class Form1 : Form {
String message = "Greeting from the client";
TextBox textBox1, textBox2;
TcpClient client;
public Form1() {
this.Width = 335;
Label label1 = new Label();
label1.Text = "Server IP:";
label1.AutoSize = true;
label1.Location = new Point(10, 10);
Controls.Add(label1);
textBox1 = new TextBox();
textBox1.Width = 100;
textBox1.Location = new Point(65, 10);
Controls.Add(textBox1);
textBox2 = new TextBox();
textBox2.Width = 300;
textBox2.Multiline = true;
textBox2.Height = 200;
textBox2.Location = new Point(10, 40);
Controls.Add(textBox2);
Button button1 = new Button();
button1.Text = "Connect";
button1.Width = 60;
button1.Location = new Point(170, 10);
button1.Click += new EventHandler(this.button1_Click);
Controls.Add(button1);
Button button2 = new Button();
button2.Text = "disconnect";
button2.Location = new Point(235, 10);
button2.Click += new EventHandler(this.button2_Click);
Controls.Add(button2);
}
public void button1_Click(Object sender, EventArgs e) {
try {
client = new TcpClient(Convert.ToString(textBox1.Text), 8888);
// Translate the passed message into ASCII and store it as a Byte array.
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
// Get a client stream for reading and writing.
NetworkStream stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
textBox2.AppendText(Environment.NewLine + ">> Sent: " + message);
// Buffer to store the response bytes.
data = new Byte[256];
Visual C# - Penn P. Wu, PhD. 451
// String to store the response ASCII representation.
String responseData = String.Empty;
// Read the first batch of the TcpServer response bytes.
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
textBox2.AppendText(Environment.NewLine + ">> Received: " + responseData);
// Close everything.
stream.Close();
}
catch (Exception ex) {
textBox2.AppendText(Environment.NewLine + ex.Message + "....");
}
}
public void button2_Click(Object sender, EventArgs e) {
try {
client.Close();
}
catch (Exception ex) {
String str = ex.Message;
textBox2.AppendText("No connection made yet!");
}
finally {
textBox2.AppendText(Environment.NewLine + "disconnected....");
}
}
[STAThread]
public static void Main() {
Application.Run(new Form1());
}
}
2. Type csc /t:winexe lab14_3.cs and press [Enter] to compile.
3. Launch the lab14_2.exe and keep it running as the server. Test the program by accessing the server. If the server
and client are in the same machine, use 127.0.0.1 as server’s IP address; otherwise, use the correct IP address of
the server. To find the server’s IP address issue “ipconfig” in a Command Prompt of the server. A sample
output looks:
and
4. Capture a screen shot similar to the above and paste it to the Word document named lab14.doc (or .docx).
Learning Activity #4: Building a simple UDP server
1. Under the C:\cis218 directory, use Notepad to create a new text file named lab14_4.cs with the following
contents.
using System;
Visual C# - Penn P. Wu, PhD. 452
using System.Drawing;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class Form1 : Form {
TextBox textBox1, textBox2;
Label label1;
// IPEndPoint client;
Socket sendSoc;
IPEndPoint groupEP;
public Form1() {
Button button1 = new Button();
button1.Text = "Start Server";
button1.Location = new Point(10, 10);
button1.Click += new EventHandler(this.button1_Click);
Controls.Add(button1);
Button button2 = new Button();
button2.Text = "Send";
button2.Location = new Point(200, 40);
button2.Click += new EventHandler(this.button2_Click);
Controls.Add(button2);
label1 = new Label();
label1.Text = "Enter text to broadcast via UDP:";
label1.AutoSize = true;
label1.Location = new Point(10, 50);
Controls.Add(label1);
textBox1 = new TextBox();
textBox1.Multiline = true;
textBox1.Location = new Point(10, 70);
textBox1.Size = new Size(ClientSize.Width - 20, 50);
textBox1.ScrollBars = ScrollBars.Vertical;
Controls.Add(textBox1);
textBox2 = new TextBox();
textBox2.Multiline = true;
textBox2.Location = new Point(10, 130);
textBox2.Size = new Size(ClientSize.Width - 20, 120);
textBox2.ScrollBars = ScrollBars.Vertical;
Controls.Add(textBox2);
}
public void button1_Click(Object sender, EventArgs e) {
sendSoc = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
// to an individual IP
// IPAddress ipAddr = IPAddress.Parse("192.168.0.119");
// client = new IPEndPoint(ipAddr, 11000);
// send to a subnet
groupEP = new IPEndPoint(IPAddress.Broadcast, 11000);
textBox2.Text = "Server started...";
}
Visual C# - Penn P. Wu, PhD. 453
public void button2_Click(Object sender, EventArgs e) {
byte[] send_buffer = Encoding.ASCII.GetBytes(textBox1.Text);
textBox2.AppendText(Environment.NewLine + "> sending to address: " +
IPAddress.Broadcast);
try {
// send to an individual client
//sendSoc.SendTo(send_buffer, client);
// send to a group
sendSoc.EnableBroadcast = true;
sendSoc.SendTo(send_buffer, groupEP);
//sendSoc.Send(send_buffer, send_buffer.Length, groupEP);
}
catch (Exception ex) {
string str = ex.Message;
textBox2.AppendText(Environment.NewLine + ex.Message + " Message not sent.");
}
finally{
textBox2.AppendText(Environment.NewLine + ">> Message has been sent to the
broadcast address.");
}
}
[STAThread]
public static void Main() {
Application.Run(new Form1());
}
}
2. Type csc /t:winexe lab14_4.cs and press [Enter] to compile.
3. Test the program after you complete learning activity #5. A sample output looks:
4. Capture a screen shot similar to the above and paste it to the Word document named lab14.doc (or .docx).
Learning Activity #5: Building a simple UDP client
1. Under the C:\cis218 directory, use Notepad to create a new text file named lab14_5.cs with the following
contents. using System;
using System.Drawing;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
Visual C# - Penn P. Wu, PhD. 454
public class Form1 : Form {
TextBox textBox1;
// The thread that will hold the connection listener
private Thread udpListener;
public Form1() {
this.Size = new Size(400, 200);
textBox1 = new TextBox();
textBox1.Text += "> Waiting for broadcast..." + Environment.NewLine;
textBox1.Multiline = true;
textBox1.Location = new Point(10, 10);
textBox1.Size = new Size(ClientSize.Width - 20, ClientSize.Height-20);
textBox1.ScrollBars = ScrollBars.Vertical;
Controls.Add(textBox1);
udpListener = new Thread(serverListening);
udpListener.Start();
}
private void serverListening() {
UdpClient listener = new UdpClient(11000);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, 11000);
String str = "";
try {
while (true) {
byte[] byteArr = listener.Receive(ref groupEP);
str = ">> Received a broadcast from " + groupEP.ToString() +
Environment.NewLine;
string serverMsg = Encoding.ASCII.GetString(byteArr, 0, byteArr.Length);
str += ">> Message :" + Environment.NewLine + serverMsg;
textBox1.AppendText(str + Environment.NewLine);
}
}
catch (Exception ex) {
str += ex.ToString();
}
finally {
listener.Close();
}
}
[STAThread]
public static void Main() {
Application.Run(new Form1());
}
}
2. Type csc /t:winexe lab14_5.cs and press [Enter] to compile. Click “Allow Access” if being asked by the
firewall application.
3. Launch lab14_5.exe, and click “Start Server”. Test the program. A sample output looks:
Visual C# - Penn P. Wu, PhD. 455
and
4. Capture a screen shot similar to the above and paste it to the Word document named lab14.doc (or .docx).
Submittal
1. Complete all the 5 learning activities.
2. Create a .zip file named lab14.zip containing ONLY the following self-executable files.
• lab14_1.exe
• lab14_2.exe
• lab14_3.exe
• lab14_4.exe
• lab14_5.exe
• lab14.doc (or .docx) [You may be given zero point if this Word document is missing]
3. Log in to course site, and enter the course site.
4. Upload the zipped file to question 11 of Assignment.
Programming Exercise:
1. Use Notepad to create a new file named ex14.cs with the following (be sure to replace YourFullNameHere with
the correct one):
//File Name: ex14.cs
//Programmer: YourFullNameHere
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
public class TCPServer
{
private static int port = 8001;
public static void Main()
{
IPAddress ipAddress = IPAddress.Any;
TcpListener listener = new TcpListener(ipAddress, port);
listener.Start();
Console.WriteLine("Server is running");
Console.WriteLine("Listening on port " + port);
Console.WriteLine("Waiting for connections...");
while (true)
{
Socket s = listener.AcceptSocket();
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);
byte[] b = new byte[65535];
int k = s.Receive(b);
Console.WriteLine("Received:");
Visual C# - Penn P. Wu, PhD. 456
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(b[i]));
ASCIIEncoding enc = new ASCIIEncoding();
s.Send(enc.GetBytes("Server responded"));
Console.WriteLine("\nSent Response");
s.Close();
}
}
}
2. Convert the above console-based TCP server to a GUI-based one.
3. Compile the program. Click “Start Server”. A sample output looks:
4. Download the “programming exercise template”, and rename it to ex14.doc. Capture a screen shot similar to the
above figure and then paste it to the Word document named “ex14.doc” (or .docx).
5. Compress the source code (ex14.cs), the executable (ex14.exe), and the Word document (ex14.doc or .docx) to
a .zip file named “ex14.zip”. You may be given zero point if any of the required file is missing.
Grading Criteria:
• You must be the sole author of the codes.
• You must meet all the requirements in order to earn credits. You will receive zero if you use Visual Studio (C#)
IDE to generate the code.
• No partial credit is given.