URGENT - InvalidOperationException on UDP ReceiveFrom call in Wind

G

Guest

I have an application that we are porting from Unmanaged C++ to VB.NET
that involves sockets. There are two pieces to the code. One piece is
a one to one TCP call to a server which is working fine. The second
piece receives streaming data from the server on a regular basis via
UDP. My problem is that I can not make the ReceiveFrom call work.
This code is multithreaded and I don't know if that has any bearing on
it or not.

First off, I make a call to the function "OpenStreaming" which does the
following:

m_StreamSocket = New Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp)

Dim sockaddr_in As New
System.Net.SocketAddress(AddressFamily.InterNetwork)
Dim sep As New System.Net.IPEndPoint(System.Net.IPAddress.Any, nPort)
globalPort = nPort
m_StreamSocket.Bind(sep.Create(sockaddr_in))

Dim stws As New StreamThreadWithState(Me)
m_hStreamThread = New System.Threading.Thread(AddressOf
stws.StreamThread)
m_hStreamThread.Start()

"StreamThread" runs with the following code:

While (1)

Dim nResult As System.Int32

' Call StreamHandler(), the main worker function of
this thread
nResult = pThis.StreamHandler

' Check for error. Timeout errors are okay in this
instance.
If (((O22SIOMM.SIOMM_OK <> nResult) And
(O22SIOMM.SIOMM_TIME_OUT <>
nResult))) Then
Exit While
End If

' Check flag to see if we should keep looping
If pThis.m_bListenToStreaming = False Then
' Stop looping
nResult = O22SIOMM.SIOMM_OK
Exit While
End If

' Check the timeouts of all stream items

pThis.CheckStreamTimeouts()

pThis.m_hStreamThread.Sleep(1)

End While

The "StreamHandler" code is as follows:

Dim ecode As Int32
Dim nResult As System.Int32
Dim bCriticalSectionFlag As Boolean = True

Try
If (m_StreamSocket Is Nothing) Then
StreamHandler = SIOMM_ERROR_NOT_CONNECTED
Exit Function
End If
Catch e As SocketException
m_O22UTILS.writeOptoErrorToLog(Me.GetType.Name &
".StreamHandler",
e.Message, e.ErrorCode)
StreamHandler = SIOMM_TIME_OUT
Exit Function
Catch e As ObjectDisposedException
m_O22UTILS.writeOptoErrorToLog(Me.GetType.Name &
".StreamHandler",
e.Message)
StreamHandler = SIOMM_TIME_OUT
Exit Function
Catch e As Exception
m_O22UTILS.writeOptoErrorToLog(Me.GetType.Name &
".StreamHandler",
e.Message)
StreamHandler = SIOMM_TIME_OUT
Exit Function
End Try

' Creates an IpEndPoint to capture the identity of the
sending host.
Dim sender As New
System.Net.IPEndPoint(System.Net.IPAddress.Any, 0)
Dim SourceAddr As System.Net.EndPoint = CType(sender,
System.Net.EndPoint)
Try
Dim lep As System.Net.EndPoint
Dim lipep As System.Net.IPEndPoint
Dim lip As System.Net.IPAddress
lip = New
System.Net.IPAddress(System.Net.IPAddress.Parse(System.Net.Dns.GetHostByName(System.Net.Dns.GetHostName).AddressList(0).ToString()).Address)
lipep = New System.Net.IPEndPoint(lip, globalPort)
lep = lipep
' lep = New
System.Net.IPEndPoint(lip, globalPort)
' lep = New
System.Net.IPEndPoint(System.Net.IPAddress.Any,
globalPort)
' m_StreamSocket.Bind(lep)
Dim testbytes() As Byte
ReDim testbytes(100)
Dim idx
For idx = LBound(testbytes) To UBound(testbytes)
testbytes(idx) = New Byte
testbytes(idx) = 0
Next idx
'm_StreamSocket.SendTo(testbytes, SourceAddr)
'Result =
m_StreamSocket.ReceiveFrom(m_pbyLastStreamBlock,
m_nStreamLength, SocketFlags.None, SourceAddr)

'NOTE: I have already called BIND from OpenStreaming function
'HERE IS WHERE I BLOW UP
nResult =
m_StreamSocket.ReceiveFrom(m_pbyLastStreamBlock, 660,
SocketFlags.None, SourceAddr)
Catch e As SocketException
m_O22UTILS.writeOptoErrorToLog(Me.GetType.Name &
".StreamHandler",
"m_StreamSocket.Bind : " & e.Message, e.ErrorCode)
nResult = e.ErrorCode
StreamHandler = SIOMM_ERROR
Exit Function
Catch e As ObjectDisposedException
StreamHandler = SIOMM_ERROR
m_O22UTILS.writeOptoErrorToLog(Me.GetType.Name &
".StreamHandler",
"m_StreamSocket.Bind : " & e.Message)
Exit Function
Catch e As Exception
m_O22UTILS.writeOptoErrorToLog(Me.GetType.Name &
".StreamHandler",
"m_StreamSocket.Bind : " & e.Message)
StreamHandler = SIOMM_ERROR

