none
WINCE 6.0 UDP Socket can not receive data from PC!!! RRS feed

  • Question

  • The develop board is using CAsyncSocket to create a UDP socket. It can send data to PC. But when PC send data to the board, the function OnReceive is definitely not called at all. Anybody knows why?

    PS: I used to build a test program, in which the develop board can both send and receive date correctly. However, in the program above, it can only send data to PC. The only difference between this two programs is that I add login module to the program above. In the login module, I use a TCP socket, which derived from CSocket, to connect to the server and the TCP socket is closed after login successfully.

    In addition, I am sure that the IP address and UDP port are both correct when PC send data to the develop board.

    Sunday, May 15, 2011 10:59 AM

Answers

  • Hi,

    I've got the reason why OnReceive function could not be activated. This is indeed caused by MFC bugs in WinCE.

     

    Ok, there are two things that need to be done to make this work:

    There is a bug in the CAsyncSocket in WindowsCE. 
    First to understand the bug, you need to know how AsyncSockets work in CE. Because the CE does not actually support AsyncSockets, they have to be simulated by having a worker thread which waits for a list of events. The list of events contains two fixed user events, exit and remap. As new CAsyncSocket or derived objects are created, the remap event is posted and the worker thread reads an internal map of created sockets and the events that the sockets wants to be notified about to create a list of events to wait for and the sockets to used when the event is signaled. 

    • BUG 1:    The implementation can delete/destroy the events associated with a socket before notifying the worker thread that the event is no-longer used. This especially will happen when the socket is closed or the AsyncSocket is destroyed.
    • BUG 2:    If the workerthread enters the WaitFor... function with the deleted event in the list, it will return an error. When the worker thread detects and error on the WaitFor..., it reports an error and returns to the Waitfor.. function. Since the deleted event was not removed from the list, the WaitFor.. returns an error and therefore you end up in an endless loop. This prevents AsyncSocket from signalling any events.
    • WORK AROUND: Before closing the server socket, you must disable the event detection for the socket. So Shutdown( 2 ), AsyncSelect(0) and then close the socket. This will prevent the worker thread from enterying the endless error loop.

    I don't know what the root cause of this is, but for some reason on CE the AsyncSocket listener will only notify you of the first Accept. But you can work around this using a timer loop to poll by calling Accept().

     

    In the WorkerThreadProc() function, my program entered the endless loop because of the reasons listed above and the error "Error: failed on waiting multiple events." was displayed in the output window ceaselessly. This prevents AsyncSocket from signalling any events.

    In my program, I firstly initialize UdpClientSock(a derived UDP CAsyncSocket )and then use TcpClientSock(a derived TCP CSocket) to connect to the Sever to process login verification as well as the synchronous communication. After login successfully, I close the TcpClientSock. The later P2P communication will be held on the UdpClientSock. 

    When the login process finish, I try to Shutdown(2) and AsyncSelect(0) before close the TcpClientSock but it doesn't work.

    Any method to solve the problem? For example, how to notify the WorkerThreadProc() that the event will no longer be used manually? Or the only way is to rewrite my program in WinSock?


    • Marked as answer by Jack.G Monday, May 23, 2011 4:25 AM
    Saturday, May 21, 2011 8:13 AM

