TCP/IP na przykładzie .NET

Transkrypt

TCP/IP na przykładzie .NET
TCP/IP na przykładzie .NET
Pierwszy podstawowy program
 Uruchamiamy Visual Studio
 Zakładamy nowy projekt (ctrl+shift+n)
Pierwszy podstawowy program
 Z zakładki „tools” wybieramy odpowiednie kontrolki i
układamy na formatce
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
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;
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();
}
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);
}
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
Drugi program
 We właściwościach zmieniamy dodatkowo następujące
parametry:
•Text: 127.0.01
•Text: 2222
•ReadOnly: true
•Enabled: false
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;
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);
}
}
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);
}
}
}
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);
}
}
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);
}
}
}
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);
}
}
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);
}
}
}
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();
}
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ń.

Podobne dokumenty