开发者

Questions about Perl & Ruby Sockets Programming

Here are four codes:

Code A: (Perl TCP Server)

prompt> perl -e '
use IO::Socket;

$s = IO::Socket::INET->new(LocalPort => 8080, Type => SOCK_STREAM, Reuse => 1, Listen => 10, Proto => "tcp") or die "$!";
while ($c = $s->accept) {
   print while <$c>;
}'

Code B: (Perl TCP Client)

prompt> perl -e '
use IO::Socket;

$c = IO::Socket::INET->new(PeerAddr => "localhost:8080") or die "$!";
while (<>) {
   print $c $_
}'

Code C: (Ruby TCP Server)

prompt> ruby -e '
require "socket"

s = TCPServer.new("localhost", 8080)
while( c = s.accept)
    while l = c.gets
       puts l
    end
end'

Code D: (Ruby TCP Client)

prompt> ruby -e '
require "socket"

c = TCPSocket.new("localhost", 8080)
while l = gets
   c.puts l
end'

The following issues confused me:

  1. Code A and Code B can be run simultaneously. I thought it should threw an "Address already be used" Error when the latter process starts which bind to the same TCP port with former process.

  2. Two (maybe more than two) instance of Code C can be run simulataneously, while I can't run two instance of Code A.

  3. while Code A and Code C were being running simultaneously, I visited "http://localhost:8008" via Google Chrome, then Code C printed the HTTP messages, while Code A did not.

  4. while I run Code C singlehandedly, Code B can not connect to it.

    开发者_如何学运维
  5. while I run Code A singlehandedly, Code D can connect to it.

  6. while Code A and Code C were being running simultaneously, code D connected to C and Code B connected A.


Code A and Code B can be run simultaneously. I thought it should threw an "Address already be used" Error when the latter process starts which bind to the same TCP port with former process.

The addresses wouldn't conflict in this situation, only ports. More specifically, if the source ports were the same. Destinations ports are regularly the same, as this defines where a service may exist.

Ex: http servers generally use source port 80 with destination ports "randomized". http clients generally use destination port 80 with source ports "randomized". (Not truly random, but that's beyond the scope of the question.)

while Code A and Code C were being running simultaneously, I visited "http://localhost:8008" via Google Chrome, then Code C printed the HTTP messages, while Code A did not.

This statement in particular leads me to believe the code above wasn't actually was was ran. Specifically this line:

s = TCPServer.new("localhost", 8080)

This would explain most of the issues you're describing. Try putting each of these into files and running them. You'll lessen the possibility of typos from one run to the next.

The only remaining unsolved issue is this guy:

Two (maybe more than two) instance of Code C can be run simulataneously, while I can't run two instance of Code A.

Try running lsof -Pni:8080 (or something similar in your environment), to see what services are listening on that port.

There appears to be a dual-stack issue with the Ruby script. It's defaulting to IPv6 localhost, then IPv6 site-local, and lastly IPv4 localhost. It's looks as if it's specifying the source address internally.

The Perl script is functioning correctly. It's likely opening a socket with in6addr_any and listening comfortably on v4 and v6.


Code A and Code B can be run simultaneously. I thought it should threw an "Address already be used" Error when the latter process starts which bind to the same TCP port with former process.

The server is bound to 127.0.0.1:8080, and the client is bound to 127.0.0.1:<some free port> (since you didn't request to bind the client to a specific a port). 127.0.0.1:8080 != 127.0.0.1:<some free port>, so no problem.

Two (maybe more than two) instance of Code C can be run simulataneously, while I can't run two instance of Code A.

You can't run more than two working instances of "C". It's impossible to have two sockets bound to the same IP address and port. It's like trying to give two people the same mailing address.

while Code A and Code C were being running simultaneously, I visited "http://localhost:8008" via Google Chrome, then Code C printed the HTTP messages, while Code A did not.

Of course. Because "C" manged to bind to 127.0.0.1:8080, "A" can't and dies.

while I run Code C singlehandedly, Code B can not connect to it.

I don't see why. What error do you get?


When I tried it in a file with one modification from above code

  • Ruby Client <-> Ruby server was Success
  • Perl Client <-> Perl Server was Success
  • Ruby Client <-> Perl Server was Success
  • Perl Client <-> Ruby Server FAILED

I got the below Error..

  • "No connection could be made because the target machine actively refused it. at pc.pl line 4."

So I was wondering what was going on!!! So I checked with a different client program and it was still not connecting to the Ruby client server. So I thought to focus on ruby server first

sample Socket Tester: http://sourceforge.net/projects/sockettest/

Ruby Server:

s = TCPServer.new("localhost", 20000)
while( c = s.accept)
    while l = c.gets
        puts l
    end
end

Perl Client:(pc.pl)

#!/usr/bin/perl
use IO::Socket::INET;
print "Client\n";
$c = IO::Socket::INET->new(PeerAddr => "localhost:20000") or die "$!";
while (<>) {
    print $c $_
}

The other code for reference:

Perl Server:

#!/usr/bin/perl
use IO::Socket::INET;
print "Server\n";
$s = IO::Socket::INET->new(LocalPort => 20000, Type => SOCK_STREAM, Reuse => 1, Listen => 10, Proto => "tcp") or die "$!";
while ($c = $s->accept) {
    print while <$c>;
}

Ruby Client:

require "socket"

c = TCPSocket.new("localhost", 20000)
while l = gets
    c.puts l
end

The FIX

I had 3 systems connected in my house and replacing localhost to the actual IP of the current PC resolved the issue. (ipconfig in WINDOWS to get the IP)

Ruby Server:

require "socket"

s = TCPServer.new("192.168.1.3", 20000)
while( c = s.accept)
    while l = c.gets
       puts l
    end
end

Perl Client:

#!/usr/bin/perl
use IO::Socket::INET;

print "Client\n";
$c = IO::Socket::INET->new(PeerAddr => "192.168.1.3:20000") or die "$!";
while (<>) {
   print $c $_
}

Thx Abraham

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