All replies

  • Step #1 is to forget about "CAsyncSocket" and use regular WinSock sockets calls to attempt the receive.  This removes a layer of potential bugs and allows you to see if you have a network problem, a problem with the code supposedly sending the packets from the PC, or a problem with MFC.  You don't have to continue to use plain WinSock forever, but write a simple program to make sure that everything up to that level of the software stack works and you'll know where to go from there.

    My guess is the last, a bug in MFC, as I've successfully used WinSock on many different versions of Windows CE to receive datagram data.

    Paul T.

    Monday, May 16, 2011 3:11 PM
  • Thank you for your reply. Since the systems(I'm developing IM systems), both XP version and CE version, are built based on CAsyncSocket, it is impractical to change to WinSock sockets, so many places to modify.

    However, I find what the key problem is. It's just that the OnReceive function is not called. I try to manually receive data and the data can be retreived correctly! That is to say, when the XP version system send a text message to the CE version program, the OnReceive function in CE program is not activated automatically, but, at this time, I use a button to call RecvFrom function to receive the text message in the CE version program, it worked successfully and the correct messages are received.

    Do you know the reason why OnReceive function is not activated?

    Wednesday, May 18, 2011 4:54 AM
  • Anyone could help me?
    Thursday, May 19, 2011 4:46 AM
  • So, you've verified my guess, that MFC on CE has a bug.  This is totally not a surprise to me; I never use MFC on CE devices.  You haven't told us what development tools you're using, what version of CE, etc.  Any patch that might exist would be dependent on those parameters.

    Paul T.

    Thursday, May 19, 2011 11:00 PM
  • Development Tool: Visual Studio 2005 with patch sp1

    WinCE version: WinCE 6.0

    Patch:

    WinCE 6.0 SP1

    WinCE6.0 R2

    WinCE6.0 R3

    WinCE6.0 R3 Rolllup

    PS: I used to build a test program(separate the UDP socket module from the program I mentioned above), which can both send and receive date correctly on the development board. The OnReceive function can be activated automatically.

    Friday, May 20, 2011 4:17 AM
  • "so many places to modify"

    That's a problem on it's own...
    If your TCPIP stuff would be encapsulated in a single class, you wouldn't have this problem.
    In that case it would be easy to implement paul's suggestion.
    Also your TCPIP code would be more compact and less likely to suffer from environment issues, since there is only a well-defined , concentrated set of code responsible for handling the socket. Also you would be able to stub this module to test the classes that use them (to rule out some other part closes the socket for example).
    I suggest you take a critical look at your design before continuing on the technical details.
    I know there is never time for this kind of action, but you are probably spending this time already on your bug-hunt.

    Rob
    www.robtso.nl

     

     

     


    Friday, May 20, 2011 6:23 AM
  • Thank you for your suggestion.

    Actually I encapsulated the network related code in a single class well. By "So many places to modify" I mean that I need to redesign all the network related functions, which are the main module in this "tiny" system. Changing to Winsock will need to rewrite all these functions in the sever program,PC version client program and CE version client program.... What's more? The PC version client program works pretty well. The only problem is the WinCE version client program. I don't know why the OnReceive function can not be activated once the program was transplanted into WinCE version...

    Friday, May 20, 2011 4:15 PM
  • "Actually I encapsulated the network related code in a single class well"

    Ok, CEWL....

    Another advantage of using winsock, is that you can compile your code to run on the desktop-PC unmodified.
    When I write APPs on CE I always make them run on both, saving a lot of time on deploying and debugging.

    There should be many examples around for a simple winsock TCPIP server, in a straightforward implementation create 1 clienthandler (thread, active class) per connection.

    Rob.
    www.robtso.nl

     

     

    Friday, May 20, 2011 4:37 PM
  • Hi,

    I've got the reason why OnReceive function could not be activated. This is indeed caused by MFC bugs in WinCE.

     

    Ok, there are two things that need to be done to make this work:

    There is a bug in the CAsyncSocket in WindowsCE. 
    First to understand the bug, you need to know how AsyncSockets work in CE. Because the CE does not actually support AsyncSockets, they have to be simulated by having a worker thread which waits for a list of events. The list of events contains two fixed user events, exit and remap. As new CAsyncSocket or derived objects are created, the remap event is posted and the worker thread reads an internal map of created sockets and the events that the sockets wants to be notified about to create a list of events to wait for and the sockets to used when the event is signaled. 

    • BUG 1:    The implementation can delete/destroy the events associated with a socket before notifying the worker thread that the event is no-longer used. This especially will happen when the socket is closed or the AsyncSocket is destroyed.
    • BUG 2:    If the workerthread enters the WaitFor... function with the deleted event in the list, it will return an error. When the worker thread detects and error on the WaitFor..., it reports an error and returns to the Waitfor.. function. Since the deleted event was not removed from the list, the WaitFor.. returns an error and therefore you end up in an endless loop. This prevents AsyncSocket from signalling any events.
    • WORK AROUND: Before closing the server socket, you must disable the event detection for the socket. So Shutdown( 2 ), AsyncSelect(0) and then close the socket. This will prevent the worker thread from enterying the endless error loop.

    I don't know what the root cause of this is, but for some reason on CE the AsyncSocket listener will only notify you of the first Accept. But you can work around this using a timer loop to poll by calling Accept().

     

    In the WorkerThreadProc() function, my program entered the endless loop because of the reasons listed above and the error "Error: failed on waiting multiple events." was displayed in the output window ceaselessly. This prevents AsyncSocket from signalling any events.

    In my program, I firstly initialize UdpClientSock(a derived UDP CAsyncSocket )and then use TcpClientSock(a derived TCP CSocket) to connect to the Sever to process login verification as well as the synchronous communication. After login successfully, I close the TcpClientSock. The later P2P communication will be held on the UdpClientSock. 

    When the login process finish, I try to Shutdown(2) and AsyncSelect(0) before close the TcpClientSock but it doesn't work.

    Any method to solve the problem? For example, how to notify the WorkerThreadProc() that the event will no longer be used manually? Or the only way is to rewrite my program in WinSock?


    • Marked as answer by Jack.G Monday, May 23, 2011 4:25 AM
    Saturday, May 21, 2011 8:13 AM
  • I finally put the close() function in the deconstructor in case this error happen when the program is running. It works!
    Monday, May 23, 2011 4:27 AM