background image

TCP/IP na przykładzie .NET 

background image

Pierwszy podstawowy program   

Uruchamiamy Visual Studio 

Zakładamy nowy projekt (ctrl+shift+n) 

background image

Pierwszy podstawowy program   

Z zakładki „tools” wybieramy odpowiednie kontrolki i 
układamy na formatce 

background image

Pierwszy podstawowy program   

We właściwościach zmieniamy następujące parametry 

•Minimum size: 300;300 
•Name: textBoxAdres 
•Name: textBoxPort 
•Name: buttonPolacz 
•Name: buttonSerwuj 
•Name: richTextBoxOdbior 
•Name: textBoxKomunikat 
•Name: buttonWyslij 
•Anchor: Top, Left, Right 
•Anchor: Top 
•Anchor: Top, Bottom, Left, Right 
•Anchor: Bottom, Left, Right 

background image

Pierwszy podstawowy program   

Używamy dodatkowej przestrzeni nazw: 

using 

System.Net.Sockets; 

using 

System.Net; 

 

W klasie Form1 dodajemy zmienne 

  

private 

TcpListener tcpLsn; 

private 

Encoding ASCII = Encoding.ASCII; 

//kodowanie 

Socket s; 

 

background image

Pierwszy podstawowy program   

Dodajemy obsługę guzika „Serwuj”  
 

private void 

buttonSerwuj_Click

(object 

sender

EventArgs 

e) 

   { 

   tcpLsn = 

new 

TcpListener(IPAddress.Parse(textBoxAdres.Text),

  

int.

Parse(textBoxPort.Text)); 

//zainicjiuj listenera na podanym     

 

 

 

 

  porcie i adresie 

   

tcpLsn.Start(); 

   

Socket 

sckt = tcpLsn.AcceptSocket(); 

//funkcja blokująca do czasu  

 

 

 

 

       nadejścia połączenia 

   Byte

[] odebraneBajty = 

new 

Byte

[100]; 

   int 

ret = sckt.Receive(odebraneBajty, odebraneBajty.Length, 0); 

   string 

tmp = 

null

   tmp = System.Text.

Encoding

.ASCII.GetString(odebraneBajty); 

   

if 

(tmp.Length > 0) 

      { 
      richTextBoxOdbior.AppendText(tmp); 
      } 
  tcpLsn.Stop(); 
  } 

 

background image

Pierwszy podstawowy program   

Dodajemy obsługę guzika „Połącz” oraz „Wyślij” 

 

private void 

