Socket still sending?

  • Thread starter Thread starter Robert A. van Ginkel
  • Start date Start date
R

Robert A. van Ginkel

Hello Fellow Developer,

I use the System.Net.Sockets to send/receive data (no
tcpclient/tcplistener), I made a receivethread in my wrapper, the
receivethread loops/sleeps while waiting for data and then fires a
datareceived event.
Within the waitingloop there is a timeout function, but I want the the
'last-time-socket-used' variable set when the socket is finished sending.
When I send by System.Net.Sockets.Socket.Send(buffer()) (<--this can be
10Mb) then it imitially returns to my thread, so the (internal) Send
functions buffers it. I tried to Poll, but this only tells you if you could
write to the socket, and I tried the getSocketOption(Tried
Socket/TCP/IP,Tried
SendBuffer/ReceiveBuffer/SendLowWater/ReceiveLowWater/SendTimeout/ReceiveTim
eout) but that throws an Error. (Before u look in my code I would like to
explain that I want to catch all exceptions in the parent object.)

Regards,
Robert

Ok this is myconnectionclass.vb

Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.IO
Imports System.Collections
Imports System.Threading
Imports System.Diagnostics

Public Class SmartConnection
Public Event ConnectionOpened(ByVal pMe As SmartConnection)
Public Event DataReceived(ByVal pMe As SmartConnection, ByVal Data As
Message)
Public Event CouldntConnect(ByVal pMe As SmartConnection)
Public Event ConnectionClosed(ByVal pMe As SmartConnection)
Public Event [Error](ByVal pMe As SmartConnection, ByVal pErr As
Exception)
Public Event TimeOut(ByVal pme As SmartConnection)

Private _Socket As Socket
Private _ReadThread As Thread
Private _StopThread As Thread 'Lookup threadingpool
Private _Closing As Boolean = False
Private _InError As Boolean = False
Private _lport As Long
Private lasttimeout As Long
Private pHost As String
Private pPort As Long
Private pRead As Boolean
Private pTimeout As Long
Private _Iswriting As Boolean = False

Protected Overrides Sub Finalize()
_ReadThread = Nothing
_StopThread = Nothing
_Socket = Nothing
MyBase.Finalize()
End Sub

#Region " Properties"
Public ReadOnly Property IsClosing() As Boolean
Get
IsClosing = (_Closing Or _Socket Is Nothing)
End Get
End Property

Public ReadOnly Property Connected() As Boolean
Get
Try
Connected = ((Not IsClosing) AndAlso _Socket.Connected =
True)
Catch e As Exception
OnError(e)
End Try
End Get
End Property

