Hi,

ich arbeite an einem Client-Server-Projekt. Da ich mit asynchronen Sockets in .NET noch nicht so firm bin, nutze ich als Kommunikationsbibliothek eine leicht angepasste Version der MSDN-Beispiel-Implementierungen
http://msdn.microsoft.com/de-de/library/fx6588te.aspx
http://msdn.microsoft.com/de-de/library/bew39x2a.aspx

Mir ist bewusst, dass dies eine möglichst minimalistische Implementierung zu sein scheint, aber kann mir bitte jemand sagen, an welchen Stelle die Nutzung dieses Codes problematisch werden könnte? Und warum?

Mein Bibliothek funktioniert 90% der Zeit problemlos, selbst bei "größeren" Dateimengen (~15 KB)

Allerdings habe ich im Moment das Problem, dass wenn ich eine bestimmte Aktion ausführe zwar die richtigen Daten gesendet werden. Diese aber nicht komplett ankommen. Es fehlt in diesem Fall scheinbar das 1. kB.

Hier mein kompletter Quelltext für die Bibliothek:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
Public Class StateObject
    Public ID As Integer = 0
    ' Client  socket.
    Public workSocket As Socket = Nothing
    ' Size of receive buffer.
    Public Const BufferSize As Integer = 1024
    ' Receive buffer.
    Public buffer(BufferSize) As Byte
    ' Received data string.
    Public sb As New StringBuilder
End Class 'StateObject
 
Public Class AsyncronousServer
    Implements IDisposable
 
    Public allDone As New ManualResetEvent(False)   'informiert über ACCEPT
    Public MessageBuffer As Queue(Of Message)
    'Public clients As New Hashtable '(Client-ID, StateObject)
    Public state As New StateObject
    Public localSock As Socket
    Public MsgEvent As ManualResetEvent             ' wenn eine Nachricht erhalten wurde
 
    Public Sub New(ByVal listenEP As IPEndPoint, ByRef MBuffer As Queue(Of Message), ByRef newMsg As ManualResetEvent)
        localSock = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
        localSock.Bind(listenEP)
        MessageBuffer = MBuffer
        MsgEvent = newMsg
        localSock.Listen(1)
    End Sub
 
    Public Sub Accept()
        localSock.BeginAccept(New AsyncCallback(AddressOf AcceptCallback), localSock)
    End Sub
 
 
    Public Sub AcceptCallback(ByVal ar As IAsyncResult)
        ' Get the socket that handles the client request.
 
        Dim listener As Socket = CType(ar.AsyncState, Socket)
        ' End the operation.
        Dim handler As Socket = listener.EndAccept(ar)
        ' Create the state object for the async receive.
 
        state.workSocket = handler
        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReadCallback), state)
        allDone.Set()
    End Sub 'AcceptCallback
 
    Public Sub read()
        state.workSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReadCallback), state)
    End Sub
 
    Public Sub ReadCallback(ByVal ar As IAsyncResult)
        Dim content As String = String.Empty
 
        ' Retrieve the state object and the handler socket
        ' from the asynchronous state object.
        Dim state As StateObject = CType(ar.AsyncState, StateObject)
        Dim handler As Socket = state.workSocket
 
        ' Read data from the client socket. 
        Dim bytesRead As Integer = 0
        Try
            ' Read data from the remote device.
            bytesRead = handler.EndReceive(ar)
        Catch ex As Exception
            Console.WriteLine("Verbindung zum Server verloren")
        End Try
        Try
            If bytesRead > 0 Then
                ' There  might be more data, so store the data received so far.
                state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, bytesRead))
 
                content = state.sb.ToString()
                If bytesRead < StateObject.BufferSize Then
                    ' All the data has been read from the 
                    ' client. Display it on the console.
                    Dim msg As New Message(state.sb.ToString())
                    MessageBuffer.Enqueue(msg)
                    MsgEvent.Set()
                    state.sb.Remove(0, state.sb.Length) 'speicher leeren
                Else
                    ' Not all data received. Get more.
                    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReadCallback), state)
                End If
            End If
        Catch ex As Exception
            Console.WriteLine("Fehler beim Lesen: " & ex.ToString())
        Finally
 
        End Try
    End Sub 'ReadCallback
 
    Public Sub Send(ByVal ID As Integer, ByVal data As String)
        ' Convert the string data to byte data using UTF8 encoding.
        Dim byteData As Byte() = Encoding.UTF8.GetBytes(data)
 
        ' Begin sending the data to the remote device.
        state.workSocket.BeginSend(byteData, 0, byteData.Length, 0, New AsyncCallback(AddressOf SendCallback), state)
    End Sub 'Send
 
 
    Private Sub SendCallback(ByVal ar As IAsyncResult)
        ' Retrieve the socket from the state object.
        Dim handler As Socket = CType(ar.AsyncState.workSocket, Socket)
 
        ' Complete sending the data to the remote device.
        Dim bytesSent As Integer = handler.EndSend(ar)
        read() ' wieder alles auf Lesen setzen
    End Sub 'SendCallback
 
    Public Sub closeAll()
        state.workSocket.Shutdown(SocketShutdown.Both)
        state.workSocket.Close()
    End Sub
 