buttonPolacz_Click(

object 

sender,

 

EventArgs e

 { 
 s =

 

new 

Socket

(

AddressFamily

.InterNetwork,

 SocketType

.Stream,

 

ProtocolType

.Tcp); 

 IPAddress 

hostadd

 = IPAddress

.Parse(textBoxAdres.Text); 

 

int 

port =

 

Int32

.Parse(textBoxPort.Text); 

 IPEndPoint 

EPhost = 

new 

IPEndPoint

(hostadd, port); 

 s.Connect(EPhost);  
 } 
 

private void 

buttonWyslij_Click(

object 

sender,

 

EventArgs e

 { 

 string 

str = textBoxKomunikat.Text; 

 

Byte

[] byteData = ASCII.GetBytes(str.ToCharArray()); 

 s.Send(byteData, byteData.Length, 0); 
 } 

 

 

background image

Pierwszy podstawowy program   

Pierwsza działająca wersja ale ma poważne wady: 

Usługa zadziała tylko raz (przydałaby się pętla) 

Jest kilka blokujących funkcji przez co tracimy kontrolę 
w głównej formatce (przydałby się osobny wątek) 

Brak obsługi błędów 

Brak możliwości wielokrotnego podłączania się i 
odłączania 

Brak uodpornienia interfejsu na głupie zachowania 
 

2 wersja programu część powyższych ma wyeliminowane 

background image

Drugi program 

 

We właściwościach zmieniamy dodatkowo następujące 
parametry: 

•Text: 127.0.01 
•Text: 2222 
•ReadOnly: true 
•Enabled: false 

background image

Drugi program 

 

public delegate void 

DodajKolorowyTekst

(

RichTextBox 

RichTextBox,

 

string 

Text,

 

Color 

kolor); 

        

private void 

DodajKolorowyTekstFn(

RichTextBox 

rtb,

 

string 

tekst,

 

Color 

kolor) 

        { 
            

var

 StartIndex = rtb.TextLength; 

            rtb.AppendText(tekst); 
            

var

 EndIndex = rtb.TextLength; 

            rtb.Select(StartIndex, EndIndex - StartIndex); 
            rtb.SelectionColor = kolor; 
        } 

 
private void 

AppendColoredText(

RichTextBox 

RTB,

 

string 

Text,

 

Color 

kolor) 

        { 
            

if

 (RTB.InvokeRequired) 

            { 
                RTB.Invoke(

new

 

DodajKolorowyTekst

(DodajKolorowyTekstFn), RTB, Text, kolor); 

            } 
            

else 

            { 
                DodajKolorowyTekstFn(RTB, Text, kolor); 
            } 
        } 

 
private 

Encoding 

ASCII =

 Encoding

.ASCII;

 

//kodowanie 

private 

TcpListener 

tcpLsn; 

Socket 

s; 

Thread 

tcpThd; 

background image

Drugi program 

 

 

private void 

buttonSerwuj_Click(

object 

sender, 

EventArgs 

e) 

    { 

    

if 

(buttonSerwuj.Text == "Stop")  

        { 

        

try 

            { 
            

tcpThd.Abort(); 

            tcpLsn.Stop(); 
            buttonSerwuj.Text = 

"Serwuj"

            

buttonPolacz.Enabled = 

true

            

textBoxAdres.Enabled =

 true

            

textBoxPort.Enabled = 

true

            

        catch 

(

Exception 

ex) 

            { 
            AppendColoredText(richTextBoxOdbior, "

Bład odłączenia: \n

",

 

Color

.Red); 

            AppendColoredText(richTextBoxOdbior, ex.Message +

 

"\n", 

Color

.Red); 

            } 
        } 

background image

Drugi program 

 

  else 

       { 
       

try 

           { 

 

 

//zainicjiuj listenera na podanym porcie i adresie 

 

 

tcpLsn = 

new 

TcpListener

(

IPAddress

.Parse(textBoxAdres.Text),

int.

Parse(textBoxPort.Text));

  

 

 

tcpLsn.Start(); 

           AppendColoredText(richTextBoxOdbior, "

Słucham na: 

",

 

Color

.Red); 

           AppendColoredText(richTextBoxOdbior, tcpLsn.LocalEndpoint.ToString() + "

\n

",

 

Color

.Blue); 

 

        //przygotowanie wątku czekającego na połączenia

 

           tcpThd = 

new 

Thread

(

new 

ThreadStart

(WaitingForClient));  

 

 

tcpThd.Start(); 

//wystartowanie wątku czekającego na połączenia 

           

buttonSerwuj.Text = 

"Stop"; 

//zmiana nazwy 

           

buttonPolacz.Enabled =

 

false

;

 

//zmiany stanów 

           

textBoxAdres.Enabled = 

false

;

  

           

textBoxPort.Enabled = 

false

           } 
       catch 

(

Exception 

ex) 

           { 
           AppendColoredText(richTextBoxOdbior,

 

"Bład połączenia: \n"

,

 

Color

.Red); 

           AppendColoredText(richTextBoxOdbior, ex.Message + 

"\n"

,

 

Color

.Red); 

           } 
       } 

background image

Drugi program 

 

 

public void 

WaitingForClient() 

        { 

            while 

(

true

            

                try 
                

                    

Socket 

sckt = tcpLsn.AcceptSocket(); 

                    Byte

[] odebraneBajty = 

new 

Byte

[textBoxKomunikat.MaxLength]; 

                    

AppendColoredText(richTextBoxOdbior,

 

"Podłączony klient z: "

,

 

Color

.Red); 

                    

AppendColoredText(richTextBoxOdbior, sckt.RemoteEndPoint.ToString() + 

"\n"

,

 

Color

.Blue); 

                    

while 

(sckt.Connected) 

                    { 

                        try 
                        

                            int 

ret = sckt.Receive(odebraneBajty, odebraneBajty.Length, 0); 

                            if 

(ret > 0) 

                            { 

                                string 

tmp = 

null

                                odebraneBajty[ret] = 0; 
                                tmp = System.Text.

Encoding

.ASCII.GetString(odebraneBajty); 

                                

if (

tmp.Length > 0) 

                                { 
                                    AppendColoredText(richTextBoxOdbior, tmp, 

Color

.Black); 

                                    AppendColoredText(richTextBoxOdbior, 

"\n"

,

 

Color

.Black); 

                                } 
                            } 

background image

Drugi program 

 

 
                            

else 

                            { 
                                AppendColoredText(richTextBoxOdbior, 

"Błąd odbioru\n"

,

 

Color

.Red); 

                                

break

                            } 
                        } 

                        catch 

(

Exception 

ex) 

                        { 
                            

if 

(!sckt.Connected) 

                            { 
                                AppendColoredText(richTextBoxOdbior, 

"Połaczenie zerwane\n"

,

 

Color

.Red); 

                                AppendColoredText(richTextBoxOdbior, ex.Message + 

"\n"

,

 

Color

.Red); 

                                

break

                            } 
                        } 
                    } 
                } 

                catch 

(

Exception 

ex) 

                { 

                    MessageBox

.Show("Koniec: " + ex.Message); 

                } 
            } 
        } 

background image

Drugi program 

 

 

private void 

buttonPolacz_Click(

object 

sender,

 

EventArgs 

e) 

        { 

            

if 

(buttonPolacz.Text == 

"Odłącz"

            { 

                

try 

                

                    s.Disconnect(

false

); 

                    textBoxKomunikat.Enabled = 

false

                    buttonWyslij.Enabled = 

false

                    buttonSerwuj.Enabled = 

true

                    textBoxAdres.Enabled = 

true

                    textBoxPort.Enabled = 

true

                    

buttonPolacz.Text = 

"Połacz"

                    AppendColoredText(richTextBoxOdbior, 

"Odłączono \n"

,

 

Color

.Red); 

                } 

                

catch 

(

Exception 

ex) 

                { 
                    AppendColoredText(richTextBoxOdbior, 

"Błąd odłaczenia: \n"

,

 

Color

.Red); 

                    AppendColoredText(richTextBoxOdbior, ex.Message + 

"\n"

,

 

Color

.Red); 

                } 
            } 

background image

Drugi program 

 

 

else 

            { 

                try 

                { 
                    s = 

new 

Socket

(

AddressFamily

.InterNetwork, 

SocketType

.Stream,

 ProtocolType

.Tcp); 

                    IPAddress 

hostadd = 

IPAddress

.Parse(textBoxAdres.Text); 

                    

int 

port =

 

Int32

.Parse(textBoxPort.Text); 

                    IPEndPoint 

EPhost = 

new 

IPEndPoint

(hostadd, port); 

                    s.Connect(EPhost); 
 

                   

if (

s.Connected) 

                    { 
                        textBoxKomunikat.Enabled = 

true

                        buttonWyslij.Enabled = 

true

                        buttonSerwuj.Enabled = 

false

                        textBoxAdres.Enabled = 

false

                        textBoxPort.Enabled = 

false

                        buttonPolacz.Text = 

"Odłącz"

                        AppendColoredText(richTextBoxOdbior,

 "Podłączono \n"

,

 

Color

.Red); 

                    } 
                } 

                

catch 

(

Exception 

ex) 

                { 
                    AppendColoredText(richTextBoxOdbior,

 

"Błąd podłaczenia: \n"

,

 

Color

.Red); 

                    AppendColoredText(richTextBoxOdbior, ex.Message + 

"\n"

,

 

Color

.Red); 

                } 
            } 
        } 

background image

Drugi program 

 

 

private void 

buttonWyslij_Click(

object 

sender,

 

EventArgs 

e) 

        { 

            

if 

(s != null && s.Connected)

 

//jeżeli jesteśmy podłączeni to wysyłamy  

            { 

                

string 

str = textBoxKomunikat.Text; 

                

Byte

[] byteData = ASCII.GetBytes(str.ToCharArray()); 

                s.Send(byteData, byteData.Length, 0); 
            } 
        } 

 
 
 

 private void 

Form1_FormClosed(

object 

sender,

 

FormClosedEventArgs e

        { 

            

if

 (tcpThd != 

null

                tcpThd.Abort(); 
            

if

 (tcpLsn != 

null

                tcpLsn.Stop(); 
        } 

background image

Trzecia wersja programu 

Wprowadzono następujące modyfikacje: 

Obsługa wielu klientów jednocześnie (serwer 
wielowątkowy) 

Wydzielenie obsługi połączeń do osobnej klasy 

Dzięki serializacji i deserializacji przekazywanie całych 
obiektów 

Informowanie za pomocą zdarzeń.