Maximum number of sockets

A

A Ma

I am using ActiveState Perl under Windows. The default maximum number of
sockets that I can open is 64. I found the parameter PERL_FD_SETSIZE in
c:\perl\lib\core\sys\socket.h. I changed that number but it did not take
effect. Is there something else I need to change? Do I need to recompile
anything?
 
U

Uri Guttman

ASU> That parameter is a reflection of the value obtained from the
ASU> system, not the determinant of the system's behavior. Changing
ASU> that value is the same thing as spray painting a highway speed
ASU> limit sign: It is not going to change the rules.

ASU> So, you can search Google for the information specific to your
ASU> operating system. I cannot, however, help but wonder why you
ASU> would want to open more than 64 sockets at a time by a single
ASU> application.

64 is a small number of sockets to have in a process. i wrote a large
scale crawler (in c) and it did over 2000 parallel fetches driven by an
event loop in a single process. but as you said any issues with the
maximum number of sockets is with the OS and the build of perl and not
with the language itself.

and your spray painting analogy is missing a point. i think he changed
the number in the socket.h file but i highly doubt he rebuilt perl with
it (given that it is an activestoat perl). so i would say it was more
like spraying graffiti in the air and expecting the speed limit to
change. :)

uri
 
B

Brian McCauley

A. Sinan Unur said:
That parameter is a reflection of the value obtained from the system, not
the determinant of the system's behavior.

You'd think so wouldn't you. But (in C) that's not the case with
FD_SETSIZE. The underlying select() is capable of coping with arbitrary
sized fdsets, the macro FD_SETSIZE just determines how such space is
allocated when you create an fdset.

You can just change FD_SETSIZE, recompile your program and it will can
have more sockets (I have actually done this in C on Windows).
Changing that value is the same
thing as spray painting a highway speed limit sign: It is not going to
change the rules.

Not quite. In this case I suspect it does change the rules, but you
need to make sure that everyone who needs to know the new rule has read
the sign. So I'm gussing you need to rebuild perl.
 
A

A Ma

Brian McCauley said:
You'd think so wouldn't you. But (in C) that's not the case with
FD_SETSIZE. The underlying select() is capable of coping with arbitrary
sized fdsets, the macro FD_SETSIZE just determines how such space is
allocated when you create an fdset.

You can just change FD_SETSIZE, recompile your program and it will can
have more sockets (I have actually done this in C on Windows).


Not quite. In this case I suspect it does change the rules, but you
need to make sure that everyone who needs to know the new rule has read
the sign. So I'm gussing you need to rebuild perl.

I suspect I have to recompile Perl but I am using ActiveState Perl and I
don't have the source. So I am not sure how I can do that. Any further
suggestions would be helpful.
 
S

Sisyphus

..
..
I suspect I have to recompile Perl but I am using ActiveState Perl and I
don't have the source. So I am not sure how I can do that. Any further
suggestions would be helpful.

You can get the source, too, from ActiveState ... or you can get the source
from www.perl.org.

Perl-5.8.8 builds easily from source on Win32 using the freely available
MinGW (gcc) compiler - just read the instructions in the Readme.win32 that's
in the top level folder of the perl source.

Looks like the source file you'll need to amend is
win32\include\sys\socket.h.

Cheers,
Rob
 
A

A Ma

Sisyphus said:
.
.

You can get the source, too, from ActiveState ... or you can get the
source
from www.perl.org.

Perl-5.8.8 builds easily from source on Win32 using the freely available
MinGW (gcc) compiler - just read the instructions in the Readme.win32
that's
in the top level folder of the perl source.

Looks like the source file you'll need to amend is
win32\include\sys\socket.h.

Cheers,
Rob
Thanks for the suggestion. I downloaded the source from ActiveState
(AP819-source), MinGW (5.0.2) and dmake (4.5). I followed the instructions
in Readme.win32, ran dmake and got the following error.