Exit Function
End Try

Next I make a call to "StartStreamListening" which does: (I don't think
this is important because I am not even getting data from the server
yet because of the receiveFrom failure)

m_StreamCriticalSection.WaitOne()
Checks a list of classes for data. Each class is supposed to have data
or they will not be in the list
m_StreamCriticalSection.ReleaseMutex()

I have to ship this product by Friday 5/6/2005 and I am panicking
because this function is the only item left to port before thorough
testing can begin.

Please , Please, Please can someone help.

This is being run on Windows CE but when I run it on my desktop as a normal
windows app, I don't get the invalidoperationException. Is this a bug in
compact frameworks?

Thanks,
Mike Dixon
 
P

Paul G. Tobey [eMVP]

I doubt that it's a 'bug', although it might be something which is
unsupported. Can you send a smaller example that shows the problem. Bits
and pieces of code aren't really helpful in this situation.

You're saying that the Windows CE device connects to the server or the
server connects to the Windows CE device with a stream socket? The Windows
CE device then opens a datagram socket and receives data from the server?
Remember that ReceiveFrom() doesn't prevent you from receiving from other
hosts; it just returns which host the packet came from. What is the network
physical layer here? Ethernet? Wireless Ethernet?

Paul T.
 
G

Guest

Paul G. Tobey said:
I doubt that it's a 'bug', although it might be something which is
unsupported. Can you send a smaller example that shows the problem. Bits
and pieces of code aren't really helpful in this situation.

You're saying that the Windows CE device connects to the server or the
server connects to the Windows CE device with a stream socket? The Windows
CE device then opens a datagram socket and receives data from the server?
Remember that ReceiveFrom() doesn't prevent you from receiving from other
hosts; it just returns which host the packet came from. What is the network
physical layer here? Ethernet? Wireless Ethernet?

Paul T.


Paul,
Thanks for your response. It will take me a few minutes to get a
simple example built and then I will post it. To answer your other
questions:

You are correct that the WinCE device opens a datagram socket and will
receive data from the server (when receiveFrom or alternative works). This
is a closed network so there will only be one server on it and in the case of
multiple servers, we will be coding for that. The network is a cat5 based
ethernet system that is totally isolated from the rest of the world. I will
post some shorter code in a few minutes.

Thanks,
Mike Dixon
 
G

Guest

Paul G. Tobey said:
OK, that's fine. What device is this running on?

Paul T.

I am not sure exactly. It is a small computer board with a Pentium
processor, serial port, ethernet connector, display connector and one
mouse/keyboard connector, and a USB connector. This device does not have a
hard drive, it has a compact flash card for the OS which of course is Windows
CE 4.1

Mike
 
G

Guest

Stressed Out Developer said:
I am not sure exactly. It is a small computer board with a Pentium
processor, serial port, ethernet connector, display connector and one
mouse/keyboard connector, and a USB connector. This device does not have a
hard drive, it has a compact flash card for the OS which of course is Windows
CE 4.1

Mike



Public Function doUDPTest() As Int32
Dim nResult As Int32
Dim m_StreamSocket As Socket
Try
m_StreamSocket = New
System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp)
m_StreamSocket.Blocking = False
Dim sockaddr_in As New System.Net.SocketAddress(AddressFamily.InterNetwork)
Dim sep As New System.Net.IPEndPoint(System.Net.IPAddress.Any, 1500)

Dim sender As New System.Net.IPEndPoint(System.Net.IPAddress.Any, 1500)
Dim SourceAddr As System.Net.EndPoint = CType(sender, System.Net.EndPoint)
Dim m_pbyLastStreamBlock() As Byte
ReDim m_pbyLastStreamBlock(660)
Dim idx
For idx = LBound(m_pbyLastStreamBlock) To UBound(m_pbyLastStreamBlock)
m_pbyLastStreamBlock(idx) = New Byte
Next idx

m_StreamSocket.Bind(sep.Create(sockaddr_in))
nResult = m_StreamSocket.ReceiveFrom(m_pbyLastStreamBlock, 0, 660,
SocketFlags.None, SourceAddr)
m_StreamSocket.Close()
Catch e As SocketException
MsgBox("(" & e.ErrorCode & ") - " & e.Message & " pos =<" & posval & ">")
m_StreamSocket.Close()

