Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++ MFC Sockets MSDN
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:
    DialogB *receive;
    CWnd *t_pParent;
 

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:
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:
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 10-Apr-13 7:31am
Comments
Parwarrior7 at 11-Apr-13 13:05pm
   
Anyone else have any input?
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

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.
  Permalink  
Comments
Parwarrior7 at 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 at 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 at 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 at 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
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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.
  Permalink  

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

  Print Answers RSS
0 OriginalGriff 200
1 George Jonsson 175
2 Kornfeld Eliyahu Peter 169
3 PIEBALDconsult 110
4 Richard MacCutchan 85
0 OriginalGriff 6,080
1 DamithSL 4,648
2 Maciej Los 4,087
3 Kornfeld Eliyahu Peter 3,624
4 Sergey Alexandrovich Kryukov 3,294


Advertise | Privacy | Mobile
Web03 | 2.8.141220.1 | Last Updated 10 Apr 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100