2014-03-03 85 views
2

我寫了一個網絡課的小程序,遇到了一些困惑。IO ::套接字與套接字我「使用」兩者?

我目前正在使用的東西,但在我發現的perl網絡示例中看到了一些不一致之處。

有的人導入Socket模塊,有的導入IO :: Socket模塊。更令人困惑的是,一些導入Socket和IO :: Socket。

有沒有重點?我以爲IO :: Socket會導入Socket?

我問,因爲我試圖使用一個函數「getaddrinfo()」,它不停地大喊我的「未定義的子程序& main :: getaddrinfo調用./tcp_server.pl行13」。它在Socket perldoc中。

我通過手動指定主機IP來得到它,但我希望它自動檢索運行它的機器的主機IP。有什麼建議?

這裏是我的代碼:

#!/usr/bin/perl 

# Flushing to STDOUT after each write 
$| = 1; 

use warnings; 
use strict; 
use Socket; 
use IO::Socket::INET; 


# Server side information 
# Works with IPv4 addresses on the same domain 
my ($err, @res) = getaddrinfo(`hostname`); #'128.101.38.191'; 
my $listen_port = '7070'; 
my $protocal  = 'tcp'; 
my ($socket, $client_socket); 
my ($client_address, $client_port); 
# Data initializer 
my $data = undef; 


# Creating interface 
$socket = IO::Socket::INET->new (
LocalHost => shift @res, 
LocalPort => $listen_port, 
Proto  => $protocal, 
Listen  => 5, 
Reuse  => 1, 
) or die "Socket could not be created, failed with error: $!\n"; # Prints error code 

print "Socket created using host: @res \n"; 
print "Waiting for client connection on port $listen_port\n"; 

while(1) { 
    # Infinite loop to accept a new connection 
    $client_socket = $socket->accept() 
     or die "accept error code: $!\n"; 

# Retrieve client information 
$client_address = $client_socket->peerhost(); 
$client_port = $client_socket->peerport(); 

print "Client accepted: $client_address, $client_port\n"; 

# Write 
$data = "Data from Server"; 
print $client_socket "$data\n"; 

# Read 
$data = <$client_socket>; 
print "Received from client: $data\n"; 

} 
$socket->close(); 
+0

爲什麼使用'getaddrinfo'?只需將主機名傳遞給'LocalHost' – ikegami

+0

我想獲取IP地址。當我使用實際的主機名時,我似乎無法使其工作。 – rusty

+0

你忘記刪除尾隨換行符了嗎? – ikegami

回答

4

這是隻使用IO ::插座容易得多:

use strict; 
use warnings; 
use IO::Socket::INET; 
my $server = IO::Socket::INET->new(
    LocalPort => 7080, 
    Listen => 10, 
    Reuse => 1 
) or die $!; 
while (1) { 
    my $client = $server->accept or next; 
    print $client "foo\n"; 
} 

如果你想要做的IPv6只需更換IO ::插座:: INET與IO ::插座:: IP或IO ::插座:: INET6。如果您稍後想在套接字上使用SSL,請用IO :: Socket :: SSL替換它並添加一些證書。這是一個開銷,但更少的代碼編寫和更容易理解。

+0

我不知道我可以完全省略IP時,使我的插座。這很有道理,但我認爲我早些時候嘗試過,但有另一個問題,並認爲缺少IP是原因。謝謝! – rusty

3

你需要從插槽導入getaddrinfo()。見the docs

use Socket 'getaddrinfo'; 

你可能想在Linux系統上使用的Sys::Hostname代替`hostname`。不需要爲此而分叉。

+2

更好使用Sys :: Hostname –

+0

感謝您指出,@Steffen。我會在漢諾威給你買一瓶啤酒。 :) – simbabque

+0

這可以讓它工作!現在我有一個問題打印存儲在@res中的IP ... – rusty