Protected ReadOnly Property Receiving() As Boolean
Get
Try
If Not Connected Then Throw New Exception("Socket is not
connected")
Receiving = ((Not _ReadThread Is Nothing) AndAlso
_ReadThread.IsAlive)
Catch e As Exception
OnError(e)
End Try
End Get
End Property

Public ReadOnly Property IPlocal() As String
Get
Try
If Connected Then IPlocal = EP2IPS(_Socket.LocalEndPoint)
Catch e As Exception
OnError(e)
End Try
End Get
End Property

Public ReadOnly Property IPremote() As String
Get
Try
If Connected Then IPremote = EP2IPS(_Socket.RemoteEndPoint)
Catch e As Exception
OnError(e)
End Try
End Get
End Property
#End Region
#Region " Connect"
Public Overridable Sub ConnectTo(ByRef hostName As String, ByRef port As
Long, Optional ByVal timeout As Long = 0)
Try
StartConnect(hostName, port, timeout, True)
Catch e As Exception
OnError(e)
End Try
End Sub

Protected Sub ConnectToWithoutReading(ByRef hostName As String, ByRef
port As Long, Optional ByVal timeout As Long = 0)
Try
StartConnect(hostName, port, timeout, False)
Catch e As Exception
OnError(e)
End Try
End Sub

Private Sub StartConnect(ByRef hostName As String, ByRef port As Long,
ByRef timeout As Long, ByRef read As Boolean)
Try
If Not _ReadThread Is Nothing Then Throw New Exception("Already
trying to connect")
_ReadThread = New Thread(AddressOf ConnectThread)
pHost = hostName : pPort = port : pRead = read : pTimeout =
timeout
_ReadThread.Start()
Catch e As Exception
OnError(e)
End Try
End Sub

Private Sub ConnectThread()
Try
If pHost = "" Then Throw New ArgumentNullException("hostname")
If pPort < IPEndPoint.MinPort Or pPort > IPEndPoint.MaxPort Then
Throw New ArgumentOutOfRangeException("port", "ArgRange_Port")
_Socket = New Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp)
Try
_Socket.Connect(New
IPEndPoint(Dns.Resolve(pHost).AddressList(0), pPort))
_lport = CType(_Socket.LocalEndPoint,
System.Net.IPEndPoint).Port
If Not pRead Then
SetReadName("SC.Read[PreConnect]")
_ReadThread = Nothing
Else
SetReadName("SC.EarlyRead[" & _lport & "]")
End If
OnConnectionOpened()
If pRead Then Receive()
Catch e As SocketException 'e.ErrorCode = 10061
SetReadName("SC.Read[NoConnect]")
_ReadThread = Nothing
OnCouldntConnect()
Close()
End Try
Catch e As Exception
SetReadName("SC.Read[Error]")
_ReadThread = Nothing
OnError(e)
End Try
End Sub
#End Region
#Region " Receive"
Protected Sub StartReceive()
Try
If Receiving Then Throw New Exception("Receiving was already
started")
_ReadThread = New Thread(AddressOf Receive)
SetReadName("SC.LateRead[" & _lport & "]")
_ReadThread.Start()
Catch e As Exception
OnError(e)
End Try
End Sub

Private Sub Receive()
Dim i As Long
Dim b() As Byte
'Dim ds As String, dt As String
Try
Do While Connected
If pTimeout > 0 Then lasttimeout = CurrTick() + pTimeout
Do While _Socket.Available = 0
'dt = ds
'ds = "@" & _lport & ","
'ds += _Socket.GetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.SendBuffer) & ","
'ds += _Socket.GetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.SendLowWater) & ","
'ds += _Socket.GetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.SendTimeout)
'Debug.WriteLineIf(dt <> ds, ds)
_ReadThread.Sleep(ReceiveWait)
If IsClosing Then Exit Sub
If _Socket.Poll(0, SelectMode.SelectError) Then

'System.Runtime.InteropServices.Marshal.GetLastWin32Error())
'_Socket.GetSocketOption(SocketOptionLevel.IP,
SocketOptionName.Error)
OnError(New Exception("Socket Error"))
End If
If pTimeout > 0 Then
'If _Socket.Poll(0, SelectMode.SelectWrite) Then
'lasttimeout = CurrTick() + pTimeout
'Else
If lasttimeout <= CurrTick() Then
OnTimeOut()
Close()
Exit Sub
End If
'Endif
End If
Loop
ReDim b(_Socket.Available - 1)
'SyncLock _Socket
i = _Socket.Receive(b, SocketFlags.None)
'End SyncLock
If i <> b.Length Then Throw New
Exception("Socket-data-length differs")
If i = 0 Then Throw New Exception("Socket-data-length = 0")
OnMessageReceived(New Message(b))
b = Nothing
Loop
Catch e As Exception
OnError(e)
End Try
End Sub
#End Region
#Region " Send"
Public Overridable Overloads Sub Send(ByRef data As String)
Try
Send(getbytes(data))
Catch e As Exception
OnError(e)
End Try
End Sub

Public Overridable Overloads Sub Send(ByRef data() As Byte)
Try
If Not Connected Then Throw New Exception("Socket isn't
connected")
_Iswriting = True
'SyncLock _Socket
_Socket.Send(data)
'End SyncLock
_Iswriting = False
Catch e As Exception
_Iswriting = False
OnError(e)
End Try
End Sub
#End Region
#Region " Close"
Public Overridable Sub Close() 'OR QUEE IT?
Try
If IsClosing Then Throw New Exception("Already is closing")
_Closing = True
_StopThread = New Thread(AddressOf DoClose)
_StopThread.Name = "SC.Stop[" & _lport & "]"
_StopThread.Start()
Catch e As Exception
OnError(e)
End Try
End Sub

Private Sub DoClose()
Try
_StopThread.Sleep(CloseWait)
Try
If Not _ReadThread Is Nothing Then
SetReadName("SC.Read[Close]")
If _ReadThread.IsAlive Then _ReadThread.Abort()
End If
Catch e As Exception
End Try
Try
If Not _Socket Is Nothing AndAlso _Socket.Connected Then
_Socket.Close()
Catch e As Exception
End Try
_ReadThread = Nothing
_Socket = Nothing
_Closing = False
_StopThread = Nothing
OnConnectionClosed()
Catch e As Exception
OnError(e)
End Try
End Sub
#End Region
#Region " OnEvent"
Protected Sub OnError(ByRef pErr As Exception) 'If 2 errors in diff
threads?
Debug.WriteLine(pErr.Message)
Debug.WriteLine(pErr.StackTrace)
Try
If Not _InError Then
_InError = True
Close()
_InError = False
End If
RaiseEvent Error(Me, pErr)
Catch e As Exception
Throw e
End Try
End Sub

Protected Sub OnTimeOut()
Try
RaiseEvent TimeOut(Me)
Catch e As Exception
OnError(e)
End Try
End Sub

Protected Sub OnCouldntConnect()
Try
RaiseEvent CouldntConnect(Me)
Catch e As Exception
OnError(e)
End Try
End Sub

Protected Sub OnConnectionClosed()
Try
RaiseEvent ConnectionClosed(Me)
Catch e As Exception
OnError(e)
End Try
End Sub

Protected Sub OnConnectionOpened()
Try
RaiseEvent ConnectionOpened(Me)
Catch e As Exception
OnError(e)
End Try
End Sub

Protected Sub OnMessageReceived(ByRef data As Message)
Try
RaiseEvent DataReceived(Me, data)
Catch e As Exception
OnError(e)
End Try
End Sub
#End Region

Private Sub SetReadName(ByRef pName As String)
If Not _ReadThread Is Nothing AndAlso _ReadThread.Name Is Nothing
Then _ReadThread.Name = pName
End Sub

End Class
 
Hi Robert,

Are you using Blocking or Non-Blocking mode?
AFAIK when used in blocking mode the method is blocked till it finishes.
Other solution would be to try asnyc sending..

Miha
 
Hello Miha,

Thanks for your reaction.

I tried _Socket.Blocking = True in the sub ConnectThread. But this made no
differends.

With asnyc sending (BeginSend..EndSend), After the async callsback the
socket is still sending (even if blocking is on)

Regards, Robert
 
The code for async is this:

Private Sub SendFinish(ByVal pia As System.IAsyncResult)
Try
If Not Connected Then Throw New Exception("Socket isn't
connected")
Dim i As Long = _Socket.EndSend(pia)
_Iswriting = False
Catch e As Exception
_Iswriting = False
OnError(e)
End Try
End Sub

Public Overridable Overloads Sub Send(ByRef data() As Byte)
Try
If Not Connected Then Throw New Exception("Socket isn't
connected")
'A data arrival can be faster then the syncthread
Thread.CurrentThread.Sleep(500) 'This is probally _ReadThread
If _Iswriting Then Throw New Exception("Already sending")
_Iswriting = True 'Cant write more then once!! TX/RC/RC/TX no
RC/TX/TX/RC
'SyncLock _Socket
'_Socket.Send(data)
_Socket.BeginSend(data, 0, data.Length, SocketFlags.None,
AddressOf SendFinish, Nothing)
'End SyncLock
'_Iswriting = False
Catch e As Exception
'_Iswriting = False
OnError(e)
End Try
End Sub
 
Back
Top