关于Perl& amp;的问题Ruby套接字编程

时间:2011-05-30 16:58:12

标签: ruby perl sockets

以下是四个代码:

代码A :( Perl TCP服务器)

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>;
}'

代码B :( Perl TCP客户端)

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

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

代码C :( Ruby TCP服务器)

prompt> ruby -e '
require "socket"

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

代码D :( Ruby TCP客户端)

prompt> ruby -e '
require "socket"

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

以下问题使我感到困惑:

  1. 代码A和代码B可以同时运行。我认为它应该抛出一个“地址已被使用”错误,当后一个进程开始时,它与前一个进程绑定到同一个TCP端口。

  2. 代码C的两个(可能多于两个)实例可以同时运行,而我无法运行代码A的两个实例。

  3. 当代码A和代码C同时运行时,我通过谷歌浏览器访问了“http:// localhost:8008”,然后代码C打印了HTTP消息,而代码A则没有。

  4. 当我单独运行Code C时,代码B无法连接到它。

  5. 当我单独运行代码A时,代码D可以连接到它。

  6. 当代码A和代码C同时运行时,代码D连接到C,代码B连接A.

3 个答案:

答案 0 :(得分:1)

  

代码A和代码B可以同时运行。我认为它应该抛出一个“地址已经被使用”错误,当后一个进程开始时,它与前一个进程绑定到同一个TCP端口。

在这种情况下,地址不会发生冲突,只有端口。更具体地说,如果源端口是相同的。目标端口通常是相同的,因为它定义了服务可能存在的位置。

Ex:http服务器通常使用源端口80,目标端口为“randomized”。 http客户端通常使用目标端口80,源端口“随机化”。 (不是真正的随机,但这超出了问题的范围。)

  

当代码A和代码C同时运行时,我通过谷歌浏览器访问了“http:// localhost:8008”,然后代码C打印了HTTP消息,而代码A则没有。

这句话特别让我相信上面的代码实际上并没有被运行。特别是这一行:

  

s = TCPServer.new(“localhost”,8080)

这可以解释您所描述的大部分问题。尝试将每个文件放入文件并运行它们。你将减少从一次运行到另一次运行的拼写错误的可能性。

唯一尚未解决的问题是这个人:

  

代码C的两个(可能多于两个)实例可以同时运行,而我无法运行代码A的两个实例。

尝试运行lsof -Pni:8080(或您环境中的类似内容),以查看正在该端口上侦听的服务。

Ruby脚本似乎存在双栈问题。它默认为IPv6 localhost,然后是IPv6 site-local,最后是IPv4 localhost。它看起来好像是在内部指定源地址。

Perl脚本运行正常。它很可能用in6addr_any打开一个套接字并在v4和v6上轻松收听。

答案 1 :(得分:1)

代码A和代码B可以同时运行。我认为它应该抛出一个“地址已被使用”错误,当后一个进程开始绑定到与前一个进程相同的TCP端口时。

服务器绑定到127.0.0.1:8080,客户端绑定到127.0.0.1:&lt;某些自由端口&gt; (因为您没有请求将客户端绑定到特定的端口)。 127.0.0.1:8080!= 127.0.0.1:<有些免费端口&gt;,所以没问题。

代码C的两个(可能多于两个)实例可以同时运行,而我不能运行代码A的两个实例。

您不能运行两个以上的“C”工作实例。将两个套接字绑定到同一IP地址和端口是不可能的。这就像试图给两个人一样的邮寄地址。

当代码A和代码C同时运行时,我通过谷歌浏览器访问了“http:// localhost:8008”,然后代码C打印了HTTP消息,而代码A没有。

当然。因为“C”管理绑定到127.0.0.1:8080,“A”不能并且死亡。

当我单独运行Code C时,代码B无法连接到它。

我不明白为什么。你得到什么错误?

答案 2 :(得分:0)

当我在一个文件中尝试使用上面代码中的一个修改

  • Ruby Client&lt; - &gt; Ruby服务器是成功的
  • Perl客户端&lt; - &gt; Perl Server成功
  • Ruby Client&lt; - &gt; Perl Server成功
  • Perl客户端&lt; - &gt; Ruby Server FAILED

我得到了以下错误..

  • “无法建立连接,因为目标计算机是主动的 拒绝了。在pc.pl第4行。“

所以我想知道发生了什么!所以我检查了一个不同的客户端程序,它仍然没有连接到Ruby客户端服务器。所以我想首先关注ruby服务器

示例套接字测试程序: 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客户端:(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 $_
}

其他参考代码:

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客户端:

require "socket"

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

FIX

我家里连接了3个系统,将localhost替换为当前PC的实际IP解决了这个问题。 (WINDOWS中的ipconfig获取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客户:

#!/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 $_
}

亚伯拉罕先生