#Region "IDisposable Support"
    Private disposedValue As Boolean ' So ermitteln Sie überflüssige Aufrufe
 
    ' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                state.workSocket.Shutdown(SocketShutdown.Both)
                state.workSocket.Close()
            End If
 
            ' TODO: Nicht verwaltete Ressourcen (nicht verwaltete Objekte) freigeben und Finalize() unten überschreiben.
            ' TODO: Große Felder auf NULL festlegen.
        End If
        Me.disposedValue = True
    End Sub
 
    ' Dieser Code wird von Visual Basic hinzugefügt, um das Dispose-Muster richtig zu implementieren.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Ändern Sie diesen Code nicht. Fügen Sie oben in Dispose(ByVal disposing As Boolean) Bereinigungscode ein.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region
 
End Class
 
Public Class AsyncronousClient
    Implements IDisposable
 
    Public socktoserver As Socket
 
    ' ManualResetEvent instances signal completion.
    Private Shared connectDone As New ManualResetEvent(False)
    Private Shared sendDone As New ManualResetEvent(False)
    Private Shared receiveDone As New ManualResetEvent(False)
    Private newMsg As ManualResetEvent
    Private content As New StringBuilder()
 
    Private MessageBuffer As Queue(Of Message)
 
    Public Sub New(ByVal sock As Socket, ByRef MBuffer As Queue(Of Message), ByRef MsgEvent As ManualResetEvent)
        socktoserver = sock
        MessageBuffer = MBuffer
        newMsg = MsgEvent
    End Sub
 
    Public Function connect(ByVal remoteEP As EndPoint) As Boolean
        socktoserver.BeginConnect(remoteEP, New AsyncCallback(AddressOf ConnectCallback), socktoserver)
        connectDone.WaitOne()
        Return socktoserver.Connected
    End Function
 
    Private Sub ConnectCallback(ByVal ar As IAsyncResult)
        ' Retrieve the socket from the state object.
        Dim client As Socket = CType(ar.AsyncState, Socket)
 
        ' Complete the connection.
        client.EndConnect(ar)
 
        'Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString())
 
        ' Signal that the connection has been made.
        connectDone.Set()
    End Sub 'ConnectCallback
 
 
    Public Sub Receive()
 
        ' Create the state object.
        Dim state As New StateObject
        state.workSocket = socktoserver
 
        ' Begin receiving the data from the remote device.
        socktoserver.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReceiveCallback), state)
    End Sub 'Receive
 
 
    Private Sub ReceiveCallback(ByVal ar As IAsyncResult)
 
        ' Retrieve the state object and the client socket 
        ' from the asynchronous state object.
        Dim state As StateObject = CType(ar.AsyncState, StateObject)
        Dim client As Socket = state.workSocket
        Dim bytesRead As Integer = 0
        Try
            ' Read data from the remote device.
            bytesRead = client.EndReceive(ar)
        Catch ex As Exception
            Console.WriteLine("Verbindung zum Server verloren")
        End Try
        If bytesRead > 0 Then
            ' There might be more data, so store the data received so far.
            state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, bytesRead))
 
            content.Append(state.sb.ToString())
            state.sb.Remove(0, state.sb.Length) 'speicher leeren
            If bytesRead < StateObject.BufferSize Then
                ' All the data has been read from the 
                ' client. Display it on the console.
                Dim msg As New Message(content.ToString())
                MessageBuffer.Enqueue(msg)
                'state.sb.Remove(0, state.sb.Length) 'speicher leeren
                content.Remove(0, content.Length)
                newMsg.Set()
                Receive()
            Else
                ' Not all data received. Get more.
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReceiveCallback), state)
            End If
            'newMsg.Reset()
        End If
    End Sub 'ReceiveCallback
 
 
    Public Sub Send(ByVal data As String)
        ' Convert the string data to byte data using UTF8 encoding.
        Dim byteData As Byte() = Encoding.UTF8.GetBytes(data)
 
        ' Begin sending the data to the remote device.
        socktoserver.BeginSend(byteData, 0, byteData.Length, 0, New AsyncCallback(AddressOf SendCallback), socktoserver)
    End Sub 'Send
 
 
    Private Sub SendCallback(ByVal ar As IAsyncResult)
        ' Retrieve the socket from the state object.
        Dim client As Socket = CType(ar.AsyncState, Socket)
 
        ' Complete sending the data to the remote device.
        Dim bytesSent As Integer = client.EndSend(ar)
 
        ' Signal that all bytes have been sent.
        sendDone.Set()
        Receive()   ' wieder auf Lesen setzen
    End Sub 'SendCallback
 
    Public Sub close()
        socktoserver.Shutdown(SocketShutdown.Both)
        socktoserver.Close()
    End Sub
 
#Region "IDisposable Support"
    Private disposedValue As Boolean ' So ermitteln Sie überflüssige Aufrufe
 
    ' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                close()
            End If
 
            ' TODO: Nicht verwaltete Ressourcen (nicht verwaltete Objekte) freigeben und Finalize() unten überschreiben.
            ' TODO: Große Felder auf NULL festlegen.
        End If
        Me.disposedValue = True
    End Sub
 
    ' Dieser Code wird von Visual Basic hinzugefügt, um das Dispose-Muster richtig zu implementieren.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Ändern Sie diesen Code nicht. Fügen Sie oben in Dispose(ByVal disposing As Boolean) Bereinigungscode ein.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region
 
End Class

Ich habe mir auch schon mehrere Tutorials online angesehen. Diese behandeln meist aber nur die Grundlagen, wie im MSDN-Beispiel.

Danke schonmal für die Hilfe.

mfg LuigiEd