Написание клиента 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
Proverte kod v komentariyah gde pro list tam oshibki detskie
Оставить комментарий:
|
|