networking in .net (1) lecture notes/week 11-2.pdf · 2006-11-23 · 1 networking in .net (1) these...
TRANSCRIPT
1
Networking in .NET (1)
These slides are meant to be for teaching purposes only and only for the students that are registered in CSE4413 and should not be published as a
book or in any form of commercial product, unless written permission is obtained.
2
Client-Server model
• All communication (SOAP exchanges, Web applications, etc) is done via “low level” socket programming.
• The general idea is:– A computer that acts as “Server” makes its
service(s) available at a particular port.– Other computers that know about this server
can then request connections and receive the service(s).
3
Typical Client-Server communication scenario
• Server1. Initiate “service available”
at a particular port.2. Wait for client request for
connection.3. Once client’s request is
received: a) Establish connectionb) Establish communication
stream (so that can send and receive data).
4. Provide service5. Close connection6. Go to step 2 (wait for
client’s request for connection).
• Client1. Request connection from
server (must know: server “name” (IP address) and port # at which service is available).
2. (If connection is established) establish communication stream (so that can send and receive data).
3. Get the service.
4
Typical Client-Server communication scenario
Server Client
80
5555
…
port
client = new TcpClient( );
client.Connect( "localhost", 5555);
cs= client.GetStream();
reader = new BinaryReader( cs) ;
writer = new BinaryWriter( cs) ;
server = new TcpListener( 5555);
server.Start();
c = server.AcceptSocket();
ss = new NetworkStream(c);
reader = new BinaryReader(ss);
writer = new BinaryWriter(ss);
Initiate “service available” at port 5555. Wait for client request for connection.
Establish connection with client; Establish communication stream (so that can send and
receive data).
Request connection from server with IP localhost, at port 5555
5
An application
The server
The client
6
After the client connects, the server sends a message and closes the
connection.
The client receives and displays the
message.
7
Designer view :: Server
8
Code structure :: Server
9
The code :: Serverusing System;using System.Drawing;using System.Collections;using System.ComponentModel;using System.Windows.Forms;using System.Data;
using System.Threading;using System.Net.Sockets;using System.IO;
namespace WindowsApplication2Server{
public class Form1 : System.Windows.Forms.Form{
private System.Windows.Forms.Button button1;private System.Windows.Forms.Label label1;
private Socket conn; // the client
private NetworkStream socketStream; private BinaryReader reader;private BinaryWriter writer; private Thread readThread;private System.Windows.Forms.Label label2;private System.Windows.Forms.Button button2;
Needed for threading, networking and message
exchanges.
10
..private System.ComponentModel.Container components = null;
public Form1(){
InitializeComponent();}
//…[STAThread]static void Main() {
Application.Run(new Form1());}
private void button1_Click(object sender, System.EventArgs e){
readThread = new Thread( new ThreadStart( RunServer ) );readThread.Start();
label2.Text = "calling run server";}
public void RunServer() {
TcpListener listener ;
11
…try {
label2.Text += "\r\nTrying to establish server at port 5555";// create listener (the server)
listener = new TcpListener( 5555); // listens at port 5555label2.Text += "\r\nEstablished server at port 5555";
// server waits for connection
listener.Start();label2.Text += "\r\nestablished connection and waiting for client...";
// establish connection upon client's requestwhile ( true ) {
conn = listener.AcceptSocket(); // establish connectionlabel2.Text += "\r\n .... client connected!!!";
// create communication steam
socketStream = new NetworkStream( conn);label2.Text += " opening communication stream ...";
// attach a reader and a writer to the stream
writer = new BinaryWriter( socketStream);label2.Text += "\r\n ... ... opened writer";
reader = new BinaryReader( socketStream);label2.Text += "\r\n ... ... opened reader";
writer.Write( "(FROM SERVER) -- connection established");writer.Write( "\r\n(Server)-- connection closing...");label2.Text += "\r\n ... sent message to client!";
writer.Close();label2.Text += " ...closed connection";
} }catch ( Exception ex) {
MessageBox.Show( ex.ToString());}
}
12
…/
private void button2_Click(object sender, System.EventArgs e){
try {
writer.Close();reader.Close();socketStream.Close();conn.Close();
}catch ( Exception ee) {
MessageBox.Show( ee.ToString());}Application.Exit();
}}}
13
Designer view :: Client
14
Code structure :: Client
15
The code :: Clientusing System;using System.Drawing;using System.Collections;using System.ComponentModel;using System.Windows.Forms;using System.Data;
using System.Threading;using System.Net.Sockets;using System.IO;
namespace WindowsApplication1Client{
/// <summary>/// Summary description for Form1./// </summary>public class Form1 : System.Windows.Forms.Form{
private System.Windows.Forms.Button button1;private System.Windows.Forms.Label label1;private System.Windows.Forms.Button button2;private System.ComponentModel.Container components = null;
public Form1(){}
16
…/// <summary>/// Clean up any resources being used./// </summary>
//…private void InitializeComponent(){
this.button1 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();this.button2 = new System.Windows.Forms.Button();this.SuspendLayout();// // button1// this.button1.Location = new System.Drawing.Point(32, 32);this.button1.Name = "button1";this.button1.TabIndex = 0;this.button1.Text = "Start Client";this.button1.Click += new System.EventHandler(this.button1_Click);// // label1// this.label1.Location = new System.Drawing.Point(16, 72);this.label1.Name = "label1";this.label1.Size = new System.Drawing.Size(352, 216);this.label1.TabIndex = 1;this.label1.Text = "label1";// // button2// this.button2.Location = new System.Drawing.Point(168, 40);this.button2.Name = "button2";this.button2.TabIndex = 2;this.button2.Text = "Exit Client";this.button2.Click += new System.EventHandler(this.button2_Click);// // Form1// this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);this.ClientSize = new System.Drawing.Size(392, 301);this.Controls.Add(this.button2);this.Controls.Add(this.label1);this.Controls.Add(this.button1);this.Name = "Form1";this.Text = "Form1";this.ResumeLayout(false);
}#endregion
17
…
[STAThread]static void Main() {
Application.Run(new Form1());}
private Thread readThread;
private void button1_Click(object sender, System.EventArgs e){
readThread = new Thread( new ThreadStart ( RunClient));readThread.Start();
}
18
…private NetworkStream clientStream;private BinaryWriter writer;private BinaryReader reader;
public void RunClient() {
TcpClient client;
try {
label1.Text = "Attempting connection to server ...";
client = new TcpClient( );client.Connect( "localhost", 5555);
label1.Text += "\r\n" + "connection established!";// establish a data exchange capable stream.
clientStream = client.GetStream();// hookup reader and writer to streams
reader = new BinaryReader( clientStream) ;writer = new BinaryWriter( clientStream) ;
bool gotServerMessage = false;
string message = "";
19
…/
do {
message = reader.ReadString();
label1.Text += "\r\n" + " received message from server!";
label1.Text += "\r\n the message :: " + message;
gotServerMessage = true;
} while ( !gotServerMessage );}catch ( Exception ee ) { }
}
private void button2_Click(object sender, System.EventArgs e){
Application.Exit();}
}}
20
Threads
• A thread is a “lightweight” process. • Processes run within their own separate space
and communicate with each other by exchanging messages (since they do not share any space).
• Threads run within a process and communicate with each other by sharing memory space. (i.e. by being able to access the same space as other fellow threads).
21
P1 (process)
T1 (thread)
T2
T3
P2 (process)
T4 T5
Memory space
Object, shared by T1, T2, T3
22
Threads in C#
• Threads in C# are done similar to Java, but with delegates.
• C# has a predefined delegate class ThreadStart for this purpose.• C# has predefined method Start() that starts the threads.• Java:
– Have thread objects containing method run()• C#:
– Have methods Xrun(), each of which is hooked to a separate thread using C#’s ThreadStart delegate. The names of these methods are programmer chosen.
– Each such method contains the code that is to be executed under a separate thread.
23
Threads in C#using System;using System.Threading;namespace ConsoleApplication4{class Test {static void printA () // to run on thread t1{ int count = 0;
while (true) { Console.Write("A"); count++; if (count % 10000 ==0) break; }
}
static void printB () // to run on thread t2{ int count = 0;
while (true) { Console.Write("B");count++; if (count % 10000 ==0) break; }
}
public static void Main () {
Thread t1 = new Thread(new ThreadStart(printA));Thread t2 = new Thread(new ThreadStart(printB));t1.Start(); t2.Start();
}}}
Hook the desired
methods to corresponding
threads.
Start the threads; method Start() is a predefined method in C#
24
Notice the interleaving …
25
Threads in C#using System;using System.Threading;
namespace ConsoleApplication3{
class SimpleThread{
// method ARun to run on thread t1public void ARun() {
for (int i=0; i<1000; i++) {
Console.Write(" [A "+i+ "]");}
}// method BRun to run on thread t2
public void BRun() {
for (int i=0; i<1000; i++) {
Console.Write(" [B "+i+ "]");}
}
26
Threads in C# … // method CRun to run on thread t3public void CRun(){
for (int i = 0; i < 1000; i++){
Console.Write(" [C "+i+ "]");}
}public void go() { // ThreadStart is a predefined C# delegate, for threads.ThreadStart threadDelegate1 = new ThreadStart( ARun);ThreadStart threadDelegate2 = new ThreadStart( BRun);ThreadStart threadDelegate3 = new ThreadStart( CRun);
Thread t1 = new Thread( threadDelegate1);Thread t2 = new Thread( threadDelegate2);Thread t3 = new Thread( threadDelegate3);
t1.Start();t2.Start();t3.Start();
}
static void Main (string[] args){
new SimpleThread().go();}
}}
Start the threads; method Start() is a predefined method in C#
Create the threads
Hook the desired
methods to corresponding threads
27
Notice the interleaving …
…
…
28
A multithreaded server• It is realistic that a server serves more than one client at
a time. (it is not realistic that a server serves one client from start to end, while other clients wait to be connected).
• A multithreaded server is a server which accepts clients’ requests for connection and accepts more than one client at a time. Consequently, the server serves the clients, concurrently.
• The concurrency is achieved by the server assigning each client to a separate thread, and then start (and run) all threads. (The multithreaded capabilities of the underlying operating system then allow for this multithreading to be achieved.)
29
Example
The client sends to the server a string (“A”, or “B”, or “C”), as many times as
specified in the textbox.
The server connects with the 3 clients,
receives the strings sent by each client and displays them, using 3
different threads.
30
Running
• To start the application, enter numbers in the textbox of each client and press the start button of the server and of all the clients.
31
Running … server started and it has displayed some of the received strings
Notice the interleaving …
32
A bit later …
Notice the interleaving …
33
The clients …
34
The code structure :: Server
serviceThreads is an array of Thread. Each client is associated with one
serviceThread.
35
The code :: Server
using System;using System.Drawing;using System.Collections;using System.ComponentModel;using System.Windows.Forms;using System.Data;
using System.Threading;using System.Net.Sockets;using System.IO;
namespace WindowsApplication2ServerMultiThreaded{
/// <summary>/// Summary description for Form1./// </summary>public class Form1 : System.Windows.Forms.Form{
private System.Windows.Forms.Button button1;private System.Windows.Forms.Button button2;private System.Windows.Forms.TextBox textBox1;/// <summary>/// Required designer variable./// </summary>private System.ComponentModel.Container components = null;
36
…public Form1(){
/// <summary>/// Clean up any resources being used./// </summary>protected override void Dispose( bool disposing ){
if( disposing ){
if (components != null) {
components.Dispose();}
}base.Dispose( disposing );
}
#region Windows Form Designer generated code/// <summary>/// Required method for Designer support - do not modify/// the contents of this method with the code editor./// </summary>private void InitializeComponent(){
//…
}#endregion
[STAThread]static void Main() {
Application.Run(new Form1());}
37
…
private NetworkStream [] socketStream = new NetworkStream[3];
private BinaryReader [] reader = new BinaryReader[3];
private BinaryWriter [] writer = new BinaryWriter[3];
private Thread readThread;
private Thread [] serviceThreads = new Thread[3];
private Socket [] conn = new Socket[3]; // the clients (assume 3 clients)
private void button1_Click(object sender, System.EventArgs e){
readThread = new Thread( new ThreadStart( RunServer ) );readThread.Start();
textBox1.Text = "calling run server";
}
One stream set per client.
One thread per client
Main server thread.
38
…public void RunServer() {
TcpListener listener ; try {
textBox1.Text += "\r\nTrying to establish server at port 5555";// create listener (the server)
listener = new TcpListener( 5555); // listens at port 5555textBox1.Text += "\r\nEstablished server at port 5555";
// server waits for connection
listener.Start();textBox1.Text += "\r\nestablished connection and waiting for client...";
// establish connection upon client's requestwhile ( true ) {
conn[0] = listener.AcceptSocket(); // establish connectiontextBox1.Text += "\r\n .... client 0 connected!!!";
conn[1] = listener.AcceptSocket(); // establish connectiontextBox1.Text += "\r\n .... client 1 connected!!!";
conn[2] = listener.AcceptSocket(); // establish connectiontextBox1.Text += "\r\n .... client 2 connected!!!";
// create communication steam
socketStream[0] = new NetworkStream( conn[0]);textBox1.Text += " opening communication stream ...0";
// attach a reader and a writer to the stream
socketStream[1] = new NetworkStream( conn[1]);textBox1.Text += " opening communication stream ...1";
socketStream[2] = new NetworkStream( conn[2]);textBox1.Text += " opening communication stream ...2";
writer[0] = new BinaryWriter( socketStream[0]);textBox1.Text += "\r\n ... ... opened writer 0 ";
Connect to each client.
Establish stream to
each client.
39
…writer[1] = new BinaryWriter( socketStream[1]);textBox1.Text += "\r\n ... ... opened writer 1 ";
writer[2] = new BinaryWriter( socketStream[2]);textBox1.Text += "\r\n ... ... opened writer 2 ";
reader[0] = new BinaryReader( socketStream[0]); textBox1.Text += "\r\n ... ... opened reader 0 ";
reader[1] = new BinaryReader( socketStream[1]); textBox1.Text += "\r\n ... ... opened reader 1 ";
reader[2] = new BinaryReader( socketStream[2]); textBox1.Text += "\r\n ... ... opened reader 2 ";
serviceThreads[0] = new Thread( new ThreadStart( ServiceA));serviceThreads[1] = new Thread( new ThreadStart( ServiceB));serviceThreads[2] = new Thread( new ThreadStart( ServiceC));
serviceThreads[0].Start();serviceThreads[1].Start();serviceThreads[2].Start();
} // while} //try catch ( Exception ex) {
MessageBox.Show( ex.ToString());}
} // end RunServer
Put each client on a separate thread.
Start the client threads.
40
…public void ServiceA ()
{int count=0;while (true) {
textBox1.Text += reader[0].ReadString() + ".";count++;
}}
public void ServiceB ()
{int count=0;while (true) {
textBox1.Text += reader[1].ReadString() + "." ;count++;
}}
public void ServiceC ()
{int count=0;while (true) {
textBox1.Text += reader[2].ReadString() + ".";
count++;}
}
Read incoming message from each client.
41
…/
private void button2_Click(object sender, System.EventArgs e){
readThread.Abort();serviceThreads[0].Abort();serviceThreads[1].Abort();serviceThreads[2].Abort();
Application.Exit();}
}}
42
The code structure :: Client A
43
The code :: Client Ausing System;using System.Drawing;using System.Collections;using System.ComponentModel;using System.Windows.Forms;using System.Data;
using System.Threading;using System.Net.Sockets;using System.IO;
namespace WindowsApplication2ClientA{
public class Form1 : System.Windows.Forms.Form{
private System.Windows.Forms.Button button1;private System.Windows.Forms.Button button2;private System.Windows.Forms.TextBox textBox1;private System.Windows.Forms.Label label1;private System.Windows.Forms.TextBox textBox2;/// <summary>/// Required designer variable./// </summary>private System.ComponentModel.Container components = null;
44
…//…
private void InitializeComponent(){
//…}
/// <summary>/// The main entry point for the application./// </summary>[STAThread]static void Main() {
Application.Run(new Form1());}
private Thread readThread;
private void button1_Click(object sender, System.EventArgs e){
readThread = new Thread( new ThreadStart ( RunClient));readThread.Start();
}
private NetworkStream clientStream;private BinaryWriter writer;private BinaryReader reader; Main client
thread.
45
…/public void RunClient() {
TcpClient client;try {
textBox1.Text = "Attempting connection to server ...";
client = new TcpClient( );client.Connect( "localhost", 5555);textBox1.Text += "\r\n" + "connection established!";
// establish a data exchange capable stream.
clientStream = client.GetStream(); // hookup reader and writer to streamsreader = new BinaryReader( clientStream) ;writer = new BinaryWriter( clientStream) ;int count = 0; int howmanyWrites = Int32.Parse( textBox2.Text);for (int i = 0; i < howmanyWrites; i++){
writer.Write("A");textBox1.Text += "\r\n" + " written message to server! " + count;count++;
} }catch ( Exception ee ) { }
} // RunClient
private void button2_Click(object sender, System.EventArgs e){
Application.Exit();}} // end class ClientA}
Establish communication
stream.
Connect to server.
Send message to server.
46
The code structure :: Client B
47
The code :: Client Busing System;using System.Drawing;using System.Collections;using System.ComponentModel;using System.Windows.Forms;using System.Data;
using System.Threading;using System.Net.Sockets;using System.IO;
namespace WindowsApplication2ClientB{
/// <summary>/// Summary description for Form1./// </summary>public class Form1 : System.Windows.Forms.Form{
private System.Windows.Forms.Button button1;private System.Windows.Forms.Button button2;private System.Windows.Forms.TextBox textBox1;private System.Windows.Forms.Label label1;private System.Windows.Forms.TextBox textBox2;/// <summary>/// Required designer variable./// </summary>private System.ComponentModel.Container components = null;
48
…//…
static void Main() {
Application.Run(new Form1());}
private Thread readThread;
private void button1_Click(object sender, System.EventArgs e){
readThread = new Thread( new ThreadStart ( RunClient));readThread.Start();
}
private void button2_Click(object sender, System.EventArgs e){
Application.Exit();}
private NetworkStream clientStream;private BinaryWriter writer;private BinaryReader reader;
int howManyWrites = 0;
49
…/public void RunClient() {
TcpClient client;try {
textBox1.Text = "Attempting connection to server ...";
client = new TcpClient( );client.Connect( "localhost", 5555);textBox1.Text += "\r\n" + "connection established!";
// establish a data exchange capable stream.
clientStream = client.GetStream();reader = new BinaryReader( clientStream) ;writer = new BinaryWriter( clientStream) ;
int count = 0;
howManyWrites = Int32.Parse( textBox2.Text);
for (int i = 0; i < howManyWrites; i++){
writer.Write("B");textBox1.Text += "\r\n" + " written message to server! " + count;count++;
} }catch ( Exception ee ) { }
}
} // end class ClientB}
50
The code structure :: Client C
51
The code :: Client Cusing System;using System.Drawing;using System.Collections;using System.ComponentModel;using System.Windows.Forms;using System.Data;
using System.Net.Sockets;using System.Threading;using System.IO;
namespace WindowsApplication2ClientC{
/// <summary>/// Summary description for Form1./// </summary>public class Form1 : System.Windows.Forms.Form{
private System.Windows.Forms.Button button1;private System.Windows.Forms.Button button2;private System.Windows.Forms.TextBox textBox1;private System.Windows.Forms.TextBox textBox2;private System.Windows.Forms.Label label1;/// <summary>/// Required designer variable./// </summary>private System.ComponentModel.Container components = null;
52
…//…static void Main() {
Application.Run(new Form1());}
private void Form1_Load(object sender, System.EventArgs e){
}private Thread readThread;
private void button1_Click(object sender, System.EventArgs e){
readThread = new Thread( new ThreadStart ( RunClient));readThread.Start();
}
private NetworkStream clientStream;private BinaryWriter writer;private BinaryReader reader;
53
…public void RunClient() {
TcpClient client;try {
textBox1.Text = "Attempting connection to server ...";
client = new TcpClient( );client.Connect( "localhost", 5555);textBox1.Text += "\r\n" + "connection established!";// establish a data exchange capable stream.
clientStream = client.GetStream(); reader = new BinaryReader( clientStream) ;writer = new BinaryWriter( clientStream) ;int count = 0; int howManyWrites = Int32.Parse( textBox2.Text);for (int i = 0; i < howManyWrites; i++){
writer.Write("C");textBox1.Text += "\r\n" + " written message to server! " + count;count++;
} }catch ( Exception ee ) { }
}
private void button2_Click(object sender, System.EventArgs e){
Application.Exit();}}}