Hallo Leute!
Ich hoffe das ich im richtigen Forum bin.
Mein Problem liegt beim Socket Empfang
wenn ich von Server zum Client eine Datei sende empfängt Client zwischen 2 und 7 mal dieselbe vollständige Datei Daten
wenn ich von Client zum Server eine Datei sende, empfängt Server nur 1 mal die vollständige Datei Daten was auch Richtig ist.
Kann mir vielleicht ein Helfen?
Der Code
Spoiler anzeigen
"Um keine Threadübergreifend zu verursachen"
Danke im Vorraus!
*Topic verschoben*
Ich hoffe das ich im richtigen Forum bin.
Mein Problem liegt beim Socket Empfang
wenn ich von Server zum Client eine Datei sende empfängt Client zwischen 2 und 7 mal dieselbe vollständige Datei Daten
wenn ich von Client zum Server eine Datei sende, empfängt Server nur 1 mal die vollständige Datei Daten was auch Richtig ist.
Kann mir vielleicht ein Helfen?
Der Code
VB.NET-Quellcode
- #Region " Events "
- Public Event Connected(ByVal sender As Winsock)
- Public Event Disconnected(ByVal sender As Winsock)
- Public Event DataArrival(ByVal sender As Winsock, ByVal BytesTotal As Integer)
- Public Event ConnectionRequest(ByVal sender As Winsock, ByVal requestID As Socket)
- Public Event SendComplete(ByVal sender As Winsock)
- Public Event HandleError(ByVal sender As Winsock, ByVal Description As String, ByVal Method As String, ByVal myEx As String)
- Public Event StateChanged(ByVal sender As Winsock, ByVal state As WinsockStates)
- #End Region
- #Region " Variables "
- Private _RemoteIP As String = "127.0.0.1"
- Private _LocalPort As Integer = 80
- Private _RemotePort As Integer = 80
- Private _State As WinsockStates = WinsockStates.Closed
- Private _sBuffer As String
- Private _buffer() As Byte
- Private _byteBuffer(1024) As Byte
- Private _sockList As Socket
- Private _Client As Socket
- #End Region
- #Region " Constructors "
- Public Sub New()
- Me.New(80)
- End Sub
- Public Sub New(ByVal Port As Long)
- Me.New("127.0.0.1", Port)
- End Sub
- Public Sub New(ByVal IP As String)
- Me.New(IP, 80)
- End Sub
- Public Sub New(ByVal IP As String, ByVal Port As Long)
- RemoteIP = IP
- RemotePort = Port
- LocalPort = Port
- End Sub
- #End Region
- #Region " Properties "
- Public Property LocalPort() As Integer
- Get
- Return _LocalPort
- End Get
- Set(ByVal Value As Integer)
- If GetState = WinsockStates.Closed Then
- _LocalPort = Value
- Else
- Throw New Exception("Must be idle to change the local port")
- End If
- End Set
- End Property
- Public Property RemotePort() As Integer
- Get
- Return _RemotePort
- End Get
- Set(ByVal Value As Integer)
- If GetState <> WinsockStates.Connected Then
- _RemotePort = Value
- Else
- Throw New Exception("Can't be connected to a server and change the remote port.")
- End If
- End Set
- End Property
- Public Property RemoteIP() As String
- Get
- Return _RemoteIP
- End Get
- Set(ByVal Value As String)
- If GetState = WinsockStates.Closed Then
- _RemoteIP = Value
- Else
- Throw New Exception("Must be closed to set the remote ip.")
- End If
- End Set
- End Property
- <Browsable(False)> Public ReadOnly Property GetState() As WinsockStates
- Get
- Return _State
- End Get
- End Property
- #End Region
- #Region " Methods "
- Public Sub Listen()
- Dim x As New System.Threading.Thread(AddressOf DoListen)
- x.Start()
- End Sub
- Public Sub Close()
- Try
- Select Case GetState
- Case WinsockStates.Listening
- ChangeState(WinsockStates.Closing)
- _sockList.Close()
- Case WinsockStates.Connected, WinsockStates.Connecting, WinsockStates.ConnectionPending, WinsockStates.HostResolved, WinsockStates.Open, WinsockStates.ResolvingHost
- ChangeState(WinsockStates.Closing)
- _Client.Close()
- Case WinsockStates.Closed
- 'do nothing
- End Select
- ChangeState(WinsockStates.Closed)
- Catch ex As Exception
- ChangeState(WinsockStates.Error)
- RaiseEvent HandleError(Me, ex.Message, ex.TargetSite.Name, ex.ToString)
- End Try
- End Sub
- Public Sub Accept(ByVal requestID As Socket)
- Try
- ChangeState(WinsockStates.ConnectionPending)
- _Client = requestID
- RaiseEvent Connected(Me)
- ChangeState(WinsockStates.Connected)
- _Client.BeginReceive(_byteBuffer, 0, 1024, SocketFlags.None, AddressOf DoStreamReceive, Nothing)
- Catch ex As Exception
- ChangeState(WinsockStates.Error)
- RaiseEvent HandleError(Me, ex.Message, ex.TargetSite.Name, ex.ToString)
- End Try
- End Sub
- Public Sub Connect()
- If GetState = WinsockStates.Connected Or GetState = WinsockStates.Listening Then
- RaiseEvent HandleError(Me, "Already open, must be closed first", "Connect", "Nothing here")
- Exit Sub
- End If
- Try
- Dim remIP As String
- ChangeState(WinsockStates.ResolvingHost)
- Try
- Dim x As System.Net.IPAddress
- x = IPAddress.Parse(_RemoteIP)
- remIP = x.ToString
- Catch ex1 As Exception
- 'not a valid IP address - resolve DNS
- Try
- Dim x As System.Net.Dns
- Dim ip As IPHostEntry = x.GetHostByName(_RemoteIP)
- Dim t() As IPAddress = ip.AddressList
- remIP = t(0).ToString
- Catch ex2 As Exception
- ChangeState(WinsockStates.Error)
- RaiseEvent HandleError(Me, ex2.Message, ex2.TargetSite.Name, ex2.ToString)
- End Try
- End Try
- ChangeState(WinsockStates.HostResolved)
- _Client = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
- Dim rEP As New IPEndPoint(IPAddress.Parse(remIP), RemotePort)
- ChangeState(WinsockStates.Connecting)
- _Client.BeginConnect(rEP, New AsyncCallback(AddressOf OnConnected), Nothing)
- Catch ex As Exception
- ChangeState(WinsockStates.Error)
- RaiseEvent HandleError(Me, ex.Message, ex.TargetSite.Name, ex.ToString)
- End Try
- End Sub
- Public Sub Connect(ByVal IP As String, ByVal Port As Integer)
- RemoteIP = IP
- RemotePort = Port
- Connect()
- End Sub
- #End Region
- #Region " Public Functions/Subs "
- Public Function LocalIP() As String
- Dim h As System.Net.IPHostEntry = System.Net.Dns.GetHostByName(System.Net.Dns.GetHostName)
- Return CType(h.AddressList.GetValue(0), Net.IPAddress).ToString
- End Function
- Public Function RemoteHostIP() As String
- Dim iEP As IPEndPoint = _Client.RemoteEndPoint
- Return iEP.Address.ToString
- End Function
- #End Region
- #Region " Send Overloads "
- Public Sub Send(ByVal Data As String)
- Dim sendBytes() As Byte = System.Text.Encoding.ASCII.GetBytes(Data)
- Me.Send(sendBytes)
- End Sub
- Public Sub Send(ByVal Data() As Byte)
- Select Case GetState
- Case WinsockStates.Closed
- 'can't send - not connected
- Case WinsockStates.Listening
- 'listening
- Case WinsockStates.Connected
- Try
- 'send the bytes that are passed
- ReDim Preserve Data(UBound(Data) + 1)
- Data(UBound(Data)) = 4
- _Client.Send(Data)
- Catch ex As Exception
- Me.Close()
- ChangeState(WinsockStates.Error)
- RaiseEvent HandleError(Me, ex.Message, ex.TargetSite.Name, ex.ToString)
- End Try
- End Select
- End Sub
- Public Sub Send(ByVal Data As Bitmap)
- Dim str As New System.IO.MemoryStream
- Data.Save(str, System.Drawing.Imaging.ImageFormat.Bmp)
- Dim sendBytes(str.Length - 1) As Byte
- str.Position = 0
- str.Read(sendBytes, 0, str.Length)
- Me.Send(sendBytes)
- End Sub
- #End Region
- #Region " GetData Overloads "
- Public Sub GetData(ByRef data As String)
- Dim byt() As Byte = Nothing
- GetData(byt)
- For i As Integer = 0 To UBound(byt)
- If byt(i) = 10 Then
- data &= vbLf
- Else
- data &= ChrW(byt(i))
- End If
- Next
- End Sub
- Public Sub GetData(ByRef bytes() As Byte)
- ReDim bytes(UBound(_buffer))
- _buffer.CopyTo(bytes, 0)
- Erase _buffer
- End Sub
- Public Sub GetData(ByRef bitmap As Bitmap)
- Dim byt() As Byte = Nothing
- GetData(byt)
- Dim str As New System.IO.MemoryStream(byt, False)
- bitmap = Bitmap.FromStream(str)
- End Sub
- #End Region
- #Region " Private Functions/Subs "
- Private Sub ChangeState(ByVal new_state As WinsockStates)
- _State = new_state
- RaiseEvent StateChanged(Me, _State)
- End Sub
- Private Sub OnConnected(ByVal asyn As IAsyncResult)
- Try
- _Client.EndConnect(asyn)
- ChangeState(WinsockStates.Connected)
- _Client.BeginReceive(_byteBuffer, 0, 1024, SocketFlags.None, AddressOf DoStreamReceive, Nothing)
- RaiseEvent Connected(Me)
- Catch ex As Exception
- ChangeState(WinsockStates.Error)
- RaiseEvent HandleError(Me, ex.Message, ex.TargetSite.Name, ex.ToString)
- End Try
- End Sub
- Private Sub DoListen()
- Try
- Dim tmpSocket As Socket
- _sockList = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
- Dim ipLocal As New IPEndPoint(IPAddress.Any, LocalPort)
- _sockList.Bind(ipLocal)
- _sockList.Listen(1)
- ChangeState(WinsockStates.Listening)
- _sockList.BeginAccept(New AsyncCallback(AddressOf OnClientConnect), Nothing)
- Catch ex As Exception
- Me.Close()
- ChangeState(WinsockStates.Error)
- RaiseEvent HandleError(Me, ex.Message, ex.TargetSite.Name, ex.ToString)
- End Try
- End Sub
- Private Sub OnClientConnect(ByVal asyn As IAsyncResult)
- Try
- Dim tmpSock As Socket
- If GetState = WinsockStates.Listening Then
- tmpSock = _sockList.EndAccept(asyn)
- RaiseEvent ConnectionRequest(Me, tmpSock)
- _sockList.BeginAccept(New AsyncCallback(AddressOf OnClientConnect), Nothing)
- End If
- Catch ex As Exception
- Me.Close()
- ChangeState(WinsockStates.Error)
- RaiseEvent HandleError(Me, ex.Message, ex.TargetSite.Name, ex.ToString)
- End Try
- End Sub
- Private Sub DoStreamReceive(ByVal ar As IAsyncResult)
- Dim intCount As Integer
- Try
- intCount = _Client.EndReceive(ar)
- If intCount < 1 Then
- Me.Close()
- ReDim _byteBuffer(1024)
- RaiseEvent Disconnected(Me)
- Exit Sub
- End If
- If IsNothing(_buffer) Then
- ReDim Preserve _buffer(intCount - 1)
- Array.Copy(_byteBuffer, 0, _buffer, 0, intCount)
- Else
- ReDim Preserve _buffer((_buffer.Length + (intCount - 1)))
- Array.Copy(_byteBuffer, 0, _buffer, (_buffer.Length) - intCount, intCount)
- End If
- Array.Clear(_byteBuffer, 0, intCount)
- If _Client.Available = 0 Then
- ' RaiseEvent DataArrival(Me, 0)'<<<<<<< Fehler, da ein Threadübergreifend verursachen wird
- CrossThread.RunGui(AddressOf DoDataArrival, 0)
- End If
- _Client.BeginReceive(_byteBuffer, 0, 1024, SocketFlags.None, AddressOf DoStreamReceive, Nothing)
- Catch ex As Exception
- Me.Close()
- ReDim _byteBuffer(1024)
- RaiseEvent Disconnected(Me)
- End Try
- End Sub
- #End Region
- Private Sub DoDataArrival(ByVal BytesTotal As Integer)
- RaiseEvent DataArrival(Me, BytesTotal)
- End Sub
- End Class
- #Region " Enumerations "
- Public Enum WinsockStates
- Closed = 0
- Open = 1
- Listening = 2
- ConnectionPending = 3
- ResolvingHost = 4
- HostResolved = 5
- Connecting = 6
- Connected = 7
- Closing = 8
- [Error] = 9
- 'Listening = 1
- 'Connected = 2
- End Enum
- #End Region
"Um keine Threadübergreifend zu verursachen"
Visual Basic-Quellcode
- Public Class CrossThread
- Public Shared Sub RunAsync(Of T1, T2, T3)(ByVal Action As Action(Of T1, T2, T3), ByVal Arg1 As T1, ByVal Arg2 As T2, ByVal Arg3 As T3)
- ' Aufruf von Action.EndInvoke() gewährleisten, indem er als
- ' Callback-Argument mitgegeben wird
- Action.BeginInvoke(Arg1, Arg2, Arg3, AddressOf Action.EndInvoke, Nothing)
- End Sub
- Public Shared Sub RunAsync(Of T1, T2)(ByVal Action As Action(Of T1, T2), ByVal Arg1 As T1, ByVal Arg2 As T2)
- Action.BeginInvoke(Arg1, Arg2, AddressOf Action.EndInvoke, Nothing)
- End Sub
- Public Shared Sub RunAsync(Of T1)(ByVal Action As Action(Of T1), ByVal Arg1 As T1)
- Action.BeginInvoke(Arg1, AddressOf Action.EndInvoke, Nothing)
- End Sub
- Public Shared Sub RunAsync(ByVal Action As Action)
- Action.BeginInvoke(AddressOf Action.EndInvoke, Nothing)
- End Sub
- Private Shared Function GuiCrossInvoke(ByVal Action As [Delegate], ByVal ParamArray Args() As Object) As Boolean
- If Application.OpenForms.Count = 0 Then
- ' Wenn kein Form mehr da ist, so tun, als ob das Invoking
- ' ausgeführt wäre
- Return True
- End If
- If Application.OpenForms(0).InvokeRequired Then
- Application.OpenForms(0).BeginInvoke(Action, Args)
- Return True
- End If
- Return False
- End Function
- Public Shared Sub RunGui(Of T1, T2, T3)(ByVal Action As Action(Of T1, T2, T3), ByVal Arg1 As T1, ByVal Arg2 As T2, ByVal Arg3 As T3)
- ' Falls Invoking nicht erforderlich, die Action direkt ausführen
- If Not GuiCrossInvoke(Action, Arg1, Arg2, Arg3) Then
- Action(Arg1, Arg2, Arg3)
- End If
- End Sub
- Public Shared Sub RunGui(Of T1, T2)(ByVal Action As Action(Of T1, T2), ByVal Arg1 As T1, ByVal Arg2 As T2)
- If Not GuiCrossInvoke(Action, Arg1, Arg2) Then Action(Arg1, Arg2)
- End Sub
- Public Shared Sub RunGui(Of T1)(ByVal Action As Action(Of T1), ByVal Arg1 As T1)
- If Not GuiCrossInvoke(Action, Arg1) Then Action(Arg1)
- End Sub
- Public Shared Sub RunGui(ByVal Action As Action)
- If Not GuiCrossInvoke(Action) Then Action()
- End Sub
- [/spoiler]
- End Class
Danke im Vorraus!
*Topic verschoben*
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „tommy“ ()