| |
VB.NET - Ein- und UmsteigerRe: Probleme mit TCP | | | Autor: Preisser | Datum: 22.06.11 18:59 |
| Hallo,
vielleicht solltest du auch im Server die aufgetretenen Exceptions nicht einfach ignorieren lassen, sondern eine Ausgabe mit einbauen, wenn eine Exception auftritt (Art der Exception, Fehlermeldung und Stacktrace).
Bist du dir auch sicher, dass du den SyncLock richtig verwendest? Beispielsweise in ListenToConnection() siehst du zuerst in der Liste nach, ob der Client schon vorhanden ist, machst dann noch was anderes und fügst den Client dann hinzu. Da der Codeblock eine logische Einheit/Transaktion ist, muss entsprechend ein Synclock von der For Each-Schleife bis zu PClients.Add(c) gehen, und nicht z.b. zwei getrennte SyncLocks (einer bei der For Each-Schleife und einer bei dem PClients.Add). Sonst könnte es ja passieren, dass ein Client trotzdem doppelt drin ist, wenn die Threads grade ungünstig laufen.
Übrigens liefert StreamReader.ReadLine() null (Nothing), wenn das Streamende erreicht ist. Es wäre besser, nach den Rückgabewert auf Nothing zu testen, anstatt darauf zu vertrauen, dass bei einem späteren Zugriff auf den String eine NullReferenceException geworfen wird.
Beitrag wurde zuletzt am 22.06.11 um 19:08:31 editiert. | |
Probleme mit TCP | | | Autor: Daddaaff | Datum: 22.06.11 16:34 |
| Hallo, ich bin mit meiner Server-Client_Anwendung schon einiges weiter, jedoch plagen mich manche Kleinigkeiten wofür ich einfach keine Ursache finden kann. Machmal entstehen doppelte Verbindungen, es passieren unerklärlich Verbindungsabbrüche, wonach ein erneutes Verbind erst nach dem Neustart der Anwendungen möglich ist und manchmal bleibt die Anwendung einfach stehen. Kann sich das mal einer ansehen, ob ich da wo einen Dankfehler habe?
Start des Servers:
Try
PServer = New TcpListener(PIPendpoint)
PServer.Start()
While True
PClient = New TcpClient
Dim c As New Connection
TXT("Warte auf neue Verbindung")
PClient = PServer.AcceptTcpClient
c.stream = PClient.GetStream
c.streamw = New StreamWriter(c.stream)
c.streamr = New StreamReader(c.stream)
Dim t As New Threading.Thread(AddressOf ListenToConnection)
t.Start(c)
End While
Catch ex As Exception
End Try Hier die ListenToConnection():
Dim Info As String
Dim Infos() As String
Try
c.streamw.WriteLine(ID & "||" & PConnectable)
c.streamw.Flush()
Info = c.streamr.ReadLine
Infos = Split(Info, "||")
c.ClientID = Infos(0)
For Each cl As Connection In PClients 'Um doppelte Verbindungen zu
' vermeiden
Dim cIP() As String
cIP = Split(cl.ClientID.ToString, ":")
If cIP(0) = Infos(0) Then
TXT(cIP(0) & " bereits verbunden")
c.stream.Close()
Exit Sub
Else
TXT(cIP(0) & " noch nicht verbunden")
End If
Next
c.ClientIP = PClient.Client.RemoteEndPoint.ToString
c.Servant = Infos(1)
PClients.Add(c)
TXT("Neuer Client: " & c.ClientID)
Dim SplitMSG() As String
Dim NewTTL As Integer
Dim FullMSG As String
While True
FullMSG = c.streamr.ReadLine
MSG(FullMSG)' Da passieren alle möglichen Sachen, jedoch nicht
' von belangen
End While
Catch
Try
PClients.Remove(c)
TXT(c.ClientID & " hat die Verbindung abgebrochen")
Catch ex As Exception
End Try
End Try So Connecte Ich:
Function Connect(ByVal IP As String)
Try
For Each c As Connection In PClients 'Um doppelte Verbindungen zu
' vermeiden
Dim cIP() As String
cIP = Split(c.ClientIP.ToString, ":")
If cIP(0) = IP Then
TXT(cIP(0) & " bereits verbunden")
Return False
Exit Function
Else
TXT(cIP(0) & " noch nicht verbunden")
End If
Next
TXT("Verbinde zu " & IP)
PClient = New TcpClient
PClient.Connect(IP, PPort)
If PClient.Connected Then
Dim c As New Connection
c.stream = PClient.GetStream
c.streamw = New StreamWriter(c.stream)
c.streamr = New StreamReader(c.stream)
Dim t As New Threading.Thread(AddressOf ListenToConnection)
t.Start(c)
End If
Catch ex As Exception
TXT("EX: Verbindung konnte nicht hergestellt werden")
Return False
End Try
Return True
End Function Wo könnte hier ein Fehler liegen?
Vielen Dank für eure Hilfe! | |
Re: Probleme mit TCP | | | Autor: Code_mancer | Datum: 22.06.11 16:40 |
| Beim schnellen drüber sehen vermisse ich sowas wie ein synclock o.ä.
Das heisst: es könnte sein, dass zwei von dir gestartete threads gleichzeitig auf die selben Objekte zugreifen und das ergibt gerne mal pures Chaos.
--------------------
Ich habe keine besondere Begabung, sondern bin nur leidenschaftlich neugierig.
- Albert Einstein | |
Re: Probleme mit TCP | | | Autor: Daddaaff | Datum: 22.06.11 16:59 |
| So etwas?
SyncLock PClients
PClients.Add(c) ' und fügen sie der liste der clients hinzu.
End SyncLock Wo würde ich das noch benötigen, ausser bei Arbeiten mit der Liste? | |
Re: Probleme mit TCP | | | Autor: Daddaaff | Datum: 22.06.11 17:33 |
| Ok, Danke für die Hilfe.
Was macht eigentlich ein Thread, wenn er versucht auf eine Datei zuzugreifen, die mit SyncLock gesperrt ist? Wartet er einfach bis sie wieder frei ist? | |
Re: Probleme mit TCP | | | Autor: Code_mancer | Datum: 22.06.11 17:41 |
| In die Richtung habe ich noch nicht mit Threads gearbeitet, aber ich denke, da verläuft es ähnlich. Schließlich manipulierst du ja nicht direkt die Datei, sondern gibst immer erst einem Objekt den Auftrag, diese Datei zu manipulieren. Da SyncLock den Zugriff auf das Objekt unterbindet, müsste ein weiterer Thread "vorm" Lock warten, bis der bereits arbeitende Thread den Lock-Bereich verlassen hat.
--------------------
Ich habe keine besondere Begabung, sondern bin nur leidenschaftlich neugierig.
- Albert Einstein | |
Re: Probleme mit TCP | | | Autor: Daddaaff | Datum: 22.06.11 17:56 |
| Ich habe nun alle Arbeiten mit der Liste über SyncLock gesichert, jedoch bestehen meine Probleme weiterhin! Vorallem das ich vor einem Erneuten verbinden die Anwendungen erst neu starten muss. Ich weis jedoch nicht ob es am Server oder am Client liegt. | |
Re: Probleme mit TCP | | | Autor: Daddaaff | Datum: 22.06.11 19:54 |
| Normalerweise behandle ich die Exeptions. So bin ich auch darauf gekmmen, dass manchmal beim Senden don Daten ein fehler auftritt, unzwar das die Gegenstelle di3e Verbindung beendet hat. Aber ich heb eben bisher einen Verbindungsabbruch durch eine Exeption erkannt. Hoffentlich erledigt sich das, wenn ich auf nothing prüfe.
Ok, bie ListenToConnection habe ich nun das SyncLock auf den ganzen block ausgeweitet. Bei Connect allerding würde das bedeuten das die Liste sehr lange gespert ist, da es mitunter - vorallem bei nicht zustande kommender Verbindung - mehrer Sekunden dauert.
Wenn ich nun mit StreamReader.ReadLine() = Nothing einen Verbindungsabbruch erkannt habe, wie sollte ich die Verbindung ordentlich schließen? Ich habe zuvor gar nichts unternommen und versuche nun geradeTry
c.stream.Close()
c.Client.Client.Close()
TXT(c.ClientID & " hat die Verbindung abgebrochen")
PClients.Remove(c)
Catch ex As Exception
End Try Das Try ist dafür gedacht, dass es ja sein kann, das ein Client noch gar nicht in der Liste war und somit der Versuch ihn daraus zu löschen eine Exeption verursacht. Liege ich damit richtig?
Hier übrigens meine Connection:
Structure Connection
Dim stream As NetworkStream
Dim streamw As StreamWriter
Dim streamr As StreamReader
Dim ClientID As String 'Identifikation des clients.
Dim ClientIP As String 'IP des CLients
Dim Client As TcpClient
End Structure
Beitrag wurde zuletzt am 22.06.11 um 19:55:28 editiert. | |
Re: Probleme mit TCP | | | Autor: Preisser | Datum: 22.06.11 20:21 |
| Hallo,
wie meinst du das, mit Connect()? Du müsstest halt eine Art Verbindung eintragen in die Liste (also hier z.B. ein Connection-Element), und dir merken, dass diese Verbindung noch nicht hergestellt wurde o. ä. Dann musst du nicht so lange synchronisieren.
Es stimmt schon, dass bei einem Verbindungsabbruch (also wenn die Verbindung nicht ordnungsgemäß geschlossen wurde) eine Exception aufritt, aber wenn die Verbindung auf normalen Weg geschlossen wird, sollte keine auftreten; stattdessem müsste der Reader das Erreichen des Streamendes melden (mit Rückgabewert Nothing bei ReadLine()).
Wenn du aus einer Liste ein Element entfernst, das nicht vorhanden ist, gibt die .Remove()-Methode false zurück, ohne eine Exception zu werfen.
Nur müsstest du wiederrum das PClients.Remove(c) mit einem SyncLock versehen. | |
Re: Probleme mit TCP | | | Autor: Daddaaff | Datum: 22.06.11 20:28 |
| Ok, wenn nun der ein Seite offline geht, muss muss ich die ausser PClients.Remove(c) die Verbindung noch weiter beenden? Eben mit c.stream.Close() oder c.Client.Client.Close() - also den Stream oder den TCPClient schließen?
Ich habe nun bemerkt, das anfangs die Datenübertregung funktioniert. Ich sehe das gesendet und Empfangen wird. Aber schon nach kurzer Zeit, wird zwar gesendet, aber nichtmehr empfangen. Jedoch tritt kein Exeption auf.... | |
Re: Probleme mit TCP | | | Autor: Preisser | Datum: 22.06.11 20:40 |
| Hallo,
das weiß ich nicht genau, ich denke, dass es reichen müsste einfach den Stream oder das Socket zu schließen.
Wo genau wird nichts mehr empfangen, beim Server oder beim Client? | |
Re: Probleme mit TCP | | | Autor: Daddaaff | Datum: 22.06.11 20:45 |
| Soviel ich mitbekommen habe, beide! Meine einzige Idee wäre das die ListenToConnection() irgendwo hängen bleibt und somit den Stream natürlich nicht mehr liest! Jedoch konnt eich bisher nichts finden. | |
Re: Probleme mit TCP | | | Autor: Daddaaff | Datum: 22.06.11 20:57 |
| Ich bekomme nun auf jeder Seite eine Exeption!
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.IO.StreamReader.ReadBuffer()
at System.IO.StreamReader.ReadLine()
at Server.Main1.ListenToConnection(Connection c)
und dort wo ich Debugge
System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
--- End of inner exception stack trace ---
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.IO.StreamReader.ReadBuffer()
at System.IO.StreamReader.ReadLine()
at Server.Main1.ListenToConnection(Connection c) in E:\Projekte\P2P\Server\MainS.vb:line 1281
EDIT: Ich denke das der Fehler irgendwo in der ListenToConnection() liegt!
Sub ListenToConnection(ByVal c As Connection)
Dim Info As String
Dim Infos() As String
Try
c.streamw.WriteLine(PNodeID & "||" & PConnectable)
c.streamw.Flush()
Info = c.streamr.ReadLine
If Info = Nothing Then
'CloseClient(c)
TXT("Eine Verbindung wurde vorzeitig beendet")
Else
Infos = Split(Info, "||")
c.ClientID = Infos(0)
SyncLock PClients
For Each cl As Connection In PClients
Dim cIP() As String
cIP = Split(cl.ClientID.ToString, ":")
If cIP(0) = Infos(0) Then
c.stream.Close()
Exit Sub
End If
Next
c.ClientIP = PClient.Client.RemoteEndPoint.ToString
PClients.Add(c) ' und fügen sie der liste der clients hinzu.
End SyncLock
TXT("Neuer Client: " & c.ClientID)
Dim SplitMSG() As String
Dim NewTTL As Integer
Dim FullMSG As String
While True
FullMSG = c.streamr.ReadLine
If FullMSG = Nothing Then
TXT("Die Verbindung zu " & c.ClientID & " wurde" & _
"beendet")
CloseClient(c)
Else
TXT(FullMSG)
SplitMSG = Split(FullMSG, PFullMSGSplit)
.
.
.
MSG(SplitMSG(3), c.ClientID, SplitMSG(4))
End If
.
.
.
End If
End While
End If
Catch ex As Exception
TXT(ex.ToString)
End Try
End Sub
Beitrag wurde zuletzt am 22.06.11 um 21:11:00 editiert. | |
Re: Probleme mit TCP | | | Autor: Preisser | Datum: 22.06.11 21:18 |
| Hallo,
also du prüfst jetzt zwar, ob der Rückgabewert von ReadLine == Nothing ist, udn schließt dann auch den Stream; allerdings verlässt du ja dann die Schleife nicht und versuchst wieder, etwas zu lesen, was die ObjectDisposedException erklären dürfte. Nachdem du den Client getrennt hast, müsstest du auch die While-Schleife verlassen (Exit While).
Die andere Exception tritt normalerweise auf, wenn die Gegenseite die Verbindung hart geschlossen hat (z.B. wenn man den Prozess im Taskmanager beendet o.ä.). Dadurch weißt du dann auch, dass die Gegenseite die Verbindung getrennt hat. | |
Re: Probleme mit TCP | | | Autor: Daddaaff | Datum: 22.06.11 22:02 |
| Habe den Übeltäter identifizieren können! c.ClientIP = PClient.Client.RemoteEndPoint.ToString muss natürlich c.ClientIP = c.Client.Client.RemoteEndPoint.ToString lauten.
Mal sehen ob nun alles funktioniert wie es soll!
Danke für eure unterstützung! | |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
vb@rchiv CD Vol.6 vb@rchiv Vol.6
Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
Online-Update-Funktion Entwickler-Vollversionen u.v.m.Jetzt zugreifen Tipp des Monats Neu! sevDTA 3.0 Pro
SEPA mit Kontonummernprüfung
Erstellen von SEPA-Dateien mit integriertem BIC-Verzeichnis und Konto- nummern-Prüfverfahren, so dass ungültige Bankdaten bereits im Vorfeld ermittelt werden können. Weitere Infos
|