Написание клиента TCP

Проблема

Вы хотите подключиться к сокету на удаленном компьютере.

Решение

Следующее решение предполагает, что связь осуществляется через Интернет.
Либо воспользуйтесь стандартным (для версии 5.004) классом IO::Socket::INET:
use IO::Socket;
$socket = IO::Socket::INET->new(PeerAddr => $remote_host,
                                PeerPort => $remote_port,
                                Proto    => "tcp",
                                Type     => SOCK_STREAM)
  or die "Couldn't connect to $remote_host:$remote_port : $@\n";
# ... Сделать что-то с сокетом
print $socket "Why don't you call me anymore?\n";
$answer = <$socket>;
# Отключиться после завершения
close($socket);
либо создайте сокет вручную, чтобы лучше управлять его поведением:
use Socket;
# Создать сокет
socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
# Построить адрес удаленного  компьютера
$internet_addr = inet_aton($remote_host)
or die "Couldn't convert $remote_host into an Internet address: $!\n";
$paddr = sockaddr_in($remote_port, $internet_addr);
# Подключиться
connect(TO_SERVER, $paddr)
  or die "Couldn't connect to $remote_host:$remote_port : $!\n";
#  ...  Сделать что-то с сокетом
print TO_SERVER "Why don't you call me anymore?\n";
# И отключиться после завершения
close(TO_SERVER);

Комментарий

Ручное кодирование состоит из множества действий, а класс IO::Socket::INET объединяет их все в удобном конструкторе. Главное, что необходимо знать, — куда вы направляетесь (параметры PeerAddr и PeerPort) и каким образом (параметр Туре). По переданной информации IO::Socket::INET пытается узнать все остальное. Так, протокол по возможности вычисляется по типу и номеру порта; если это не удается сделать, предполагается протокол tcp.
Параметр PeerAddr содержит строку с именем хоста ("www.oreilly.com") или его IP-адресом ("204.148.40.9"). PeerPort — целое число, номер порта для подключения. Номер порта можно включить в адрес в виде "www.oreilly.com:80". Параметр Туре определяет тип создаваемого сокета: SOCK_DGRAM для датаграммного сокета или SOCK_STREAM для потокового.
Чтобы подключиться через SOCK_STREAM к порту конкретного компьютера, не поддерживающего других возможностей, передайте IO::Socket::INET->new одну строку с именем хоста и портом, разделенными двоеточием:
$client = IO::Socket::INET->new("www.yahoo.com:80")
  or die $@;
При возникновении ошибки IO::Socket::INET возвращает undef, а переменной $@ (не $!) присваивается сообщение об ошибке.
$s = IO::Socket::INET->new(PeerAddr => "bad.host.com",
                           PeerPort => 80,
                           Type     => SOCK_STREAM )
     or die $@;
Если ваши пакеты бесследно исчезают в глубинах сети, вероятно, невозможность подключения к порту будет обнаружена лишь через некоторое время. Вы можете уменьшить этот промежуток, передавая параметр Timeout при вызове IO::Socket::INET->new():
$s = IO::Socket::INET->new(PeerAddr => "bad.host.com",
                           PeerPort => 80,
                           Туре         => SOCK_STREAM,
                           Timeout    => 5 )
     or die $@;
Но в этом случае вы уже не сможете использовать $! или $@, чтобы узнать причину неудачи — невозможность подключения или тайм-аут. Иногда бывает удобнее установить тайм-аут вручную, без использования модуля.
INADDR_ANY — специальный адрес, означающий «прослушивание на всех интерфейсах». Если вы хотите ограничить его конкретным IP-адресом, включите параметр LocalAddr в вызов IO::Socket::INET->new. При ручном кодировании это делается так:
$inet_addr = inet_aton("208.146.240.1);
$paddr     = sockaddr_in($port, $inet_addr);
bind(SOCKET, $paddr) or die "bind:  $!";
Если вам известно только имя, действуйте следующим образом:
$inet_addr = gethostbyname("www.yahoo.com")
  or die "Can't resolve www.yahoo.com:  $!";
$paddr = sockaddr_in($port, $inet_addr):
bind(SOCKET, $paddr) or die "bind:  $!";

См. также

Описание функций socket, bind и connect



2013-09-10 17:05:19

Proverte kod v komentariyah gde pro list tam oshibki detskie




Оставить комментарий:
Ваше Имя:
Email:
Антибот: *  
Ваш комментарий: