Discussion:
Couldn't Connect Error - Address already in use
Rahul R
2010-04-28 11:43:38 UTC
Permalink
I am using libCurl version 7.19.6 on Windows Server 2003.

I am frquently getting Couldn't connect error even though the server is up. LibCurl debug logs show the error "Address already in use".

I am using easy interface and new handle is used for every new request.Only when i get redirect response i am reusing the same handle to connect to the redirected host.

This error("Address already in use") occurs if an application attempts to bind a socket to an IP address/port that has already been used for an existing socket, or a socket that was not closed properly, or one that is still in the process of closing.

I am trying to guess whats going wrong here ? Sometimes i get this error, sometimes i don't!

If required i can post detailed curl debug logs.

Thanks.
Daniel Stenberg
2010-04-28 21:04:47 UTC
Permalink
Post by Rahul R
I am frquently getting Couldn't connect error even though the server is up.
LibCurl debug logs show the error "Address already in use".
I am using easy interface and new handle is used for every new request.Only
when i get redirect response i am reusing the same handle to connect to the
redirected host.
Can you show us the source code for a complete little application that repeats
this problem?
Post by Rahul R
This error("Address already in use") occurs if an application attempts to
bind a socket to an IP address/port that has already been used for an
existing socket, or a socket that was not closed properly, or one that is
still in the process of closing.
Yes, and since you haven't told us about what libcurl options you use (and we
assume you're talking plain HTTP?), it is very hard to say much more about the
error.
--
/ daniel.haxx.se
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Rahul R
2010-04-29 11:29:02 UTC
Permalink
Thanks for the reply.

I would have loved to create a small application and showed it to you. However, this is part of a bigger code and can't be seperated out easily.

We are using HTTP. We are using libCurl version 7.19.6 on Windows Server 2003 and every request is sent using new curl handle(using easy interface).This is a multithreaded application

I am pasting the code snippet here(to POST a file). I am getting similar error for other requests too.

CURLcode curlcode = InitializeCurlOptions();
RETURN_CURLCODE_IF_FAILED(curlcode);

curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_READFUNCTION, ReadFile_Callback);
RETURN_CURLCODE_IF_FAILED(curlcode);

curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_WRITEFUNCTION, WriteFile_Callback);
RETURN_CURLCODE_IF_FAILED(curlcode);

curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_POST, 1L);
RETURN_CURLCODE_IF_FAILED(curlcode);

int fdFileToWrite = ::_open(rkstrSrcFilePath,_O_RDONLY);

if(fdFileToWrite == -1)
RETURN_CURLCODE_IF_FAILED(CURLE_FILE_COULDNT_READ_FILE);

struct _stat fileStat;
_fstat(fdFileToWrite,&fileStat);
::_close(fdFileToWrite);

curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_URL, rkstrURL);
RETURN_CURLCODE_IF_FAILED(curlcode);

FILE* pFILEToUpload = ::fopen(rkstrSrcFilePath,"rb");
if(!pFILEToUpload)
RETURN_CURLCODE_IF_FAILED(CURLE_FILE_COULDNT_READ_FILE);

CallBackArgs callBackArgsForFile;
callBackArgsForFile.pointerType = POINTER_FILE;
callBackArgsForFile.ptr = pFILEToUpload;

curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_READDATA, &callBackArgsForFile);
RETURN_CURLCODE_IF_FAILED(curlcode);

std::string strHTTPResponseHeader = "";
CallBackArgs callBackArgsForHeader;
callBackArgsForHeader.pointerType = POINTER_STLSTRING;
callBackArgsForHeader.ptr = &strHTTPResponseHeader;

curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_WRITEHEADER, &callBackArgsForHeader);
RETURN_CURLCODE_IF_FAILED(curlcode);

std::string strHTTPResponseData = "";
CallBackArgs callBackArgsForResponseFile;
callBackArgsForResponseFile.pointerType = POINTER_STLSTRING;
callBackArgsForResponseFile.ptr = &strHTTPResponseData;

curlcode = curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_WRITEDATA, &callBackArgsForResponseFile);
RETURN_CURLCODE_IF_FAILED(curlcode);

curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)fileStat.st_size);
RETURN_CURLCODE_IF_FAILED(curlcode);

struct curl_slist* headers_list=NULL;
ParseHeaderFields(headerFields, &headers_list);

if(headers_list != NULL)
{
//Set Header fields in the request
curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_HTTPHEADER, headers_list);
RETURN_CURLCODE_IF_FAILED(curlcode);
}

curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_DEBUGFUNCTION, TraceCurl_Callback);
curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_VERBOSE, 1L);


curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_NOBODY, 0L);
RETURN_CURLCODE_IF_FAILED(curlcode);

curlcode = ::curl_easy_perform(m_pCurlEasyHandle);
::fclose(pFILEToUpload);
::fclose(pDestinationFile);

if(headers_list != NULL)
{
curl_slist_free_all(headers_list);
}

//RETURN_CURLCODE_IF_FAILED(curlcode);
if(curlcode != CURLE_OK)
{
LogErrorMessage();
return curlcode;
}

return CURLE_OK;

The InitializeCurlOptions() sets following options: Please note that the purpose of setting these options is to be able to reuse the handle(to reset the options which has been set earlier) in some other case. But in this case(where we are getting this error), we are not reusing the handle.

//Disable Upload. This needs to be set when writing to HCAP (PUT related HTTP requests)
CURLcode curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_UPLOAD, 0L);
RETURN_CURLCODE_IF_FAILED(curlcode);

//Disable PUT. This needs to be set when writing to HCAP (PUT related HTTP requests)
curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_PUT, 0L);
RETURN_CURLCODE_IF_FAILED(curlcode);

//Set GET. This is the default setting when CURL is initialized
curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_HTTPGET, 1L);
RETURN_CURLCODE_IF_FAILED(curlcode);

//Disable NOBODY. This is the default setting when CURL is initialized. By default we get the file body
curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_NOBODY, 0L);
RETURN_CURLCODE_IF_FAILED(curlcode);

//Disable CUSTOMREQUEST. This is the default setting when CURL is initialized.
curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_CUSTOMREQUEST, NULL);
RETURN_CURLCODE_IF_FAILED(curlcode);

//Set the DNS cache timeout to 30.
curlcode = ::curl_easy_setopt(m_pCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 30);
RETURN_CURLCODE_IF_FAILED(curlcode);

Detailed curl debug logs:
Please note that CURLINFO_TEXT logs "Already in use".


