"Server.AcceptTcpClient" abbrechen...

  • VB.NET

Es gibt 21 Antworten in diesem Thema. Der letzte Beitrag () ist von SpaceyX.

    "Server.AcceptTcpClient" abbrechen...

    Moin,

    mit folgendem Code warte ich darauf, bis ein Client sich mit meinen Server verbinden will:

    VB.NET-Quellcode

    1. Client = Server.AcceptTcpClient


    Nur wie kann ich diesen Vorgang abbrechen?

    Tim
    Server.Stop wirft eine SocketException. Setzt natürlich voraus, dass der Server mit .Start() in den Listen-Modus versetzt wird.

    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    @ThuCommix: Oh, klar. An eine whileschleife dafür habe ich garnicht gedacht.. trotzdem kriege ich das noch nicht so ganz hin.

    Ich bin dann mal bereit, meinen kompletten Code hier zu posten:
    Class1.vb (Public Class Client, Public Class Server):
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.Net.Sockets
    3. Imports System.IO
    4. Imports System.Net
    5. Public Class Client
    6. Dim Stream As NetworkStream
    7. Dim StreamWriter As StreamWriter
    8. Dim StreamReader As StreamReader
    9. Dim Client As TcpClient
    10. Dim MainThread As Threading.Thread
    11. Public Event LostConnection(ByVal Reason As String)
    12. Sub New()
    13. MainThread = New Threading.Thread(AddressOf Main)
    14. MainThread.Start()
    15. End Sub
    16. Private Sub Main()
    17. While True
    18. If Client Is Nothing Then
    19. Continue While
    20. End If
    21. If Client.Connected = False Then
    22. Return
    23. End If
    24. Dim Msg As String = Receive()
    25. If Msg.Contains("shutdown") Then
    26. Dim Reason As String = Msg.Remove(0, "shutdown ".Length)
    27. RaiseEvent LostConnection(Reason)
    28. Disconnect(Reason)
    29. End If
    30. End While
    31. End Sub
    32. Public Function Connect(ByVal IP As String, ByVal Port As Integer, Optional ByRef ExitError As String = "", Optional ByVal Timeout As Integer = 5000) As Boolean
    33. If Client IsNot Nothing Then
    34. If Client.Connected Then
    35. ExitError = "Der Client ist bereits mit dem Server verbunden."
    36. Return False
    37. End If
    38. End If
    39. If Client Is Nothing Then
    40. Client = New TcpClient
    41. Dim Result As IAsyncResult = Client.BeginConnect(IP, Port, Nothing, Nothing)
    42. Dim Connected As Boolean = Result.AsyncWaitHandle.WaitOne(Timeout, True)
    43. If Connected Then
    44. Client.EndConnect(Result)
    45. Else
    46. ExitError = "Es konnte keine Verbindung zu dem Server aufgebaut werden (Timeout)"
    47. Return False
    48. End If
    49. If Client.Connected Then
    50. Stream = Client.GetStream
    51. StreamWriter = New StreamWriter(Stream)
    52. StreamReader = New StreamReader(Stream)
    53. Return True
    54. End If
    55. End If
    56. Return False
    57. End Function
    58. Public Function Disconnect(Optional ByVal Reason As String = "") As Boolean
    59. If Client IsNot Nothing Then
    60. If Client.Connected Then
    61. Send("disconnect")
    62. Client.Close()
    63. Client = Nothing
    64. Return True
    65. End If
    66. End If
    67. Return False
    68. End Function
    69. Public Sub Send(ByVal Input As String)
    70. Try
    71. StreamWriter.WriteLine(Input)
    72. StreamWriter.Flush()
    73. Catch ex As Exception : GotError(ex) : End Try
    74. End Sub
    75. Public Function Receive() As String
    76. Try
    77. Return StreamReader.ReadLine
    78. Catch ex As Exception
    79. GotError(ex)
    80. Return "error"
    81. End Try
    82. End Function
    83. Private Sub GotError(ByVal ex As Exception)
    84. Dim FilePATH As String = String.Format("{0}\client_error-{1}.log", Directory.GetCurrentDirectory, Date.Now)
    85. If File.Exists(FilePATH) Then
    86. File.Create(FilePATH)
    87. End If
    88. MsgBox("Fehler: " & ex.Message & vbNewLine & "Wurde im aktuellem Pfad gespeichert.")
    89. Dim ErrorMSG As String = String.Format("{0}: {1}{2}", Date.Now, ex.Message, vbNewLine)
    90. My.Computer.FileSystem.WriteAllText(FilePATH, ErrorMSG, True)
    91. End Sub
    92. End Class
    93. Public Class Server
    94. Dim Stream As NetworkStream
    95. Dim StreamWriter As StreamWriter
    96. Dim StreamReader As StreamReader
    97. Dim Server As TcpListener
    98. Dim Client As TcpClient
    99. Dim IPEndPoint As IPEndPoint
    100. Dim MainThread As Threading.Thread
    101. Dim IsRunning As Boolean = False
    102. Dim Commands As List(Of String)
    103. Dim ClientConnected As Boolean = False
    104. Dim CloseFromExit As Boolean = False
    105. Public Event ConnectionLost(ByVal Reason As String)
    106. Public Event ClientConnect()
    107. Public Event DataReceived(ByVal Message As String)
    108. Public Event ConlessData(ByVal Message As String)
    109. Sub New(ByVal Port As Integer)
    110. IPEndPoint = New IPEndPoint(IPAddress.Any, Port)
    111. ResetCommands() ' reset or create commandlist...
    112. End Sub
    113. Private Sub ResetCommands()
    114. Commands = New List(Of String)
    115. Commands.Add("c0mm4ndl1stf4r3v3r1mb4")
    116. End Sub
    117. Public Sub AddCommand(ByVal cmd As String)
    118. Commands.Add(cmd)
    119. End Sub
    120. Public Sub Start()
    121. Try
    122. If IsRunning Then
    123. MsgBox("Der Server ist bereits gestartet. Du kannst diesen nicht doppelt starten.")
    124. Return
    125. End If
    126. MainThread = New Threading.Thread(AddressOf Main)
    127. MainThread.Start()
    128. Catch ex As Exception : GotError(ex) : End Try
    129. End Sub
    130. Public Sub Close(Optional ByVal FromExit As Boolean = False)
    131. Try
    132. Send("shutdown Server Shutdown")
    133. IsRunning = False
    134. Server.Stop()
    135. CloseFromExit = FromExit
    136. Catch ex As Exception : GotError(ex) : End Try
    137. End Sub
    138. Public Sub Restart()
    139. Close()
    140. Start()
    141. End Sub
    142. Private Sub Main()
    143. Server = New TcpListener(IPEndPoint)
    144. Client = New TcpClient
    145. Server.Start()
    146. IsRunning = True
    147. While True
    148. If Server.Pending Then
    149. Client = Server.AcceptTcpClient()
    150. Exit While
    151. End If
    152. If CloseFromExit Then
    153. Return
    154. End If
    155. End While
    156. RaiseEvent ClientConnect()
    157. ClientConnected = True
    158. Stream = Client.GetStream
    159. StreamReader = New StreamReader(Stream)
    160. StreamWriter = New StreamWriter(Stream)
    161. While True
    162. If IsRunning = False Then
    163. Return
    164. End If
    165. Dim Msg As String = StreamReader.ReadLine
    166. Select Case Msg
    167. Case CommandExists(Msg)
    168. RaiseEvent DataReceived(Msg)
    169. Case "disconnect"
    170. ClientConnected = False
    171. RaiseEvent ConnectionLost("")
    172. Restart()
    173. Case Else
    174. RaiseEvent ConlessData(Msg)
    175. End Select
    176. End While
    177. End Sub
    178. Private Function CommandExists(ByVal cmd As String) As String
    179. For Each item In Commands
    180. If item = cmd Then
    181. Return item
    182. End If
    183. Next
    184. Return ""
    185. End Function
    186. Public Sub Send(ByVal Input As String)
    187. Try
    188. If ClientConnected = False Then
    189. Exit Sub
    190. End If
    191. StreamWriter.WriteLine(Input)
    192. StreamWriter.Flush()
    193. Catch ex As Exception : GotError(ex) : End Try
    194. End Sub
    195. Private Sub GotError(ByVal ex As Exception)
    196. Dim FilePATH As String = String.Format("{0}\server_error.txt", Directory.GetCurrentDirectory)
    197. MsgBox("Fehler: " & ex.Message & vbNewLine & "Wurde im aktuellem Pfad gespeichert.")
    198. Dim ErrorMSG As String = String.Format("{0}: {1}{2}", Date.Now, ex.Message, vbNewLine)
    199. My.Computer.FileSystem.WriteAllText(FilePATH, ErrorMSG, True)
    200. End Sub
    201. End Class


    Form1.vb:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports WindowsApplication1.Client
    3. Imports WindowsApplication1.Server
    4. Public Class Form1
    5. Dim OwnIP As String = "snip"
    6. Dim WithEvents Client As Client
    7. Dim WithEvents Server As Server
    8. Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    9. Client.Disconnect()
    10. Server.Close(True)
    11. End Sub
    12. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    13. Client = New Client
    14. Server = New Server(8)
    15. Server.Start()
    16. Server.AddCommand("test")
    17. Dim pError As String = ""
    18. If Not Client.Connect(OwnIP, 8, pError) Then
    19. MsgBox(pError)
    20. End If
    21. End Sub
    22. Sub Client_ConnectionLost(ByVal Reason As String) Handles Client.LostConnection
    23. MsgBox("Der Client hat die Verbindung zum Server verloren (" & Reason & ")")
    24. End Sub
    25. Sub Server_ConnectionLost(ByVal Reason As String) Handles Server.ConnectionLost
    26. MsgBox("Der Server hat die Verbindung zum Client verloren (" & Reason & ")")
    27. End Sub
    28. Sub Server_ClientConnected() Handles Server.ClientConnect
    29. MsgBox("Server: Client hat Verbindung mit Server erfolgreich aufgebaut.")
    30. End Sub
    31. Sub Server_DataReceived(ByVal Message As String) Handles Server.DataReceived
    32. End Sub
    33. Sub Server_GotInvalidMessage(ByVal Message As String) Handles Server.ConlessData
    34. MsgBox("Server: Kenne Befehl '" & Message & "' nicht.")
    35. End Sub
    36. End Class


    Tim
    Ach jetzt verstehe ich, du musst das anders machen. Starte einen neuen Thread (in diesen Main Thread nach den der Client angenommen wurde) der dann den neuen TcpClient händelt, sprich Events usw. Dann musst du auch den AcceptThread nicht exiten, so wird es eigentlich gemacht.
    @ThuCommix: backtothetoast:

    Ihr wisst, dass es Blödsinn ist, andauernd zu checken, ob eine Verbindungsanfrage vorliegt? Erstens treibt es die CPU-Last unnötig in die Höhe, zweitens ist es wohl daneben, wenn ohnehin signalisiert wird, wenn eine Verbindung zustande gekommen ist. Ich arbeite nun schon lange mit Sockets und diese Pending-Property habe ich noch niemals gebraucht. Der Aufruf von .Stop() tut genau das, was ich sagte und ebenso sagt es MSDN:

    msdn.microsoft.com/en-us/libra…ets.tcplistener.stop.aspx
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Ja aber das ist ja genau das Prinzip. Ich stoppe den Server, da ich keine Clients mehr annehmen will. Ich starte den Server wieder, wenn ich wieder Verbindungen möchte. Auch mit Exceptions kann man den Programmfluss wunderbar steuern. Aber gut, Dir muss ich das nicht sagen. Ich wollte das nur nochmal klar gestellt haben.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o