karstenda has asked for the wisdom of the Perl Monks concerning the following question:

Hi, thanks in advance for reading this!


Let me first explain the situation:

I'm trying to create a sort of instant messenger with perl using sockets, therefore i created two perl scripts (sender.pl and receiver.pl). They work as following: PC 1 (runs sender.pl) will send a socket (containing the message) to another PC 2 (runs receiver.pl) who will read and print the message from the incoming socket.

Problem:

My scripts are working fine as long as both PC1 and PC2 are in the same local network (using local IP). If I want to send my sockets over the internet however my script fails. I think I misconfigured the 'PeerAddr' and the 'LocalAddr' in sender.pl.
The port that I'm using in my script to send the socket over (7070) is an open port on the router of PC2, so this can't be the problem I think ...

Question:

Is it possible to send peer to peer messages with sockets? If yes, how do I do it? What's my fault?

I have to admit that this is the first time I program with sockets and I'm not really familiar with this kind of perl programming. I just the main part of this script from a website. The tutorials and searches I read about this subject (believe me I did!) weren't really helpfull, in all example scripts is PC 2 (receiver.pl) is just a webserver.

sender.pl
#!/usr/bin/perl -w use IO::Socket; $message="Hello server!" #Message you send to server my $sock = new IO::Socket::INET ( PeerAddr => "$ip", #The IP of the network of PC2 LocalAddr => "$localip", #The IP of PC2 in the local network PeerPort => '7070', Proto => 'tcp',); die "Could not create socket: $!\n" unless $sock; print $sock "$message\n"; close($sock);}
receiver.pl
#!/usr/bin/perl -w use IO::Socket; my $sock = IO::Socket::INET->new( Proto => 'tcp', LocalPort => 7070, Listen => 1, Reuse => 1, Type => SOCK_STREAM ) or die "Can't create listen socket: $!"; my $new_sock = $sock->accept(); while(<$new_sock>) {$message = $_} close($sock); print "$message";

This is my first post on this forum and I would be really thankfull if you could help me with this problem.

Replies are listed 'Best First'.
Re: Sending Socket peer to peer
by zwon (Abbot) on Dec 07, 2008 at 11:42 UTC

    It's seems you misunderstood what LocalAddr is. LocalAddr is the address that sender should use as source address, you can specify it if PC1 has several IP and you want to use one of them. PeerAddr should be the address of PC2, what do you mean by "IP of the network of PC2". If PC2 has local IP, you can't directly connect to it over the internet. You should use SOCKS or some sort of NAT on router to be able to connect to PC2 in this case. What kind of router do you use?

      Building on what zwon said...

      The LocalAddr is the source address; the PeerAddr is the destination address. If PC2 has a private address (falling in one of these ranges: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16; aka an RFC1918 address), then it cannot be reached directly from outside its local network. In that case, PeerAddr needs to be the address of the router for PC2's network. Additionally, you must create a mechanism for traffic arriving on port 7070 of the router to be forwarded to port 7070 on PC2.

      On most appliance routers for the home (e.g. Linksys WRT54G), this is called port forwarding. There is usually a configuration page for this in the router setup (on some routers, this may be hidden behind an "advanced" setup tab).

      On other routers, port forwarding is usually called DNAT (destination network address translation) because the router will rewrite the destination address of forwarded packets with the private address for PC2 (which is reachable from its router).

      Here, we see a big limitation of NAT (network address translation). Only one host behind a router can receive traffic to port 7070. It is possible to map other ports (e.g., 7071) to port 7070 on host PC3, but the protocol must allow for PC1 to send to PC3 via a port other than 7070.

      If these limitations are too limiting, another approach is to create a VPN (virtual private network; e.g., openvpn, IPsec). This could be used to create a direct path from PC1 to PC2 and PC3, though there are important security implications to this type of approach that far exceed the scope of this post.

        Thank you verry much, this is really helpfull post!

Re: Sending Socket peer to peer
by zentara (Cardinal) on Dec 07, 2008 at 14:33 UTC
    It's easy for a beginner to get the concept of server and receiver confused. The correct terms are server and client. The server opens up the port and waits for incoming connections. The client "dials up" the server's IP address, and connects. So here is a server, note it just opens a port, and knows it's own ip address.
    #!/usr/bin/perl #This is a version that can read and write #from as many clients as your machine supports. use strict; use warnings; use IO::Socket; my $server = IO::Socket::INET->new ( LocalPort => 1337, Type => SOCK_STREAM, Reuse => 1, Listen => 5 ) or die "could not open port\n"; warn "server ready waiting for connections..... \n"; my $client; while ($client = $server->accept()) { my $pid; while (not defined ($pid = fork())) { sleep 5; } if ($pid) { close $client; # Only meaningful in the client } else { $client->autoflush(1); # Always a good idea close $server; &do_your_stuff(); } } sub do_your_stuff { warn "client connected to pid $$\n"; while(my $line = <$client>) { print "client> ", $line; print $client "pid $$ > ", $line; } exit 0; }

    Now a client to connect, note you specify the ip address and port.

    #!/usr/bin/perl use IO::Socket::INET; use strict; my $socket = new IO::Socket::INET(Proto => "tcp", PeerAddr => 192.168.0.15, PeerPort => 1337); while (1) { print $socket "1234\n"; my $msg = <$socket>; print $msg; sleep(5); }

    I'm not really a human, but I play one on earth Remember How Lucky You Are
Re: Sending Socket peer to peer
by gone2015 (Deacon) on Dec 07, 2008 at 12:23 UTC
    Is it possible to send peer to peer messages with sockets? If yes, how do I do it? What's my fault?

    The magic of sockets is that it doesn't matter whether the other end is the same machine (loop-back address), a machine on the same LAN ("public" or "private" IP address) or a long way away ("public" IP address). So you are right to be puzzled...

    What does matter is that (a) the client has a working address for the server, (b) the network in between is prepared to deliver packets between the two and (c) the server is prepared to accept connections from the client -- given the address the server is listening on, and the address the client is attempting to connect from.

    I cannot tell whether you have an address problem here. You might be able to resolve that using good old-fashioned ping/traceroute. You can also poke at servers using telnet. In this day and age you should also consider whether some firewall is taking a dim view of the packets -- particularly at the server end. Also, the server itself may be "wrapped" against connections from outside the local network.

Re: Sending Socket peer to peer
by Anonymous Monk on Dec 07, 2008 at 10:16 UTC
    What's my fault?
    Its here I want to send my sockets over the internet however my script fails.
    You need to find out why/how, in other words what is the error message/code.
Re: Sending Socket peer to peer
by karstenda (Acolyte) on Dec 07, 2008 at 23:01 UTC

    Thank you for answering my post!!!

    You've given me enough information to keep me busy for a while!!!