Solved

CAsyncSocket

Posted on 2000-03-14
15
880 Views
Last Modified: 2013-11-20
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
Comment
Question by:dmaroff
  • 6
  • 5
  • 3
  • +1
15 Comments
 
LVL 1

Expert Comment

by:hiap_ho
ID: 2618635
why don't you try to connect through another port instead of 4114 like port 4000 ?
0
 
LVL 3

Expert Comment

by:stefanr
ID: 2618725
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
 

Expert Comment

by:kdrr
ID: 2618769
Why don't you use CSocket? It's more easy to use and does some low-level conversions for you like htonl() etc.
0
 
LVL 1

Expert Comment

by:hiap_ho
ID: 2618826
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
 

Author Comment

by:dmaroff
ID: 2619982
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
 

Author Comment

by:dmaroff
ID: 2620049
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
 
LVL 3

Accepted Solution

by:
stefanr earned 75 total points
ID: 2620210
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
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 

Author Comment

by:dmaroff
ID: 2621402
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
 

Author Comment

by:dmaroff
ID: 2621492
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
 

Author Comment

by:dmaroff
ID: 2621941
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
 
LVL 1

Expert Comment

by:hiap_ho
ID: 2621965
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
 
LVL 3

Expert Comment

by:stefanr
ID: 2622511
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
 
LVL 1

Expert Comment

by:hiap_ho
ID: 2622915
Is it I have heard about UDP maybe that can achieve what you want instead of TCP/IP connection that you use
0
 

Author Comment

by:dmaroff
ID: 2624004
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
 
LVL 1

Expert Comment

by:hiap_ho
ID: 2624186
Anytime
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Suggested Solutions

Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now