Frank Dzaebel, erstellt am: 25.07.2008,
zuletzt geändert: 10.05.2009
Kategorie: Client-Server,
.NET-Version: 2.0/3.5, [Download
.NET 3.5] [Download
.NET 2.0] [Download
.NET 2.0 Neuverbinden] [Download .NET 2.0 Server nicht UI-blockierend.]
Ein einfaches Beispiel einer synchronen Socket-Kommunikation mit TcpClient und
TcpListener. Dabei
wird in den angehängten Downloads unter anderem auch deutlich, dass synchrone Sockets
nicht das User Interface blockieren müssen, wenn man die Methoden in Threads ausführt.

Während hier nur ein sehr rudimentärer Überblick über
synchrone Kommunikation gegeben wird, kann ich folgendes Tutorial empfehlen, das
typische Fragestellungen aus diesem Bereich und zusätzlich asynchrones Handling
mit aufgreift: [TCP/IP Socket-Programmierung in C#
], es gibt auch einen
Download eines C#-Projektes, für den Sie sich aber dort registrieren
müssen. Dieser Download enthält folgende Teil-Projekte: [Client, DomainTest, HttpClient,
HTTPGet, MAPIComponent, MAPITest, MyHost, Ping, PingAsync, PingClass, ReceiveUDPMessage,
SendMail, SendMailAsync, SendUDPAsync, Server, TcpClientClass, TCPClientSocket,
TcpEchoClientAsync, TcpEchoServerAsync, TcpListenerClass, TCPServerSocket, UDPClientClass]
Arbeiten Sie später für UTF8Encoding mit Decodern: [TCPIP Sockets in C# Practical Guide for Programmers -TranscodeServer.cs] [als freies EBook downloaden] um die ggf. mögliche Fragmentierung von Zeichen mit mehreren
Bytes zu korrigieren.
Client.cs:
using System;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Threading;
using System.Security.Principal;
namespace Client
{
public partial class Client : Form
{
public Client()
{
InitializeComponent();
}
TcpClient tcpClient;
Stream tcpStream;
Properties.Settings Props = Properties.Settings.Default;
const int maxBuffer = 100;
/// <summary> C L I E N T </summary>
private void Form1_Load(object sender, EventArgs e)
{
Thread.Sleep(1000); // zu Demo-Zwecken: Zeit für Server-Start
txtÜbertragungstext.Text = WindowsIdentity.GetCurrent().Name;
IPAddress ipAdresse = null;
try
{
this.Show(); Application.DoEvents();
GetIpAdresse(ref ipAdresse, Dns.GetHostName());
Melde("Der Client ist gestartet auf " + ipAdresse.ToString() + ":" + Props.Port + "\r\n");
tcpClient = new TcpClient();
Melde("Verbinde mit Server .....");
tcpClient.Connect(ipAdresse, Props.Port);
Melde("Mit Server verbunden!");
Melde("Bitte den Text eingeben, " +
"der übertragen werden soll und Enter drücken.");
}
catch (Exception exp)
{
Melde(exp.Message);
return;
}
}
private IPAddress GetIpAdresse(ref IPAddress ipAdresse, string hostName)
{
IPAddress[] ipAdressen = Dns.GetHostEntry(hostName).AddressList;
foreach (IPAddress ip in ipAdressen)
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
ipAdresse = ip; break;
}
if (ipAdresse == null)
throw new Exception("Keine IPV4-IP auflösbar.");
return ipAdresse;
}
private void Melde(string msg)
{
txtMeldung.AppendText(msg + "\r\n");
}
private void btnOK_Click(object sender, EventArgs e)
{
try
{
tcpStream = tcpClient.GetStream();
UTF8Encoding encoding = new UTF8Encoding();
//Arbeiten Sie hier später über Decoder! Thema Fragmentierung von Doppelbytes.
byte[] ba = encoding.GetBytes(txtÜbertragungstext.Text);
Melde("\r\nÜbertrage zum Server : \"" + txtÜbertragungstext.Text + "\"");
tcpStream.Write(ba, 0, ba.Length);
byte[] buffer = new byte[maxBuffer];
int gelesen = tcpStream.Read(buffer, 0, maxBuffer);
string empfangen = encoding.GetString(buffer,0,gelesen);
Melde("Empfangen: \"" + empfangen + "\"");
}
catch (Exception exp) { Melde(exp.Message); return; }
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (tcpStream != null) tcpStream.Close();
if (tcpClient != null) tcpClient.Close();
}
}
}
Server.cs:
using System;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
namespace Server
{
public partial class Server : Form
{
public Server()
{
InitializeComponent();
}
Properties.Settings Props = Properties.Settings.Default;
Socket socket;
TcpListener tcpListener;
const int maxBuffer = 100;
/// <summary> S E R V E R </summary>
private void Form1_Load(object sender, EventArgs e)
{
IPAddress ipAdresse=null;
try
{
this.Show(); Application.DoEvents();
GetIpAdresse(ref ipAdresse, Dns.GetHostName());
tcpListener = new TcpListener(ipAdresse, Props.Port);
tcpListener.Start();
}
catch (Exception exp)
{
Melde("Beim Versuch der Auflösung der Addresse: " +
ipAdresse.ToString() + " enstand folgender Fehler:\r\n" + exp.Message);
return;
}
try
{
Melde("Der Server ist gestartet auf Port : " + Props.Port);
Melde("Der lokale Endpunkt ist :" + tcpListener.LocalEndpoint);
Melde("Warte auf Verbindung eines Clients ...");
socket = tcpListener.AcceptSocket();
Melde("Client-Verbindung akzeptiert von: " + socket.RemoteEndPoint);
int received;
byte[] buffer;
string empfangen;
do
{
buffer = new byte[maxBuffer];
received = socket.Receive(buffer);
if (received == 0)
{
Server_FormClosing(this, new FormClosingEventArgs(CloseReason.None, false));
this.Close(); return;
// wenn der Client "" sendet, soll der Server beenden. (nur als Beispiel)
}
UTF8Encoding encoding = new UTF8Encoding();
empfangen = encoding.GetString(buffer, 0, received);
Melde("Vom Client empfangen : \"" + empfangen + "\"");
string toSend = "ACK";
socket.Send(encoding.GetBytes(toSend));
Melde("\r\nSende \"" + toSend + "\" - Meldung");
}
while (received != 0);
}
catch (Exception exp)
{
Melde(exp.Message);
return;
}
}
private void Melde(string msg)
{
txtMeldung.AppendText(msg + "\r\n");
}
private IPAddress GetIpAdresse(ref IPAddress ipAdresse, string hostName)
{
IPAddress[] ipAdressen = Dns.GetHostEntry(hostName).AddressList;
foreach (IPAddress ip in ipAdressen)
if (ip.AddressFamily == AddressFamily.InterNetwork)
{ ipAdresse = ip; break;
}
if (ipAdresse == null)
throw new Exception("Keine IPV4-IP auflösbar.");
return ipAdresse;
}
private void Server_FormClosing(object sender, FormClosingEventArgs e)
{
if (socket != null) socket.Close();
if (tcpListener != null) tcpListener.Stop();
}
}
}