Click here to Skip to main content
15,881,938 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hello everyone,
This is only my second instance at working with Sockets, I apologize in advance as my knowledge on the matter is clearly limited. Here's what I'm stuck on:

I have a Dialog box A. Dialog A has a button which opens Dialog Box B.
It contains two private variables:
C#
DialogB *receive;
CWnd *t_pParent;



C++
void CDialogA::OnButton1() 
{
	// TODO: Add your control notification handler code here
     receive->Create(_T("STATIC"), NULL, WS_CHILD | WS_VISIBLE,CRect(0, 0, 20, 20),                           t_pParent, 1234);
     receive->ShowWindow(SW_SHOW);
}


Create does this:
C#
BOOL DialogB::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
    // TODO: Add your specialized code here and/or call the base class

    return CDialog::Create(IDD, pParentWnd);
}


DialogB also contains all of the required IPs and port assignments required for the next step.

Is also has a button with runs the following code:
C#
void DialogB::OnButton1()
{ 
    WORD SockVersionRequested;
    WSADATA wsa_Data;
 
	// Check if socket library initialization was completed successful. 
	SockVersionRequested = MAKEWORD(1, 1);
	if(WSAStartup(SockVersionRequested, &wsa_Data) == 0)
	{
			// Create an UDP socket (SOCK_DGRAM)
		socket_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);

		if(socket_fd > 0)
		{
			// SBC!
			sender_adr.sin_family = AF_INET;
			sender_adr.sin_addr.s_addr = htonl(ip_sender);
			sender_adr.sin_port = htons(port_sender);

			// Display!
			receiver_adr.sin_family = AF_INET;
			receiver_adr.sin_addr.s_addr = htonl(ip_receiver);
			receiver_adr.sin_port = htons(port_receiver);

			// Bind the UDP socket to the port of receiver.
                        if(bind(socket_fd, (struct sockaddr *)&receiver_adr,sizeof(struct sockaddr_in)) == -1) 
			{
				closesocket(socket_fd);
				socket_fd = 0;
			}
			
			int sz;
	                int recv_data = 0;
	                char data_buffer[1024];
                        sz = sizeof(sockaddr_in);
                        recv_data = 0;
			recv_data = recvfrom(socket_fd, data_buffer, 1024, 0, (struct sockaddr *)&sender_adr, &sz);
			
		}
	}
}


This code is being run on a laptop on a LAN network connected to an FPGA transmitting a gretting message broadcast once every 5 seconds.

In this case however it is unable to receive and gets stuck on recvfrom(),however I have also run the above code from DialogA and been able to properly receive the greeting message. This is how I know that the issue above comes from the fact that DialogB is not the main thread of the application.

Does anyone know how a way for me to properly receive the greeting from Dialog B?
I'll check back in a bit and see if more information on the issue is required.
Thanks!
Posted
Comments
Parwarrior7 11-Apr-13 13:05pm    
Anyone else have any input?

I am guessing you are testing your FPGA using a little windows test program

It is almost always a bad idea to call socket functions from the application's main thread, or event/message handlers (such as OnButton1). The main reason (and there are others) is that socket functions will commonly block depending on the status of the actual comms/Ethernet line which is not what you want.

The basic way would be:

1) Create another (comms) thread and start it
2) The comms thread will call recvfrom as necessary and never block the main app thread. So your user interface will work no matter what is happening with your Ethernet packets. Clearly if you needed to send data to FPGA you would do it in that thread too.
3) When data is received by the comms thread, it should set a flag that will tell the main app thread that data is ready to be displayed. Clearly you need to be careful that data buffer is accessed by 2 threads with no conflicts.

Similar arrangements work for me very well. If you are still stuck let me know I will dig out some actual code examples.
 
Share this answer
 
Comments
Parwarrior7 10-Apr-13 20:29pm    
I've actually simplified the above code a bit from my actual implementation to explain my issue. The recvfrom is in fact called in a seperate thread created by DialogB, and storing the data from the FPGA to be used separately. However, the problem of with allowing me to bind the socket outside the main thread exists in both scenarios.
michaelmel 10-Apr-13 22:02pm    
Then I am not sure. My gut feeling is that it may be unrelated to threading in this case, but instead could be an issue with binding the socket. Does bind actually return an error code that makes sense? May be you bound the same address address before? For example, if you run the app second time after a crash and cleanup is not performed properly, then TCP/IP stack will still consider IP address as in use - in which case you will get WSAEADDRINUSE error code on return. (If this is indeed the case you could use SO_REUSEADDR option).
Parwarrior7 11-Apr-13 8:48am    
Confusingly enough, WSAGetLastError actually returns 0 after the bind and allows the program to proceed to recvfrom where it gets stuck.
michaelmel 11-Apr-13 19:54pm    
Stating the obvious but if the socket is set to be blocking (is it?) it should "get stuck" by definition until you get all 1024 bytes you have asked for. Look I think it is just a matter of debugging this thing through. Cheers
You could achieve this using different techniques.
First is to use select() model.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx[^]
Second is to use event model using functions such as WSAEventSelect, WSAWaitForMultipleEvents etc.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms741576(v=vs.85).aspx[^]
http://msdn.microsoft.com/en-us/library/windows/desktop/ms742219(v=vs.85).aspx[^]
Third is to use overlapped I/O with callback function on receive and send.
http://www.winsocketdotnetworkprogramming.com/winsock2programming/winsock2advancediomethod5h.html[^]
Of course for TCP/IP protocol you also could use I/O completion ports.

I also recomend you a book 'Network Programming for Microsoft Windows' by Anthony Jones. It might help to fulfill your requirements in winsock programming.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900