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:
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
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:
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