{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} CurlHTTPCpp::TraceCurl_Callback::942:About to connect() to 10.0.8.252 port 80 (#0)

{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} CurlHTTPCpp::TraceCurl_Callback::942: Trying 10.0.8.252...
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:6836, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:065, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::942:About to connect() to 10.0.8.251 port 80 (#0)

{TR, 04/29/2010 02:53:01:065, P:1968, T:6836, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:6836, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:065, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::942: Trying 10.0.8.251...
{TR, 04/29/2010 02:53:01:065, P:1968, T:6836, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} CurlHTTPCpp::TraceCurl_Callback::942:Address already in use

{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} CurlHTTPCpp::TraceCurl_Callback::942:couldn't connect to host

{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} CurlHTTPCpp::TraceCurl_Callback::942:Closing connection #0

{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} CurlHTTPCpp::TraceCurl_Callback::942:Couldn't connect to server

{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} ++CurlHTTPCpp::LogErrorMessage:
{ER, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} CurlHTTPCpp::LogErrorMessage::689:ÀşV R
{TR, 04/29/2010 02:53:01:065, P:1968, T:2788, C:0} --CurlHTTPCpp::LogErrorMessage:
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::942:Address already in use

{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::942:couldn't connect to host

{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::942:Closing connection #0

{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::942:Couldn't connect to server

{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} ++CurlHTTPCpp::LogErrorMessage:
{ER, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} CurlHTTPCpp::LogErrorMessage::689:
{TR, 04/29/2010 02:53:01:081, P:1968, T:6836, C:0} --CurlHTTPCpp::LogErrorMessage:
{TR, 04/29/2010 02:53:01:643, P:1968, T:6836, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:643, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:643, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::942:About to connect() to 10.0.8.252 port 80 (#0)

{TR, 04/29/2010 02:53:01:643, P:1968, T:6836, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:643, P:1968, T:6836, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:643, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:643, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::942: Trying 10.0.8.252...
{TR, 04/29/2010 02:53:01:643, P:1968, T:6836, C:0} --CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:643, P:1968, T:6836, C:0} ++CurlHTTPCpp::TraceCurl_Callback:
{TR, 04/29/2010 02:53:01:643, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::908:CURLINFO_TEXT
{TR, 04/29/2010 02:53:01:643, P:1968, T:6836, C:0} CurlHTTPCpp::TraceCurl_Callback::942:connected
Daniel Stenberg
2010-04-29 17:55:25 UTC
Permalink
Post by Rahul R
I would have loved to create a small application and showed it to you.
However, this is part of a bigger code and can't be seperated out easily.
I meant that you would write a _new_ small application using your logic that
would show the same sympthoms...
--
/ daniel.haxx.se
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Rahul R
2010-04-30 05:49:10 UTC
Permalink
Even if i create an application to reproduce the problem, it won't be useful for you. Because the hosts can be accessed only within the organization :(

By any chance, can this be a server issue ? I think this a client side problem.

I am not able to understand one thing - I am creating new handle for every request and using the handle for only a single request. Then how do i get Address Already in use error ? libCurl will establish only single socket connection in this scenario, right ? Any scenario where libCurl tries to create one more connection to the same host(for a single request) ?

I understand, its very tough for you to predict what can be the issue behind this without looking at the code. But can you give some pointers at least, where things can go wrong and whether similar problem has been reported ?

Thanks for your support.
Daniel Stenberg
2010-04-30 06:56:16 UTC
Permalink
Post by Rahul R
By any chance, can this be a server issue ? I think this a client side problem.
Only good old debugging can tell. Check what goes over the wire. Check what
the client does (strace equivalent).
Post by Rahul R
I am not able to understand one thing - I am creating new handle for every
request and using the handle for only a single request. Then how do i get
Address Already in use error ?
I can't explain that either. Only options that would bind the source end to
something should risk that and you didn't mention using any such.
Post by Rahul R
libCurl will establish only single socket connection in this scenario, right
? Any scenario where libCurl tries to create one more connection to the same
host(for a single request) ?
If you use authentication or follow redirects etc it might do more than one.
Using VERBOSE will of course tell if it does.
--
/ daniel.haxx.se
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Rahul R
2010-04-30 18:09:35 UTC
Permalink
Is there any option like REUSEADDR to reuse address ?
Any way to access the socket FD ?
Daniel Stenberg
2010-04-30 20:35:16 UTC
Permalink
Post by Rahul R
Is there any option like REUSEADDR to reuse address ?
Reuse what address?
Post by Rahul R
Any way to access the socket FD ?
Several, but if you mean from a regular easy interface use, you might want
http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html#CURLINFOLASTSOCKET
--
/ daniel.haxx.se
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Alfred Gebert
2010-07-06 16:18:26 UTC
Permalink
Post by Daniel Stenberg
Post by Rahul R
I am frquently getting Couldn't connect error even though the server is
up. LibCurl debug logs show the error "Address already in use".
I am using easy interface and new handle is used for every new
request.Only when i get redirect response i am reusing the same handle to
connect to the redirected host.
Can you show us the source code for a complete little application that
repeats this problem?
I have the same problem as Rahul.

I am using libcurl 7.19.4 on Windows XP and I want to call a
HTTP PUT operation around 8000 times. After about 4000 requests
curl_easy_perform() returns with error 7 (CURLE_COULDNT_CONNECT,
Couldn't Connect Error, Address already in use).

I modified the httpput.c example to reproduce the problem:
- Added a third program argument: how many time should the HTTP
PUT be executed.
- If curl_easy_perform() does not return 0 then print an
error and exit the program.
- Added a write callback which does nothing, because the loop
must run fast. Without this modification I could not
reproduce the error.
- Ported to Windows.

I run the program five times (third argument: 10000) with some
delay between the runs and got this output:

3931 request failed: 7
3929 request failed: 7
2 request failed: 7
1 request failed: 7
3937 request failed: 7


/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id: httpput.c,v 1.11 2008-05-22 21:20:09 danf Exp $
*/

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <io.h>

#include <curl/curl.h>

/*
* This example shows a HTTP PUT operation. PUTs a file given as a command
* line argument to the URL also given on the command line.
*
* This example also uses its own read callback.
*
* Here's an article on how to setup a PUT handler for Apache:
* http://www.apacheweek.com/features/put
*/

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
size_t retcode;

/* in real-world cases, this would probably get this data differently
as this fread() stuff is exactly what the library already would do
by default internally */
retcode = fread((FILE*)ptr, size, nmemb, (FILE*)stream);

/* fprintf(stderr, "*** We read %d bytes from file\n", retcode); */

return retcode;
}

size_t write_callback( void* Buffer, size_t BufferSize, size_t
BufferCount, void* Stream)
{
return( BufferSize * BufferCount);
}

int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
FILE * hd_src ;
int hd ;
struct stat file_info;

char *file;
char *url;

if(argc < 4)
return 1;

file= argv[1];
url = argv[2];
int count = atoi(argv[3]);

/* get the file size of the local file */
hd = _open(file, _O_RDONLY) ;
fstat(hd, &file_info);
_close(hd) ;

/* get a FILE * of the same file, could also be made with
fdopen() from the previous descriptor, but hey this is just
an example! */
hd_src = fopen(file, "rb");

/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);

for( int i=0; i < count; i++)
{
fseek(hd_src, 0, SEEK_SET);

/* get a curl handle */
curl = curl_easy_init();
if(curl) {
/* we want to use our own read function */
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);

/* enable uploading */
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);

/* HTTP PUT please */
curl_easy_setopt(curl, CURLOPT_PUT, 1L);

/* specify target URL, and note that this URL should include a file
name, not only a directory */
curl_easy_setopt(curl, CURLOPT_URL, url);

/* now specify which file to upload */
curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);

/* provide the size of the upload, we specicially typecast the value
to curl_off_t since we must be sure to use the correct data size */
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
(curl_off_t)file_info.st_size);

/* Now run off and do what you've been told! */
res = curl_easy_perform(curl);

if( res != 0)
{
printf( "%d request failed: %d\n", i+1, res);
exit( -1);
}

/* always cleanup */
curl_easy_cleanup(curl);
}
}

fclose(hd_src); /* close the local file */

curl_global_cleanup();
return 0;
}


Alfred
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Daniel Stenberg
2010-07-06 17:10:18 UTC
Permalink
I am using libcurl 7.19.4 on Windows XP and I want to call a HTTP PUT
operation around 8000 times. After about 4000 requests curl_easy_perform()
returns with error 7 (CURLE_COULDNT_CONNECT, Couldn't Connect Error, Address
already in use).
While the reason sounds a bit strange, it certainly sounds as if you're simply
draining the resources from the target server so that you then can't connect
to it anymore. The error 7 is a failed TCP connection.
--
/ daniel.haxx.se
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Alfred Gebert
2010-07-07 08:57:27 UTC
Permalink
Post by Daniel Stenberg
I am using libcurl 7.19.4 on Windows XP and I want to call a HTTP PUT
operation around 8000 times. After about 4000 requests curl_easy_perform()
returns with error 7 (CURLE_COULDNT_CONNECT, Couldn't Connect Error, Address
already in use).
While the reason sounds a bit strange, it certainly sounds as if you're
simply draining the resources from the target server so that you then can't
connect to it anymore. The error 7 is a failed TCP connection.
The target server is my own program serving SOAP requests. The client
and the target server are running on the same machine.
I have no errors on the target server.

I will retest using Apache httpd as target server and running the
libcurl program on Linux.
Post by Daniel Stenberg
--
 / daniel.haxx.se
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Alfred Gebert
2010-07-07 10:21:35 UTC
Permalink
Post by Alfred Gebert
Post by Daniel Stenberg
I am using libcurl 7.19.4 on Windows XP and I want to call a HTTP PUT
operation around 8000 times. After about 4000 requests curl_easy_perform()
returns with error 7 (CURLE_COULDNT_CONNECT, Couldn't Connect Error, Address
already in use).
While the reason sounds a bit strange, it certainly sounds as if you're
simply draining the resources from the target server so that you then can't
connect to it anymore. The error 7 is a failed TCP connection.
The target server is my own program serving SOAP requests. The client
and the target server are running on the same machine.
I have no errors on the target server.
I will retest using Apache httpd as target server and running the
libcurl program on Linux.
I retested it with a simpler program executing a HTTP GET.

The target server is Apache httpd on Linux. The libcurl client on
Windows XP fails again (result 7 of curl_easy_perform(). Running the
libcurl client on Linux (OpenSuse 11.2 x86) is fine.

So in my opinion there is a limitation of libcurl running on Windows XP.

If you want to run the program you have to change the target server URL.

#include <stdio.h>
#include <curl/curl.h>

size_t write_callback( void* Buffer, size_t BufferSize, size_t
BufferCount, void* Stream)
{
/* do nothing */

return( BufferSize * BufferCount);
}

int main(void)
{
CURL *curl;
CURLcode res;

/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);

for( int i=0; i < 10000; i++)
{
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://gebert4.e2e.ch:1884/");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);

res = curl_easy_perform(curl);

if( res != 0)
{
printf( "%d request failed: %d\n", i+1, res);
return -1;
}

/* simple progress bar */
printf( ".");

/* always cleanup */
curl_easy_cleanup(curl);
}
else
{
printf( "init failed\n");
return -2;
}
}

curl_global_cleanup();

return 0;
}
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Adam Kellas
2010-07-07 13:08:52 UTC
Permalink
Post by Alfred Gebert
So in my opinion there is a limitation of libcurl running on Windows XP.
This may be merely an artifact of the test case, and your conclusion
about Windows XP seems correct, but I don't think you should need to
create and destroy the handle each time through the loop, and this may
contribute to some form of resource exhaustion. Any reason not to hoist
the curl_easy_init/curl_easy_cleanup calls out of the loop?

AK

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Alfred Gebert
2010-07-07 13:49:53 UTC
Permalink
Post by Alfred Gebert
So in my opinion there is a limitation of libcurl running on Windows XP.
This may be merely an artifact of the test case, and your conclusion about
Windows XP seems correct, but I don't think you should need to create and
destroy the handle each time through the loop, and this may contribute to
some form of resource exhaustion. Any reason not to hoist the
curl_easy_init/curl_easy_cleanup calls out of the loop?
If I put the curl_easy_init/curl_easy_cleanup calls out of the for
loop then it works.
Thank you.

At least this is a workaround. Perhaps I can modify my real codebase too.
AK
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Adam Kellas
2010-07-07 14:58:24 UTC
Permalink
Post by Alfred Gebert
At least this is a workaround. Perhaps I can modify my real codebase too.
It's not a workaround, it's the way libcurl is intended to be used.
Let's hope you can make the same change to your codebase.

AK

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Alfred Gebert
2010-07-12 15:21:43 UTC
Permalink
Post by Alfred Gebert
At least this is a workaround. Perhaps I can modify my real codebase too.
It's not a workaround, it's the way libcurl is intended to be used. Let's
hope you can make the same change to your codebase.
Yes, you are right. I should really call
curl_easy_init/curl_easy_cleanup only once.

But running my tests it worked with Apache httpd (HTTP/1.1) but not
with my own server using HTTP/1.0 without pipelining. For the 8000
request libcurl has to open 8000 socket connections.

Now I googled again and found the answer:

libcurl can't create additional outgoing TCP/IP connections because it
runs out of available port numbers for the IP address.
On Windows the default limitation is 5000 - 1024 open sockets (5000 is
the default max user port setting and the first 1024 ports are
reserved).

You can increase the default maximum socket value in the registry:

* Start Registry Editor (regedit.exe). Locate the following key in
the registry:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

* Add or change the following registry value:
Value Name: MaxUserPort Data Type: REG_DWORD Value: 60000
Valid Range: 5000-65534 (decimal) Default: 0x1388 (5000 decimal)

* Reboot the machine.

Microsoft description of MaxUserPort:
http://technet.microsoft.com/en-us/library/cc938196.aspx

Microsoft Exchange 2003 e. g. changes MaxUserPort to 60000
http://technet.microsoft.com/en-us/library/aa995661%28EXCHG.80%29.aspx.
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Daniel Stenberg
2010-07-12 16:05:57 UTC
Permalink
Post by Alfred Gebert
libcurl can't create additional outgoing TCP/IP connections because it
runs out of available port numbers for the IP address.
Really? libcurl's return code 7 is a connect failure, and by that time it
already got a socket to use. The _server_ however tries to create a new socket
at connect time and may fail if it runs out of them...
--
/ daniel.haxx.se
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Alfred Gebert
2010-07-13 07:52:29 UTC
Permalink
Post by Daniel Stenberg
Post by Alfred Gebert
libcurl can't create additional outgoing TCP/IP connections because it
runs out of available port numbers for the IP address.
Really? libcurl's return code 7 is a connect failure, and by that time it
already got a socket to use. The _server_ however tries to create a new
socket at connect time and may fail if it runs out of them...
The server had no error but the connect() of libcurl fails and error
is WSAEADDRINUSE (Address already in use).

The documentation of WSAEADDRINUSE is:
The socket's local address is already in use and the socket was not
marked to allow address reuse with SO_REUSEADDR. This error usually
occurs when executing bind, but could be delayed until the connect
function if the bind was to a wildcard address (INADDR_ANY or
in6addr_any) for the local IP address. A specific address needs to be
implicitly bound by the connect function.

http://msdn.microsoft.com/en-us/library/ms737625%28VS.85%29.aspx
Post by Daniel Stenberg
--
 / daniel.haxx.se
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html

Loading...