سؤال

I have this code. (Used it in other old project of mine, worked wonderfully)

SOCKET Connect(char * host, int port){
   struct sockaddr_in sin = {0}; 
   struct hostent * entry = 0;

   SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if(s == INVALID_SOCKET){
    return INVALID_SOCKET;
} 

entry = gethostbyname(host);

if(entry == 0){
   closesocket(s);
    return INVALID_SOCKET;
}

sin.sin_addr   = *((LPIN_ADDR)*entry->h_addr_list);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);

// The process becomes dealocked after this line
if( connect(s,(const LPSOCKADDR)&sin,sizeof(SOCKADDR)) == SOCKET_ERROR){
    closesocket(s);
    return INVALID_SOCKET;
}

return s;
}

I started this morning working on a Delphi project using TTcpClient and Indy's TIdTcpClient wrappers and I noticed the process did not make any connections rather it just hung after calling connect. I then switched to C/C++ and tried with this code which does the same thing. After it hangs, there's no way to kill it (unless when it's being debugged where I had to exit the debugger). TaskManager, Process Explorer didn't do shit.

There are no threads or loops or whatever that may cause it to hang just this code and another function that writes to the socket after it connects.

When debugging with Visual Studio, after sometime there's a message (below)

Visual Studio Error

Even Wireshark doesn't show anything at all. Restarted my computer and still the same problem.

So has anyone ever had this problem before?

Used compilers

  • Visual Studio 2010
  • Pelles-C
  • Delphi 7

OS : Windows 7 64 bit, Ultimate

Winsock Version: 2.2

Update:

So I thought I would getaway and switched to Java only to find out the same problem after a couple of times. What the hell is wrong here. The Java takes around 2 minutes to connect even on localhost. This simple code takes ~2 minutes during which java.exe can't be killed also.

long startTime = System.currentTimeMillis(), endTime;
Socket clientSock = new Socket("localhost",80); // running Apache on localhost
endTime = System.currentTimeMillis();
Log("Connection time " + (endTime - startTime) + " ms");
clientSock.close();

run:
Connection time 125088 ms 

As for Java I did some searches and this problem was a bug in version 1 of the JDK but the change log showed it had been patched. But then again this happens in the underlying winsock library. WHY ? This program connects instantly and it also uses winsock: http://flatassembler.net/examples/quetannon.zip

So now I have to re-write 976 lines of JAVA in assembly just because of this? Help me out here people.

هل كانت مفيدة؟

المحلول

Since you are encountering the same problem in multiple wrappers that all ultimately delegate to Winsock, its safe to assume that this is an OS issue, not a coding issue. Something on your system has hosed your Winsock installation, or the OS is having networking problems in general, especially since a simple OS reboot did not clear the issue. Try using Windows' command-line netsh tool to reset both the TCP and Winsock subsystems, the command-line ipconfig tool to flush the DNS cache, reboot, and see if the problem continues.

On the coding side, you should implement a timeout on the connect() to avoid further deadlocks. There are two ways to do that:

  1. Put the socket into non-blocking mode and then call select() if connect() returns a WSAEWOULDBLOCk error. If select() times out, close the socket.

  2. Leave the socket in blocking mode and use a separate thread to manage the timeout. Call connect() in the thread, or run your timeout logic in the thread, it does not really matter, but if the timeout elapses while connect() is still running then you can close the socket, aborting connect(). This is the approach that TIdTCPClient uses.

نصائح أخرى

Ok. For the JAVA part at least I solved it by using the following code based on the answer here Java Socket creation takes more time.

So basically the default timeout value is (possibly) huge.So what I did was set a 3 second timeout then once the timeout exception is thrown, the next call works instantly.

private static final int CONNECT_TIMEOUT = 3000; // 3 seconds
private static Socket AttemptConnection(String host, int port) {
    Socket temp;
    try {
        temp = new Socket();
        temp.connect(new InetSocketAddress(host, port), CONNECT_TIMEOUT);
        return temp;
    } catch (Exception ex) {
        temp = null;
        lastException = ex.getMessage();
        return temp;
    }
}

And somewhere in your code (at least in my app)

while ( (clientSock = AttemptConnection("localhost",80)) == null ){
    Log("Attempting connection. Last exception: " + lastException);
    try{Thread.sleep(2500);}catch(Exception ex){} /* This is necessary in my application */
}

So looking at this I think the fix to all the socket implementations (JAVA,Delphi, etc) is to set a small timeout value then connect again.

EDIT:

The root of the problem was found: I have a HIPS program (COMODO Firewall) running on my laptop. If COMODO's cmdagent.exe is active, it'll show me an alert of an outgoing connection to which I can accept/deny. If not, it will silently deny the connection, so therefore something becomes deadlocked in the low levels.I was worried my PC was effed up.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top