Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / CLR / October 2003

Tip: Looking for answers? Try searching our database.

Is socketbuffer empty?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Robert A. van Ginkel - 15 Sep 2003 10:00 GMT
Hello Fellow Developer,

This looks like a long mail, but at the end of this post is my socket
wrapper attached.
I want to make a timeout procedure that starts counting down after the
socketbuffer is empty.
This connection is being used to transmit data following a RFC so I cann't
create a control protocol that tells me the data was received.
(And even if I could, I want the timeout procedure to start after I send all
data, because that makes for me the most sense. (say I am sending 128mb the
socket will take longer sending then the timeout interval))
Any questions/remarks, NOT related to my question, pls ask directly via
email, dont post on the news server because It toke me alot of effort to
create this post.

Sample case:
if u send 1 byte from a client in Canada to a server in Australia with a 28k
modem thats being shared by an office of 30 people connected to the slowest
profider. (etc.)
What I want to say is that 1 byte may take a couple of minutes, and I use 1
byte as an
example because I don't want to make a question more complicated.

TCP/IP is a async protocol, but due to the Berkley Connection engine it
keeps track of what was send and received and what was not, so when there is
a packet loss it will send again.
So a socket keeps the data sequential, and if we are optimistic, the only
thing that can go wrong is a socket error.

There are three stadiums(simplified):
(A) My object sends to the Winsock, (buffer is being fed, no data on the
network, no data on the remote point)
(B) Winsock processes his buffer and sends on the network and waits for a
confirment that the package is succesfull transmitted(buffer is 'empty',
data on the network, no data on the remote point)
(C) All data is correctly processed and transported (buffer is truely empty,
no data on the network,data on the remote point)

Relative to the Sample case:
I achieve (A) ofcourse, I would really want to know (C), but I would be
satisfied with (B). I know (B) can be achieved, I hope (C) is too.

VB.NET FrameWork 2003(all patched and updated):
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 this doesn't work
properly (It will never timeout).
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 method
buffers it.
The System.Net.Sockets.Socket is a wrapper around the Win32 Socket 2 API's,
it makes internal calls to those api's, so I started reading if they forgot
implementing some functions, but they are all implemented.

I tried:
- The beginSend/EndSend (Async way with callback when command is finished)
  This calls within the async object the Socket.Send method, so its no
help, I can better do Socket.Send myself.
- The Socket.Blocking Property, it only blocks the Receive method,
Socket.Send goes directly in the buffer and then it returns immitially.
- Socket.Poll Method, returns the accessrights of the socket, "may I use
this socket to write?"
-
getSocketOption(Socket/TCP/IP,SendBuffer/ReceiveBuffer/SendLowWater/ReceiveL
owWater/SendTimeout/ReceiveTimeout) Method
   Throws an Exception

MyWrapper.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.Blocking = True
               _Socket.Connect(New
IPEndPoint(Dns.Resolve(pHost).AddressList(0), pPort))
               _lport = CType(_Socket.LocalEndPoint, 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 ReDim b(i - 1)
               OnMessageReceived(New Message(b))
               b = Nothing
           Loop
       Catch e As ThreadAbortException
           Exit Sub
       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 Overridable Sub OnError(ByRef pErr As Exception) 'If 2 errors
in diff threads?
       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
Ron Alberda [MSFT] - 21 Oct 2003 23:06 GMT
Actually Socket.Poll doesn't return the access rights, it tells you the
state of the socket. For example if you do a Send and then do a:

Socket.Poll(SelectMode.SelectRead)

It will return false until the server sends a response.

I think that's the closest you can get to what you want.

-Ron

> Hello Fellow Developer,
>
[quoted text clipped - 61 lines]
> this socket to write?"
> -

getSocketOption(Socket/TCP/IP,SendBuffer/ReceiveBuffer/SendLowWater/ReceiveL
> owWater/SendTimeout/ReceiveTimeout) Method
>     Throws an Exception
[quoted text clipped - 345 lines]
>
> End Class
K_Lee - 22 Oct 2003 08:48 GMT
....
> > There are three stadiums(simplified):
> > (A) My object sends to the Winsock, (buffer is being fed, no data on the
[quoted text clipped - 9 lines]
> > I achieve (A) ofcourse, I would really want to know (C), but I would be
> > satisfied with (B). I know (B) can be achieved, I hope (C) is too.

From this high level descriptions of the problem, I would create a
Application level  Msg/Ack handshake  to truely make
sure the remote is responding to my local requests.

I don't think peeking into the TCP stack at one system can give
your enough info to confirm the data get to the remote.

--
Browse source code and document for .NET CLI, Mozilla, Apache, NetBSD at
http://www.slink-software.com?E=SLinkEvn_1004

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.