LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 03-02-2009, 02:51 PM   #1
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,523

Rep: Reputation: 332Reputation: 332Reputation: 332Reputation: 332
Why does connect() block for a long time?


I'm curious if anything can be done to speed up the error return of the connect() library call when attempting to connect to a remote server with an unopened port. When I attempt to connect to an unopened port on the localhost, the error return is practically immediate.

Here's some test code I am using:
Code:
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>


int FillAddress(const char* servAddr, const unsigned short servPort, struct sockaddr_in* addr);


int main(int argc, char** argv)
{
  const char*          servAddr = (argc > 1 ? argv[1] : "localhost");
  const unsigned short servPort = (argc > 2 ? atoi(argv[2]) : 9000);

  int sd = socket(AF_INET, SOCK_STREAM, 0);

  if (sd <= 0) return 1;

 
  struct sockaddr_in addr;

  if (FillAddress(servAddr, servPort, &addr) < 0) return 2;

  // This connect() blocks for a very, very long time... which is
  // not desirable.
  int status = connect(sd, (struct sockaddr*) &addr, sizeof(addr));

  printf("status = %s\n", (status == 0 ? "connected" : "not connected"));

  close(sd);

  return 0;
}


int
FillAddress(const char* servAddr, const unsigned short servPort, struct sockaddr_in* addr)
{
  struct addrinfo* host_info = 0;

  if (getaddrinfo(servAddr, 0, 0, &host_info) != 0  ||
      !host_info || !host_info->ai_addr || host_info->ai_family != AF_INET)
  {
    if (host_info) freeaddrinfo(host_info);
    return -1;
  }

  memcpy(addr, host_info->ai_addr, sizeof(struct sockaddr_in));
  addr->sin_port = htons(servPort);

  freeaddrinfo(host_info);

  return 0;
}
I attempted running this program with command-line args such as:
Code:
a.out www.google.com 80
a.out 64.233.169.104 80
 
Old 03-02-2009, 03:05 PM   #2
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,523

Original Poster
Rep: Reputation: 332Reputation: 332Reputation: 332Reputation: 332


Yep, all of the above; that's how I feel. I forgot to set the port to be non-blocking. Now the connect returns immediately.

Here's the code I added to the previous posting:
Code:
...
#include <fcntl.h>

int SetNonBlocking(int sd);
...

int main(int argc, char** argv)
{
  ...
  SetNonBlocking(sd);
  ...
}

int
SetNonBlocking(int sd)
{
  int curflags = fcntl(sd, F_GETFL, 0);
  return fcntl(sd, F_SETFL, curflags | O_NONBLOCK);
}
---------------------------

Edit:

Cr*p... apparently setting the port to non-blocking doesn't really help at all. Sure, the connect() returns immediately, but I get an EINPROGRESS error, which basically states that the connection request is pending and that I need to wait (and select/poll) for when it is done. This sort of defeats what I am trying to accomplish.

Can someone provide a clue on how to efficiently/easily scan open ports on a system? I'd hate to have to resort to building a multi-threaded application for this pet project.

Last edited by dwhitney67; 03-02-2009 at 03:18 PM.
 
Old 03-02-2009, 04:42 PM   #3
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Strangely enough, I had the same problem even when the socket was non-blocking, although it was with a bad address. The "non-blocking" connect call would block for about 30s before returning when I used an IP address that wasn't available.

Even if the server isn't blocking for accept, you should receive a connection if it's listening, the number of pending connections hasn't been exceeded, and the client is blocking. I haven't checked if writing is actually possible between the return of connect and the server's accept. For me that's undesired behavior, but it seems to be the way it works.

In general, at least one side of the connection operation must block. I normally have the server use select and have the clients connect in blocking mode, then switch the socket to non-blocking for data transfer. It can be cumbersome to have a single-threaded server with multiple clients for this very reason. Not only that, but intentionally breaking a select call isn't pretty. If all connections are independent, however, you can just design the server to use standard input and output and add it to inetd.
Kevin Barry

PS You probably don't run google.com (just noticed that part); therefore, I assume you don't have control of the server program. With the select call suggested by man connect, though, you can put it in a loop and use a timeout of { 0, 0 } (as opposed to NULL,) which will cause it to return immediately. That way you can do other things while you wait for the connection to go through.

Last edited by ta0kira; 03-02-2009 at 04:50 PM.
 
Old 03-04-2009, 07:46 PM   #4
linfidel
LQ Newbie
 
Registered: Sep 2008
Location: Left Coast, USA
Distribution: Ubuntu Hardy
Posts: 15

Rep: Reputation: 0
I'm not sure if this relates to your problem or not... It's been many years since I did socket programming (in C and C++), but when I ran into the problem of very long waits for connect, I ended up basically doing a ping first to make sure the socket was valid.

I used either ICMP or UDP for this - it's been too long to remember. But it would return a status immediately, and if OK, then I would do the connect.

This was using Winsock, so it may not even work for you.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Happy New Year! Long time listener. Fist time caller Little_Bear LinuxQuestions.org Member Intro 1 01-04-2009 06:53 AM
Long time user, first time poster to LinuxQuestions.org nevek LinuxQuestions.org Member Intro 1 07-21-2008 11:18 AM
Long time Windows users, first time Linux user Towjam LinuxQuestions.org Member Intro 1 06-21-2008 01:08 PM
Networkmanager 0.6.4 takes long time to connect TedyBear Linux - Wireless Networking 6 09-17-2007 03:44 AM
SSH takes a long time (2 minutes) to connect jinju Linux - Newbie 5 07-31-2004 11:37 PM


All times are GMT -5. The time now is 09:00 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration