Вопросы о программировании на Perl & Ruby Sockets - PullRequest
2 голосов
/ 30 мая 2011

Вот четыре кода:

Код A: (TCP-сервер Perl)

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 Server)

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" через Google Chrome, затем код C напечатал сообщения HTTP, а код A - нет.

  4. пока я запускаю код C в одиночку, код B не может подключиться к нему.

  5. пока я запускаю Code A в одиночку, Code D может подключиться к нему.

  6. при одновременном использовании кода A и кода C, код D подключен к C, а код B подключен A.

Ответы [ 3 ]

1 голос
/ 31 мая 2011
Код A и код B могут быть запущены одновременно. Я думал, что это должно выдать ошибку «Адрес уже используется», когда запускается последний процесс, который привязывается к тому же порту TCP с прежним процессом.

Сервер связан с 127.0.0.1:8080, а клиент связан с 127.0.0.1:< некоторый свободный порт> (поскольку вы не запрашивали привязку клиента к определенному порту). 127.0.0.1:8080! = 127.0.0.1:< некоторый свободный порт>, поэтому нет проблем.

Два (возможно, более двух) экземпляра кода C могут быть запущены одновременно, в то время как я не могу запустить два экземпляра кода A.

Вы не можете запустить более двух рабочих экземпляров "C". Невозможно привязать два сокета к одному IP-адресу и порту. Это все равно что пытаться дать двум людям один и тот же почтовый адрес.

когда код А и код C работали одновременно, я посетил "http://localhost:8008" через Google Chrome, затем код С напечатал сообщения HTTP, а код А - нет.

Конечно. Поскольку «С» удалось связать с 127.0.0.1:8080, «А» не может и умирает.

пока я запускаю код C в одиночку, код B не может подключиться к нему.

Не понимаю, почему. Какую ошибку вы получаете?

1 голос
/ 30 мая 2011

Код A и код B могут быть запущены одновременно. Я думал, что это должно выдать ошибку «Адрес уже используется», когда запускается последний процесс, который связывается с тем же портом TCP с прежним процессом.

В этой ситуации адреса не конфликтуют, только порты. Более конкретно, если исходные порты были одинаковыми. Порты назначения обычно одинаковы, так как это определяет, где может существовать служба.

Пример: http-серверы обычно используют исходный порт 80 с портами назначения "рандомизированными". Клиенты http обычно используют порт назначения 80 с портами источника "рандомизированными" (Не совсем случайно, но это выходит за рамки вопроса.)

когда код А и код С работали одновременно, я посетил "http://localhost:8008" через Google Chrome, затем код С напечатал сообщения HTTP, а код А - нет.

Это утверждение, в частности, заставляет меня поверить, что приведенный выше код на самом деле не был запущен. Конкретно эта строка:

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

Это объяснит большинство проблем, которые вы описываете. Попробуйте поместить каждый из них в файлы и запустить их. Вы уменьшите вероятность опечаток от одного пробега к следующему.

Единственная нерешенная проблема - этот парень:

Два (возможно, более двух) экземпляра кода C могут быть запущены одновременно, в то время как я не могу запустить два экземпляра кода A.

Попробуйте запустить lsof -Pni: 8080 (или что-то подобное в вашей среде), чтобы увидеть, какие службы прослушивают этот порт.

Кажется, есть проблема с двойным стеком со скриптом Ruby. По умолчанию используется локальный хост IPv6, затем локальный сайт IPv6 и, наконец, локальный хост IPv4. Похоже, что он указывает адрес источника внутри.

Perl-скрипт работает правильно. Вероятно, он открывает сокет с in6addr_any и комфортно слушает на v4 и v6.

0 голосов
/ 15 марта 2014

Когда я попробовал это в файле с одной модификацией, описанной выше, код

  • Ruby Client <-> Сервер Ruby был успешным
  • Клиент Perl <-> Сервер Perl был успешным
  • Ruby Client <-> Сервер Perl был успешным
  • Клиент Perl <-> Ruby Server FAILED

Я получил следующую ошибку ..

  • "Невозможно установить соединение, поскольку целевая машина активно отказывала в этом. На стр. 4 pc.pl."

Так что мне было интересно, что происходит !!!Поэтому я проверил другую клиентскую программу, и она все еще не подключалась к клиентскому серверу Ruby.Поэтому я подумал о том, чтобы сначала сосредоточиться на сервере ruby ​​

образец 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: (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:

#!/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

ИСПРАВЛЕНИЕ

У меня было 3 системы, подключенные к моему дому, и замена localhost на фактический IP-адрес текущего ПК решила проблему.(ipconfig в WINDOWS для получения IP)

Сервер Ruby:

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 $_
}

Спасибо Абрахаму

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...