Re: TCP/IP mehrere Clients

26/05/2008 - 06:20 von Peter Fleischer | Report spam
Gregor schrieb am 24. Mai 2008 um 12:22:01:


Wie funktioniert es wenn man eine Server-Anwendung mit TCP/IP schreibt das
mehrere Clients sich anmelden können?

Die Clients verbinden sich zwar(oder sie glauben es zumindest) aber ich
kann
keine Daten an sie schicken. Nur der erste Client der sich anmeldet wir
vom
Server registriert die anderen nicht?

Als Grundlage für mein Coding habe ich das Galileo TCP/IP Coding benutzt.



Wenn ein PC als Server für mehrere Clients funktionieren soll, dann muss er
pro Client Information über die Verbindung halten. Dazu musst du dir eine
Technologie erarbeiten und implementieren. Der Server muss dafür
"multi-client-fàhig" sein. Das bedeutet, dass der Server alle Clients
parallel bedienen muss. So etwas kann man nur über multithreading oder mit
asynchronen Arbeitsweisen realisieren.

Nachfolgend ein Beispiel für eine Punkt-zu-Punkt-Lösung, wo jede Seite
sowohl Server- als auch Client-Funktionalitàt besitzt. Damit ist ein
gleichrangiger beidseitiger Datenverkehr möglich (beide können den anderen
"anrufen").

Demo-Anwendung:

Option Strict On
Option Infer On

Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading

Imports ChatLib

Public Class Form1

Private tbin As New TextBox
Private lbout As New ListBox
Private myChat As New TCPChat(My.Settings.serveraddress, _
My.Settings.serverport, _
My.Settings.targetaddress, _
My.Settings.targetport)

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles MyBase.Load
Me.Text = "MiniChat"
Me.Controls.Add(lbout)
Me.Controls.Add(tbin)
With lbout
.Dock = DockStyle.Fill
End With
With tbin
.Dock = DockStyle.Top
AddHandler .KeyDown, AddressOf tbinKD
.Select()
End With
AddHandler myChat.Datareceived, AddressOf txtOut
End Sub

Private Sub tbinKD(ByVal sender As Object, _
ByVal e As KeyEventArgs)
If e.KeyCode = Keys.Enter Then
With CType(sender, TextBox)
If .Text.Length > 0 Then
myChat.SendData(.Text)
.Text = ""
End If
End With
End If
End Sub

Private Sub txtOut(ByVal txt As String)
lbout.Items.Add(String.Format("{0:HH:mm:ss}: {1}", Now, txt))
lbout.SelectedIndex = lbout.Items.Count - 1
End Sub

End Class

Dazu die Klasse in der ChatLib:

Option Infer On
Option Strict On

Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading

Public Class TCPChat
Event Datareceived(ByVal txt As String)

Public Sub SendData(ByVal txt As String)
Dim client = New TcpClient
With client
.Connect(IPAddress.Parse(_targetaddress), _targetport)
Dim data = System.Text.Encoding.ASCII.GetBytes(txt)
With client.GetStream()
.Write(data, 0, data.Length)
.Close()
End With
.Close()
End With
End Sub

Private server As TcpListener
Private clientrec As TcpClient
Private sc As SynchronizationContext

Private _targetaddress As String
Private _targetport As Integer

Public Sub New(ByVal serveraddress As String, ByVal serverport As Integer,
_
ByVal targetaddress As String, ByVal targetport As Integer)
sc = SynchronizationContext.Current
_targetaddress = targetaddress
_targetport = targetport
server = New TcpListener(IPAddress.Parse(serveraddress), serverport)
With server
.Start()
.BeginAcceptTcpClient(New AsyncCallback(AddressOf DoAccept), server)
End With
End Sub

Private Sub DoAccept(ByVal ar As IAsyncResult)
Dim sb As New StringBuilder
With CType(ar.AsyncState, TcpListener).EndAcceptTcpClient(ar)
With .GetStream()
Dim buf(256) As Byte
Dim i = .Read(buf, 0, buf.Length)
While i <> 0
sb.Append(System.Text.Encoding.ASCII.GetString(buf, 0, i))
i = .Read(buf, 0, buf.Length)
End While
End With
.Close()
End With
sc.Post(New SendOrPostCallback(AddressOf OnDatareceived), sb.ToString)
server.BeginAcceptTcpClient(New AsyncCallback(AddressOf DoAccept),
server)
End Sub

Private Sub OnDatareceived(ByVal state As Object)
RaiseEvent Datareceived(state.ToString)
End Sub

End Class

In der Config-Datei kann dann folgendes stehen:

<userSettings>
<Client.My.MySettings>
<setting name="serverport" serializeAs="String">
<value>5000</value>
</setting>
<setting name="serveraddress" serializeAs="String">
<value>127.0.0.1</value>
</setting>
<setting name="targetport" serializeAs="String">
<value>5000</value>
</setting>
<setting name="targetaddress" serializeAs="String">
<value>127.0.0.1</value>
</setting>
</Client.My.MySettings>
</userSettings>

In der Demo müsste noch eine Fehlerbehandlung eingebaut werden.

Die Klasse kann als Basis dienen für eine Klasse, die als Server mehrere
Clients bedient. Dazu müsste eine Liste der Information über die Clients
angeleget werden und im DoAccept die asynchrone Unterbrechung dem richtigen
Client zugeordnet werden. Um das aber genau zu implementieren, sollte zuerst
mal ein Ablaufplan erarbeitet werden, in dem genau festgelegt ist, wie das
Zusammenspiel ablaufen soll.


Viele Grüsse
Peter
 

Lesen sie die antworten

#1 Armin Zingler
26/05/2008 - 10:14 | Warnen spam
"Peter Fleischer" schrieb
Gregor schrieb am 24. Mai 2008 um 12:22:01:



Entschuldige die Frage, aber schreibst du die Fragen neuerdings selbst??
;-) Sehe keine Frage und auch keine "Reference" in deinem Beitrag.
Gleiches bei "JetJava" gestern.


Armin

Ähnliche fragen