easywsclient icon indicating copy to clipboard operation
easywsclient copied to clipboard

bug when working with localhost interface

Open ivog1 opened this issue 10 years ago • 4 comments

When interface is localhost, "ws://localhost/foo" for instance function connect returns SOCKET_ERROR on first try. On second try everything is fine. "if (connect(sockfd, p->ai_addr, p->ai_addrlen) != SOCKET_ERROR)..." And this happens only with localhost interface The result is a timeout delay, because of the first error.

tested on windows and mac os

ivog1 avatar Nov 24 '13 19:11 ivog1

Hi @gity2020 - thanks for the report. Give me a couple days to look into this. To clarify, is this what you see:

  1. You try to open a new WebSocket connection to localhost. It fails.
  2. You try a second time. What happens this time? Does it succeed, or does it fail after a timeout delay?

dhbaird avatar Nov 25 '13 08:11 dhbaird

Not really. Actually everything looks good on every try, except a small delay. But if you put printf functions like in this example,you will see the difference:

....
   for(p = result; p != NULL; p = p->ai_next)
    {
        fprintf(stderr,"+");
        sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
        if (sockfd == INVALID_SOCKET)
                {     fprintf(stderr,"!");continue; }
        if (connect(sockfd, p->ai_addr, p->ai_addrlen) != SOCKET_ERROR) {
            break;
        } else fprintf(stderr,"E"); 
.....

only one "+" when WS:// is an IP address, and "+E+" with a localhost connection

BTW very nice, lite and effective WS client! thanks!

P.S. a simple workaround is to use 127.0.0.1 instead of localhost.

ivog1 avatar Nov 25 '13 14:11 ivog1

Thanks for your patience while I looked into this. I am taking a guess that getaddrinfo() probably returns ipv6 and ipv4 address, and that is why you get two iterations through the loop. If you like, you can check with code like the following. How long is the delay that you observe?

+#include <arpa/inet.h>

...

     for(p = result; p != NULL; p = p->ai_next)
     {
         sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
+        // see also: getnameinfo();
+        char buf[128];
+        if (p->ai_family == AF_INET) {
+            inet_ntop(p->ai_family, &((sockaddr_in *)p->ai_addr)->sin_addr, buf, 128);
+        }
+        else if (p->ai_family == AF_INET6) {
+            inet_ntop(p->ai_family, &((sockaddr_in6 *)p->ai_addr)->sin6_addr, buf, 128);
+        }
+        else {
+            strcpy(buf, "unknown family");
+        }
+        printf("inet_ntop(): %s\n", buf);
         if (sockfd == INVALID_SOCKET) { continue; }

...

To omit AF_INET6 addresses, change the hints to this:

hints.ai_family = AF_INET;

Let me know if this helps or if we need to keep searching for another solution.

dhbaird avatar Dec 01 '13 15:12 dhbaird

Hi @gity2020 - I just wanted to check: did the last message help at all with your issue? Let me know so I can close this if your issue has been solved. Thanks!

dhbaird avatar Dec 17 '13 00:12 dhbaird