Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 967
  • Last Modified:

CAsyncSocket

Im writing a quick little program to transfer text from one computer to another using sockets in MFC and Im having trouble with the connect() member function.  It seems it keeps giving me a "WSAEWOULDBLOCK" error after I call it.  

Im not sure why Im getting this error, because the 'OnConnect' event does get fired, yet the server side program doesn't response to an Accept event,  so I know the connect is not working right.  If anyone has any ideas, Id appreciate it.

Here is a code snippet for the client side when it tries to establish a connection:

// This function is called from a button
// being pushed
void CSendboxDlg::OnSend()
{
      CEdit *IP, *Message;      

        //pointers to the edit controls
      IP = (CEdit*)GetDlgItem(IDC_IP);
      Message = (CEdit*)GetDlgItem(IDC_MESSAGE);
      
      //Get data from the controls
        IP->GetWindowText(m_lpSocket->m_lpszAddress, 50);
      Message->GetWindowText(m_lpSocket->m_lpszSendBuff, 1024);

        // port is 4114
      m_lpSocket->Create(4114);
      
        // here is the troubled line
        m_lpSocket->Connect(m_lpSocket->m_lpszAddress, 4114);      
}


Thanks for any help,
-Dan
0
dmaroff
Asked:
dmaroff
  • 6
  • 5
  • 3
  • +1
1 Solution
 
hiap_hoCommented:
why don't you try to connect through another port instead of 4114 like port 4000 ?
0
 
stefanrCommented:
It is correct that the Connect function returns FALSE and GetLastError returns WSAEWOULDBLOCK. That is how the CAsyncSocket normally works. The WSAEWOULDBLOCK just tells us that the connect operation has started, but it couldn't be completed immediately; only when the OnConnect event is fired you will know if the connect succeeded or not.

From what I see I can not detect anything wrong with your code snippet, but the question is how the sockets are created initially on the server side.

Normally it is not necessary to explicitly create the client socket with a specific port number. The default for Create is 0, which means that Windows Sockets would select a free port for you.

It is different with the server side: the client have to know the port number the server is bound to. The port number value that the server socket have as its first parameter in its Create function must be the same as the port number value for the client socket Connect call.

The default values for the lEvent parameter in both sides Create function is FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE, which means that the event functions for each type of event is activated. These can be changed at any time by calling the AsyncSelect member function. If for example the FD_ACCEPT event for the server is deactivated the OnAccept function would not be called on a client connection request.

Does the OnConnect nErrorCode parameter have a value other than 0 ?
0
 
kdrrCommented:
Why don't you use CSocket? It's more easy to use and does some low-level conversions for you like htonl() etc.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
hiap_hoCommented:
Yes OnConnect nErrorCode parameter have a value other than 0.
Following are the nErrorCode it returns :
All of the things listed below were taken from MSDN Library

0   The function executed successfully.


WSAEADDRINUSE   The specified address is already in use.


WSAEADDRNOTAVAIL   The specified address is not available from the local machine.


WSAEAFNOSUPPORT   Addresses in the specified family cannot be used with this socket.


WSAECONNREFUSED   The attempt to connect was forcefully rejected.


WSAEDESTADDRREQ   A destination address is required.


WSAEFAULT   The lpSockAddrLen argument is incorrect.


WSAEINVAL   The socket is already bound to an address.


WSAEISCONN    The socket is already connected.


WSAEMFILE   No more file descriptors are available.


WSAENETUNREACH   The network cannot be reached from this host at this time.


WSAENOBUFS   No buffer space is available. The socket cannot be connected.


WSAENOTCONN   The socket is not connected.


WSAENOTSOCK   The descriptor is a file, not a socket.


WSAETIMEDOUT   The attempt to connect timed out without establishing a connection.

WSAEWOULDBLOCK
(10035)
Resource temporarily unavailable.
This error is returned from operations on non-blocking sockets that cannot be completed immediately, for example recv when no data is queued to be read from the socket. It is a non-fatal error, and the operation should be retried later. It is normal for WSAEWOULDBLOCK to be reported as the result from calling connect on a non-blocking SOCK_STREAM socket, since some time must elapse for the connection to be established.

Can this be the reason ??? try to put a wait state before sending any message..

Regards,

Hiap Ho
0
 
dmaroffAuthor Commented:
stefanr:  So what does this "WSAEWOULDBLOCK" do?  should I ignore it then?  If not, how do I handle it? Also, how should I call the create member function on the client side, without a port number?  It wont let me pass zero parameters to it.  Where should the port number be specified on the client side?

Thanks,
-Dan
0
 
dmaroffAuthor Commented:
Another thing I noticed is that you said I should call socket.Create(0)
for the client to get a port number from Windows and socket.Create(4114)
for the server.