In file included from perllib.c:43:
perlhost.h: In function `CPerlHost* IPerlMem2Host(IPerlMem*)':
perlhost.h:239: warning: invalid access to non-static data member
`CPerlHost::m_
hostperlMem' of NULL object
perlhost.h:239: warning: (perhaps the `offsetof' macro was used incorrectly)
perlhost.h: In function `CPerlHost* IPerlMemShared2Host(IPerlMem*)':
perlhost.h:244: warning: invalid access to non-static data member
`CPerlHost::m_
hostperlMemShared' of NULL object
perlhost.h:244: warning: (perhaps the `offsetof' macro was used incorrectly)
perlhost.h: In function `CPerlHost* IPerlMemParse2Host(IPerlMem*)':
perlhost.h:249: warning: invalid access to non-static data member
`CPerlHost::m_
hostperlMemParse' of NULL object
perlhost.h:249: warning: (perhaps the `offsetof' macro was used incorrectly)
perlhost.h: In function `CPerlHost* IPerlEnv2Host(IPerlEnv*)':
perlhost.h:254: warning: invalid access to non-static data member
`CPerlHost::m_
hostperlEnv' of NULL object
perlhost.h:254: warning: (perhaps the `offsetof' macro was used incorrectly)
perlhost.h: In function `CPerlHost* IPerlStdIO2Host(IPerlStdIO*)':
perlhost.h:259: warning: invalid access to non-static data member
`CPerlHost::m_
hostperlStdIO' of NULL object
perlhost.h:259: warning: (perhaps the `offsetof' macro was used incorrectly)
perlhost.h: In function `CPerlHost* IPerlLIO2Host(IPerlLIO*)':
perlhost.h:264: warning: invalid access to non-static data member
`CPerlHost::m_
hostperlLIO' of NULL object
perlhost.h:264: warning: (perhaps the `offsetof' macro was used incorrectly)
perlhost.h: In function `CPerlHost* IPerlDir2Host(IPerlDir*)':
perlhost.h:269: warning: invalid access to non-static data member
`CPerlHost::m_
hostperlDir' of NULL object
perlhost.h:269: warning: (perhaps the `offsetof' macro was used incorrectly)
perlhost.h: In function `CPerlHost* IPerlSock2Host(IPerlSock*)':
perlhost.h:274: warning: invalid access to non-static data member
`CPerlHost::m_
hostperlSock' of NULL object
perlhost.h:274: warning: (perhaps the `offsetof' macro was used incorrectly)
perlhost.h: In function `CPerlHost* IPerlProc2Host(IPerlProc*)':
perlhost.h:279: warning: invalid access to non-static data member
`CPerlHost::m_
hostperlProc' of NULL object
perlhost.h:279: warning: (perhaps the `offsetof' macro was used incorrectly)
perlhost.h: In function `int PerlProcFork(IPerlProc*)':
perlhost.h:1838: error: invalid conversion from `void*' to `HWND__*'
dmake: Error code 129, while making 'perllib.o'


Any ideas?
 
S

Sisyphus

..
..
perlhost.h:1838: error: invalid conversion from `void*' to `HWND__*'
dmake: Error code 129, while making 'perllib.o'

ActiveState have patched that file (apparently in a way that breaks MinGW
:)


To get it to build, the exact change I made was to replace:

w32_pseudo_child_message_hwnds[w32_num_pseudo_children] =
(w32_message_hwnd == NULL) ? NULL : INVALID_HANDLE_VALUE;

with:

if (w32_message_hwnd == NULL)
w32_pseudo_child_message_hwnds[w32_num_pseudo_children] = NULL;
else w32_pseudo_child_message_hwnds[w32_num_pseudo_children] =
(HWND__*)INVALID_HANDLE_VALUE;

but it's probably easier to simply replace:

(w32_message_hwnd == NULL) ? NULL : INVALID_HANDLE_VALUE;

with:

(w32_message_hwnd == NULL) ? NULL : (HWND__*)INVALID_HANDLE_VALUE;

After that change, 'dmake' proceeded fine (though I haven't yet run 'dmake
test').

I hope the above change to perlhost.h is correct .... if you prefer to grab
the 5.8.8 source from www.perl.org, then you should be able to build it
without having to make *any* amendments to *any* files :)

(I'll submit a bug report about this to ActiveState.)

Cheers,
Rob
 
A

A Ma

Sisyphus said:
To get it to build, the exact change I made was to replace:

w32_pseudo_child_message_hwnds[w32_num_pseudo_children] =
(w32_message_hwnd == NULL) ? NULL : INVALID_HANDLE_VALUE;

with:

if (w32_message_hwnd == NULL)
w32_pseudo_child_message_hwnds[w32_num_pseudo_children] = NULL;
else w32_pseudo_child_message_hwnds[w32_num_pseudo_children] =
(HWND__*)INVALID_HANDLE_VALUE;

I made the change and was able to build a new version of Perl. However, the
change of PERL_FD_SETSIZE in socket.h didn't seem to make any difference. I
wonder if the Windows operating system imposes its own limit on the number
of sockets that can be opened by one program. In any case, I'll keep looking
into it but thanks for all your help,
 
S

Sisyphus

..
..
I made the change and was able to build a new version of Perl. However, the
change of PERL_FD_SETSIZE in socket.h didn't seem to make any difference.

You changed the socket.h that's in win32/sys (not wince/sys) ?
I can also find a lib/CORE/sys/socket.h - which I assume is the socket.h
that gets written for inclusion into the perl installation. Does the entry
for PERL_FD_SETSIZE in lib/CORE/sys/socket.h match the entry in
win32/sys/socket.h ?

It may well be that the task is not as simple as we've assumed ......

Cheers,
Rob
 
S

Sisyphus

..
..
Do they consider compatibility with MinGW a requirement of their
source code?

Good question - and I don't really know for sure, but I *think* they would
try to keep their code MinGW-compatible .... I guess time will tell :)

Cheers,
Rob
 
A

A Ma

May be I am hitting some other limit instead of FD_SETSIZE. This is my test
program:

my $pselect = IO::Select->new();

for ($i=0;$i<=100;$i++) {
my $port = $i + 500;
if ($server[$i] = IO::Socket::INET->new(LocalPort => $port,
Type => SOCK_STREAM,
Reuse => 1,
Listen => 10 )) {
$pselect->add($server[$i]);
} else {
print "Cannot open port $port.\n";
$server[$i] = 0;
}
}

$done = 0;
while ($done == 0) {
foreach $client ($pselect ->can_read(0.5)) {
my $newconn = 0;
for ($i=0;$i<=100;$i++) {
if ($client == $server[$i]) {
# accept a new connection
$client = $server[$i]->accept();
$pselect->add($client);
printf "Received a call on port %d\n", $i+500;
$newconn = 1;
}
}
}
}

This program listens to TCP ports 500 to 600. I can connect from ports 500
to 563. Beyond that, the test program cannot see the incoming connection.
Any ideas?
 
S

Sisyphus

..
..
May be I am hitting some other limit instead of FD_SETSIZE.

Did you check that FD_SETSIZE has in fact been set to your desired value ?

If socket.h contains:

#ifndef PERL_FD_SETSIZE
#define PERL_FD_SETSIZE 1000
#endif

then that means that PERL_FD_SETSIZE gets set to 1000 *only* if it was not
earlier defined. (I don't think it would have been defined earlier - but
it's probably a good idea to verify that.)

The following Inline::C script should print the actual value that
PERL_FD_SETSIZE is set to:

------------------------
use warnings;
use Inline C => Config =>
BUILD_NOISY => 1;

use Inline C => <<'EOC';

void get_size() {
printf("%d", PERL_FD_SETSIZE);
}

EOC

get_size();
 
S

Sisyphus

Sisyphus said:
.
.

Did you check that FD_SETSIZE has in fact been set to your desired value ?

If socket.h contains:

#ifndef PERL_FD_SETSIZE
#define PERL_FD_SETSIZE 1000
#endif

then that means that PERL_FD_SETSIZE gets set to 1000 *only* if it was not
earlier defined. (I don't think it would have been defined earlier - but
it's probably a good idea to verify that.)

Actually ... I've just found that winsock2.h (in the MinGW/include folder)
sets FD_SETSIZE to 64, so there's a chance that PERL_FD_SETSIZE *has* been
defined earlier. You might need to remove the first and third lines (quoted
above) from socket.h, and then re-compile perl.

Anyway - first check to see just what the actual value of PERL_FD_SETSIZE
is.


Cheers,
Rob
 
A

A Ma

Sisyphus said:
Anyway - first check to see just what the actual value of PERL_FD_SETSIZE
is.

A few updates:

1. I discovered that my immediate problem is unrelated to FD_SETSIZE. It
turns out that I had a problem with IO::Select. In my test program, if I do
the following instead:

my $pselect1 = IO::Select->new();
my $pselect2 = IO::Select->new();

for ($i=0;$i<=49;$i++) {
my $port = $i + 500;
if ($server1[$i] = IO::Socket::INET->new(LocalPort => $port,
Type => SOCK_STREAM,
Reuse => 1,
Listen => 10 )) {
$pselect1->add($server1[$i]);
} else {
print "Cannot open port $port.\n";
$server1[$i] = 0;
}

$port = $i + 550;
if ($server2[$i] = IO::Socket::INET->new(LocalPort => $port,
Type => SOCK_STREAM,
Reuse => 1,
Listen => 10 )) {
$pselect2->add($server2[$i]);
} else {
print "Cannot open port $port.\n";
$server2[$i] = 0;
}
}

then I can access all 100 ports. So IO::Select is limiting me to 64 sockets.


2. I wasn't able to run the In line C code. It seems to want to use "cl" as
the C compiler whereas I only have gcc from Mingw. I even tried copying
gcc.exe as cl.exe but the compiler options are different. I don't know how
to tell Inline to use a different compiler.


3. My original ActiveState Perl was installed in c:\perl. When I compiled my
own version, I changed INST_TOP to put it in c:\perl1. Then I changed the
path to point to c:\perl1\bin. But I think it is still going back to c:\perl
to look for some files. How do I switch between two different versions of
Perl?
 
S

Sisyphus

A Ma said:
Sisyphus said:
Anyway - first check to see just what the actual value of PERL_FD_SETSIZE
is.

A few updates:

1. I discovered that my immediate problem is unrelated to FD_SETSIZE. It
turns out that I had a problem with IO::Select. In my test program, if I do
the following instead:

my $pselect1 = IO::Select->new();
my $pselect2 = IO::Select->new();

for ($i=0;$i<=49;$i++) {
my $port = $i + 500;
if ($server1[$i] = IO::Socket::INET->new(LocalPort => $port,
Type => SOCK_STREAM,
Reuse => 1,
Listen => 10 )) {
$pselect1->add($server1[$i]);
} else {
print "Cannot open port $port.\n";
$server1[$i] = 0;
}

$port = $i + 550;
if ($server2[$i] = IO::Socket::INET->new(LocalPort => $port,
Type => SOCK_STREAM,
Reuse => 1,
Listen => 10 )) {
$pselect2->add($server2[$i]);
} else {
print "Cannot open port $port.\n";
$server2[$i] = 0;
}
}

then I can access all 100 ports. So IO::Select is limiting me to 64
sockets.

Heh ... hadn't thought of trying that :)
However, I think it still could possibly be FD_SETSIZE that's limiting you
to 64 sockets per object. (Mind you .... I don't even *know* whether
FD_SETSIZE has any effect on the number of sockets you can open :)
2. I wasn't able to run the In line C code. It seems to want to use "cl" as
the C compiler whereas I only have gcc from Mingw. I even tried copying
gcc.exe as cl.exe but the compiler options are different. I don't know how
to tell Inline to use a different compiler.

Seems odd. I think there *is* a way to get Inline to use the compiler of
choice - it should be mentioned in either 'perldoc Inline::C' or 'perldoc
Inline'.
But Inline::C should attempt to use the same compiler that was used to build
it - which in your case would be gcc. The inline::C that's being found (a
ppm ?) has apparently been built using cl.
3. My original ActiveState Perl was installed in c:\perl. When I compiled my
own version, I changed INST_TOP to put it in c:\perl1. Then I changed the
path to point to c:\perl1\bin. But I think it is still going back to c:\perl
to look for some files. How do I switch between two different versions of
Perl?

Yep - you just alter the path. Entering:
set PATH=C:\perl1\bin;%PATH%

will ensure that perl1\bin executable will be found. If you want to switch
back to C:\perl\bin you can just do:
set PATH=C:\perl\bin;%PATH%

You can always find out which perl you're running by entering:
perl -e "print $^X"

If the '.pl' extension has been associated the perl.exe in C:\perl\bin, then
altering the path to point to C:\perl1\bin won't change that - and if you
call a script by entering 'script.pl' instead of 'perl script.pl' you'll be
using C:\perl\bin, no matter which perl the path points to.

Cheers,
Rob
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top