Catch e As Exception
MsgBox(e.Message & " pos =<" & posval & ">")
m_StreamSocket.Close()

End Try

End Function


Paul,
Here is the test app function. I ran it under windows(form)
application with one button on the form that calls this function when clicked.

I receive an InvalidFunctionException when the ReceiveFrom is executed on
Windows CE . I received a 10035 socket exception on the Windows Desktop
version aka "a non-blocking socket operation could not be completed
immediately"

Thanks,
Mike
 
G

Guest

Stressed Out Developer said:
Public Function doUDPTest() As Int32
Dim nResult As Int32
Dim m_StreamSocket As Socket
Try
m_StreamSocket = New
System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp)
m_StreamSocket.Blocking = False
Dim sockaddr_in As New System.Net.SocketAddress(AddressFamily.InterNetwork)
Dim sep As New System.Net.IPEndPoint(System.Net.IPAddress.Any, 1500)

Dim sender As New System.Net.IPEndPoint(System.Net.IPAddress.Any, 1500)
Dim SourceAddr As System.Net.EndPoint = CType(sender, System.Net.EndPoint)
Dim m_pbyLastStreamBlock() As Byte
ReDim m_pbyLastStreamBlock(660)
Dim idx
For idx = LBound(m_pbyLastStreamBlock) To UBound(m_pbyLastStreamBlock)
m_pbyLastStreamBlock(idx) = New Byte
Next idx

m_StreamSocket.Bind(sep.Create(sockaddr_in))
nResult = m_StreamSocket.ReceiveFrom(m_pbyLastStreamBlock, 0, 660,
SocketFlags.None, SourceAddr)
m_StreamSocket.Close()
Catch e As SocketException
MsgBox("(" & e.ErrorCode & ") - " & e.Message & " pos =<" & posval & ">")
m_StreamSocket.Close()

Catch e As Exception
MsgBox(e.Message & " pos =<" & posval & ">")
m_StreamSocket.Close()

End Try

End Function


Paul,
Here is the test app function. I ran it under windows(form)
application with one button on the form that calls this function when clicked.

I receive an InvalidFunctionException when the ReceiveFrom is executed on
Windows CE . I received a 10035 socket exception on the Windows Desktop
version aka "a non-blocking socket operation could not be completed
immediately"

Thanks,
Mike

Please remove the "posVal" variables from the code as they were used as a
counter to see which function was executing. I thought I would remove them
before uploading the code and I left two instances in. Sorry about that

Mike
 
P

Paul G. Tobey [eMVP]

I think what's going on is that there is no data ready to be received and
that is generating an exception, but just not the one you're expecting. Why
is this socket non-blocking? That's usually a bad idea.

Please top-post, if you can. Scrolling down through two program listings is
getting on my nerves...

Paul T.
 
G

Guest

Paul,
Sorry about the bottomposting. It wasn't done on purpose. We have
another program that is receiving the data so we can confirm that the server
is streaming data. The part that confuses me the most is that Win CE is
throwing a non-socketException (InvalidOperationException) but Windows XP is
throwing an actual socketException. Shouldn't both environments throw the
same exception?

The socket is non-blocking because the application needs to continue with
other items if there is no data (also the code that this is being ported from
is set up that way and we are not in a position at this point to change the
way it functions. I welcome your comments on why Non-blocking UDP is a bad
idea.

I guess the real question behind everything here is what do I need to do to
make the ReceiveFrom work? I am confused on what is wrong with my setup? Do
you have any examples of a ReceiveFrom being used with UDP where the server
IP is unknown but the communication port is known?

Thanks,
Mike
 
P

Paul G. Tobey [eMVP]

Should, yes, but remember that the execution environment is *not the same*.
This is not a .NET run-time; it's a .NET Compact Framework run-time.

Non-blocking sockets cause you to spend time doing things that consume
processor cycles that don't need to be consumed. The better architecture is
to put your socket code in a thread. Using blocking sockets, a receive
operation that might not be completed for some time just puts the thread to
sleep. That thread consumes *zero* cycles of the processor until the socket
awakens it and data is ready. Your application will use as few cycles as
possible if it takes advantage of blocking operations wherever practical,
leaving those cycles that you're using for polling the socket now for other
applications to use.

I'd say that, in this case, you should catch the exception that's occurring,
assume that it indicates that there's no data present, document it as such
in your code, and continue with the process. If there's an exception thrown
when data *is* available, post back and I'll try to duplicate that.

Paul T.
 
Top