Windows will then pick a port number for me on the client side.  How then would I let the client know what port number the server is bound to if the client is getting a randomly available port from Windows?

Thanks,
-Dan
0
 
stefanrCommented:
WSAEWOULDBLOCK just means that you can not use the socket (Send/Receive/...) until you have received the OnConnect event and have a nErrorCode parameter equal to 0, since the socket is waiting for the connection to complete; that is until the server has called Accept for the connection attempt (in its OnAccept).

The call to Create selects the port number that is locally bound; the call to Connect selects the port number that is remotely bound (locally at the server; the one that has called Listen).

A typical scenario is (psuedo-code):

// Common header file for Client and Server.

const UINT SERVER_PORT = 8000; // For example.

// Server Side

m_ServerSocket.Create(SERVER_PORT);
m_ServerSocket.Listen();

CServerSocket::OnAccept(int nErrorCode)
{
   if (0 == nErrorCode)
   {
      CAcceptedSocket* pSocket = new CAcceptedSocket;
      Accept(*pSocket);
      pSocket->AsyncSelect();
      m_listAcceptedSocket.AddTail(pSocket);
   }
   else
   {
      // Error handling.
   }
}

// Client Side

m_bSocketConnected = FALSE;

m_ClientSocket.Create();
BOOL bOk = m_ClientSocket.Connect(_T("www.xxx.yyy.zzz"), SERVER_PORT);

if (bOk)
{
   // OK to use socket immediately.
}
else if (!bOk && WSAEWOULDBLOCK == CAsyncSocket::GetLastError())
{
   // Must wait until OnConnect before using the socket.
}
else
{
  // Error handling.
}

CClientSocket::OnConnect(int nErrorCode)
{
   if (0 == nErrorCode)
   {
      // OK to use socket.
      m_bSocketConnected = TRUE;
   }
   else
   {
      // Error handling.
   }
}

0
 
dmaroffAuthor Commented:
Beautiful.  Code is worth 1000 words!!  I noticed your checking the return type of the connect(), for the possibility of immediate socket use.  If lets say you always wanted to wait for an onConnect() event.  Will this event fire anyways, even if there is no error returned?  Im trying to cancel out duplicating any code.

Now, I dont have two computers to test this on, Im using localhost or 127.0.0.1 as the parameter to
connect().  Im running two instances of Visual C++ 6.0, one runs as client the other a server.  Is this ok to do?

Thanks,
-Dan    
0
 
dmaroffAuthor Commented:
Beautiful.  Code is worth 1000 words!!  I noticed your checking the return type of the connect(), for the possibility of immediate socket use.  If lets say you always wanted to wait for an onConnect() event.  Will this event fire anyways, even if there is no error returned?  Im trying to cancel out duplicating any code.

Now, I dont have two computers to test this on, Im using localhost or 127.0.0.1 as the parameter to
connect().  Im running two instances of Visual C++ 6.0, one runs as client the other a server.  Is this ok to do?

Thanks,
-Dan    
0
 
dmaroffAuthor Commented:
Ok, I got it to work but it only works when I have one instance of the program acting as client and server.  If I run 2 instances of VC++ and run one as client and one as server, it wont work for some reason.

Why do you think that is?  How would I test it then?

-Dan
0
 
hiap_hoCommented:
if you have 2 instance running, try to connect to your own ip instead of looping back. I'm not sure it'll work. I have never been in this field before
but I have hear from here and there a bit

0
 
stefanrCommented:
I think that the OnConnect event is always fired, but since it is extremely unlikely that Connect is successful immediately, I have not real world experience of that situation.

I am pretty sure that hiap_ho's assumption is correct that it is better to use the real IP address than the loopback, when you have two different instances running at the same time.

One problem that can arise when running on the same computer is that you must make certain that the used port number for a socket is not used by another socket for the same socket type (SOCK_STREAM/SOCK_DGRAM). Normally that would not be a problem using the default settings of CAsyncSocket, but it is possible to change the socket options to permit several socket instances to open the same socket port number.
0
 
hiap_hoCommented:
Is it I have heard about UDP maybe that can achieve what you want instead of TCP/IP connection that you use
0
 
dmaroffAuthor Commented:
Hey thanks for the help.  I was wrong, it does work if you use 127.0.0.1.  But I have another problem and I think at this point Im just going to make the server a Win32 console app.  Only because it doesn't need a GUI interface anyways, and by using MFC for the server Im making a mountain out of a mole hill.  I find that using Win32 system calls directly, is easier to follow than MFC.

Thanks for all your help,
-Dan  
0
 
hiap_hoCommented:
Anytime
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 6
  • 5
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now