chapter 4 a tourist’s guide to socket programming in perl

37
Chapter 4 http://www.lonsteins.com/articles/soc kets.pdf A Tourist’s Guide to Socket Programming in Perl

Post on 15-Jan-2016

222 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Chapter 4

http://www.lonsteins.com/articles/sockets.pdf

A Tourist’s Guide to Socket Programming in Perl

Page 2: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

TCP Protocol:

• Typical TCP client program

• call socket() to create socket• call connect() to connect to peer• send and receive data• close the socket.sets up socket

structure on this side of connection

starts three-wayhandshake and waitsfor completion

sends FIN flag fromthis side of connection

Page 3: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

echo client 1 (1):

#!/usr/bin/perl# file: tcp_echo_cli1.pl# Figure 4.1: A TCP Echo Client

# usage: tcp_echo_cli1.pl [host] [port]

use strict;use Socket;use IO::Handle;my ($bytes_out,$bytes_in) = (0,0);

my $host = shift || 'localhost';my $port = shift || getservbyname('echo','tcp');

my $protocol = getprotobyname('tcp');$host = inet_aton($host) or die "$host: unknown host";

Page 4: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

echo client 1 (2):

socket(SOCK, AF_INET, SOCK_STREAM, $protocol) or die "socket() failed: $!";my $dest_addr = sockaddr_in($port,$host);connect(SOCK,$dest_addr) or die "connect() failed: $!";

SOCK->autoflush(1);

while (my $msg_out = <>) { print SOCK $msg_out; my $msg_in = <SOCK>; print $msg_in;

$bytes_out += length($msg_out); $bytes_in += length($msg_in);}

close SOCK;print STDERR "bytes_sent = $bytes_out, bytes_received = $bytes_in\n";

Page 5: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

TCP function:

• Given all four arguments, socket() creates a local socket and associates it with the handle.

• On error, returns undef. • Typical idiom is

$boolean = socket(SOCKET,$domain,$type,$protocol);

socket(SOCK,AF_INET,SOCK_STREAM, scalar getprotobyname(‘tcp’))

# AF_INET, SOCK_STREAM defined in Socket # the last three arguments are all small integers

Page 6: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

TCP client function:

• Used with TCP. SOCKET must exist and address is packed and built with sockaddr_in() function.

• On error, returns false and $! has error number. • Local port is chosen at from ephemeral port numbers.• Illegal to call connect() twice on same socket handle. if

done, returns EISCONN (“Transport is endpoint already connected”).

• Starts three-way handshake process and waits until completed one way of the other.

$boolean = connect(SOCKET,$dest_addr);

Page 7: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

TCP functions (cont):

• Works with sockets as well as files. After closing a socket it can neither be written to nor read from.

• On error, returns undef and $! has error number. • At the remote end of the connection reading will result in

EOF while writing results in broken PIPE signal. • The broken PIPE signal is received at remote end

regardless of additional write by remote end.• Does not parallel actual socket behaviour where both

ends must send a FIN flag and sending a FIN only means you will not write any more. You may still read.

$boolean = close(SOCKET);

Page 8: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

What happens with close(SOCK):

application

tcp

socket: connection to application closedclose(SOCK)

send FIN: theoretically can still receive data

any data that arrives later, TCPknows the socket is closed andso replies as though it were neveropen in the first place by sendinga RST. No automatic RST.

data arrivesafter close()

TCP/IPStack

Page 9: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

close(SOCKET);

• Works as expected!!

printf "shutting down...\n";close(SOCK); # close for read$msg_in = <SOCK>;if ( ! defined $msg_in ) { printf "read failed\n";} else { print "read: $msg_in\n"; }

print SESSION $msg_out; $bytes_out += length($msg_out); last; } sleep(1); print SESSION "again: $msg_out\n"; # print a second time

sever code

client code

this line executed:

asd dsa shutting down... read failed

first server send

second server send

Page 10: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

close() ethereal dump:

packets 1-3: 3WHS

packet 4: client sends 4 char

packet 6: server echoes 4 char

client: port 35192server: port 2007

packet 10: server sends 12 more char

packet 11: client sends RST

packet 8: close first to FIN

Page 11: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

TCP function (cont):

• Can more precisely mirror TCP behaviour.• $how = 0: Closes socket for reading.• $how = 1: Closes socket for writing (TCP behaviour).• $how = 2: Closes socket for reading and writing (like

close())

$boolean = shutdown(SOCKET,$how);

Page 12: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

shutdown(SOCKET,0);

• Does not work as advertised!!

printf "shutting down...\n";shutdown(SOCK,0); # close for read$msg_in = <SOCK>;if ( ! defined $msg_in ) { printf "read failed\n";} else { print "read: $msg_in\n"; }

print SESSION $msg_out; $bytes_out += length($msg_out); last; } sleep(1); print SESSION "again: $msg_out\n"; # print a second time

server code

client code

this line executed:

asd dsa shutting down... read: again: dsa

first server send

second server send

Page 13: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

ethereal dump:

packets 1-3: 3WHS

packet 4: client sends 4 char

packet 6: server echoes 4 char

client: port 35188server: port 2007

packet 8: server sends 12 more char

packet 9: client ACKs 12 char

packet 10: server first to FIN

Page 14: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

shutdown(SOCKET,1):

• Works as advertised.• Client sends FIN and waits for FIN/ACK.• This is the best option to mimic the behaviour of TCP in

your own application.

Page 15: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

shutdown(SOCKET,2);

• Works as advertised.

printf "shutting down...\n";shutdown(SOCK,2); # close for read/write$msg_in = <SOCK>;if ( ! defined $msg_in ) { printf "read failed\n";} else { print "read: $msg_in\n"; }

print SESSION $msg_out; $bytes_out += length($msg_out); last; } sleep(1); print SESSION "again: $msg_out\n"; # print a second time sleep(3); print SESSION "again: $msg_out\n"; # print a second time

server code

client code

this line executed:

asd dsa shutting down... read failed

first server send

second server send

third server send

NOTE: 2nd server write sends anddid not cause error; BROKENPIPE SIGNAL arrived later. 3rd server write resulted in errorand no TCP send occurs

Page 16: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

ethereal dump:

packets 1-3: 3WHS

packet 4: client sends 4 char

packet 6: server echoes 4 char

client: port 35205server: port 2007

packet 10: server sends 12 char

packet 9: client ACKs 12 char

packet 8: client sends FIN

packet 11: client sends RST

Page 17: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

TCP Server:

• TCP servers typically start up and wait for someone to ask for service.

• They do not call connect().• The sequence of function calls is:

socket(); # creates a local socketbind(); # binds to passed port numberlisten(); # listens for incoming connection requestsaccept(); # accepts incoming connection request

Page 18: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Connection schematic:

client

server

socket();bind();listen();

listeningsocket

listeningsocket

accept();

connectedsocket

separate file descriptor

acceptloop

connect()

establishedconnection

1st

2nd

3rd4th

blocks untilconnectionrequest arrives

spawns newconnected socket

Page 19: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

TCP Server Example (1):#!/usr/bin/perl# file: tcp_echo_serv1.pl# usage: tcp_echo_serv1.pl [port]use strict; use Socket; use IO::Handle;use constant MY_ECHO_PORT => 2007;$SIG{'INT'} = \&int_handler;

my ($bytes_out,$bytes_in) = (0,0);my $port = shift || MY_ECHO_PORT;my $protocol = getprotobyname('tcp');

socket(SOCK, AF_INET, SOCK_STREAM, $protocol) or die "socket() failed: $!";setsockopt(SOCK,SOL_SOCKET,SO_REUSEADDR,1) or die "Can't set SO_REUSADDR: $!" ;

my $my_addr = sockaddr_in($port,INADDR_ANY);bind(SOCK,$my_addr) or die "bind() failed: $!";listen(SOCK,SOMAXCONN) or die "listen() failed: $!";

Page 20: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

TCP Server Example (2):warn "waiting for incoming connections on port $port...\n";while (1) { next unless my $remote_addr = accept(SESSION,SOCK); my ($port,$hisaddr) = sockaddr_in($remote_addr); warn "Connection from [",inet_ntoa($hisaddr),",$port]\n";

SESSION->autoflush(1); while (<SESSION>) { $bytes_in += length($_); chomp; my $msg_out = (scalar reverse $_) . "\n"; print SESSION $msg_out; $bytes_out += length($msg_out); } warn "Connection from [",inet_ntoa($hisaddr),",$port] finished\n"; close SESSION;}close SOCK;sub int_handler{ print STDERR "bytes_sent = $bytes_out, bytes_received = $bytes_in\n"; exit 0;};

Page 21: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Server Socket Functions 1:

• Binds a local address (IP,Port) to SOCK (previously created with socket()).

• $my_addr is packed and created with sockaddr_in() or its equivalent.

• IP address can be any of the host’s IP addresses, the loopback or the wildcard INADDR_ANY.

• Root access required to open ports under 1024.• Returns undef if it fails and $! == EACCES (“Permission

Denied”).• Normally used by server to select the port it wishes to

use. Client uses bind() when local port is specified (eg, SIP client and server both use port 5070

$boolean = bind(SOCK,$my_addr);

Page 22: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Server Socket Functions 2:

• A socket is opened for accepting incoming connection requests only. It does not have a specified remote end.

• SOCK is created with socket().• $max_queue is the maximum allowable number of

completed 3-way handshakes that have not been already accept()ed. This can not exceed a system max.

• Socket::SOMAXCONN is the system number.• On failure it returns undef and $! contains the error.

$boolean = listen(SOCK,$max_queue);

Page 23: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Server Socket Functions 3:

• Used with a listening socket to accept new connections.• LISTEN_SOCK created with socket() and listen().• On success, it returns a packed remote address as

produced by sockaddr_in(). CONN_SOCK is associated with this new address.

• accept() blocks if no completed 3-WHS is pending acceptance.

• returns undef on error and $! can be any one of a number of errors.

$boolean = accept(CONN_SOCK,LISTEN_SOCK);

Page 24: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Server Socket Functions 4:

• Used to recover the local and remote addresses associated with a socket.

• Returns a packed binary address that must be unpacked using sockaddr_in() and inet_ntoa() (for the IP address).

$my_addr = getsockname(SOCK);$remote_addr = getpeername(SOCK);

if ( $remote_addr = getpeername(SOCK)) { my ($port,$IP) = sockaddr_in($remote_addr); my $host = gethostbyname($IP,AF_INET); printf “Socket connected to $host at port $port\n”;}

Page 25: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Problems with tcp_echo_serv1.pl:

• Server can accept only one incoming connection at a time. Must complete service of one connection before accepting a second. This problem is avoided with threads or by forking or by “multiplexing” the server IO operations.

• Server runs in the foreground. ^C can kill it.• There is little or no logging.

Page 26: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Socket Options:

• Sockets have characteristics (called options) that are modifiable.

• $level refers to level of the protocol stack the option refers to (SO_SOCKET is suitable for most options).

• Some times we want to adjust TCP itself or UDP and not this particular socket. In that case use the protocol number that comes from getprotobyname().

• $option_name is an integer value; a large list exists.• $option_value is the new value for the option.• both functions return undef on failure.

$value = getsockopt(SOCK,$level,$option_name);$boolean = setsockopt(SOCK,$level,$option_name,$option_value);

Page 27: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Adjusting Socket Options:

• If the option value is boolean then use 1 or 0 for $option_value.

• Not very useful for TCP, we don’t often broadcast using that protocol.

• Some values passed to setsockopt() are packed binary

setsockopt(SOCK,SO_SOCKET,SO_BROADCAST,1);my $reuse = getsockopt(SOCK,SO_SOCKET,SO_BROADCAST);

$sz = unpack(“I”,getsockopt(SOCK,SOL_SOCKET,SNDBUF));

Page 28: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Common Socket Options:

SO_REUSEADDR Rebind to local address immediately.

SO_KEEPALIVE Enable “keepalive” ACKs.

SO_LINGER Block close() if data to send still pending.

SO_BROADCAST UDP only. Allows broadcast destination address.

SO_OOBINLINE Out-of-band data sent as urgent with urgent ptr.

SO_SNDLOWAT Minimum syswrite() write size w/o blocking (1).

SO_RECVLOWAT Minimum sysread() read size w/o blocking (1).

SO_TYPE Read-only. Returns packed SOCK_DGRAM.

SO_ERROR Read-only. Returns last error code. Clears.

setsockopt(SOCK,SO_SOCKET,SO_LINGER, pack(“II”,1,120));

sets a socket to linger for 120 seconds

Page 29: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Most Common Option (SO_REUSEADDR):

• A port in TIME_WAIT can not be immediately reused.• Setting this option lets a server that crashes reuse its

well-known port without waiting.• bind() fails early on unless this option set.

• You can have multiple processes bound to the same socket. They compete for incoming connections. Must be the same user.

setsockopt(SOCK,SO_SOCKET,S_REUSEADDR,1) or die “..”;bind(SOCK,$my_addr);

Page 30: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

fcntl() and ioctl() funcions:

• Alternative way to handle socket options.• We use this in Chapter 13 (non-blocking IO).

Page 31: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Other socket operations:

• Queues $data with TCP or UDP for transmission.• Returns number of bytes queued (sent).• Ignore $flags for now.• $destination only valid for UDP where you can redirect

data to different receivers.• On TCP, send() like syswrite().

$bytes = send(SOCK,$data,$flags[,$destination]);

Page 32: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Other socket operations:

• Accepts up to $length data into $buffer.• $buffer grows or shrinks as needed (no buffer overflow).• Ditto $flags. Set it to 0.• Returns packed address of message sender on success.• Returns undef on failure and $! is set appropriately• On TCP, recv() like sysread() except it returns sender

address.• Used mostly for UDP.

$bytes = recv(SOCK,$buffer,$length,$flags);

Page 33: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Other socket operations:

• Creates two unnamed sockets connected end to end.• Arguments have same meaning as socket()..• Returns undef on failure and $! is set appropriately• Returns true with two open sockets; no need to connect.• Both sockets will be on the same machine.• Similar to pipe() but bidirectional.• Most often used with a fork(); parent closes one socket,

child the other.

$boolean = socketpair(SOCK_A,SOCK_B,$domain,$type,$protocol);

socketpair(SOCK_A,SOCK_B,AF_UNIX,SOCK_STREAM,PF_UNSPEC);

most common invocation

Page 34: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

End-of-line:

• Special characters exported by the Socket module• Network preference is to end lines with CRLF (“\r\n” or

just “\n”).

• Socket exports $CRFL, $CR and $LF along with constants CRLF, CR and LF.

$/ = “\015\012”; # gives you control of what to expect

use Socket qw(:DEFAULT :crlf);

need this tag to get these values

Page 35: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Connect() Exceptions:

• TCP is meant to be robust even under the weakest network conditions (nuclear attack!!).

• Still needs to be able to report it “failed” at some level.• connect() exceptions are:

– ECONNREFUSED: Remote host up, no listening server (RST)– ETIMEOUT: Remote host down; connection request times out

(Silence).– ENETUNREACH: Network routing failed. (ICMP)– ENOTSOCK: Programmer error; eg, used file handle instead.

This error also returned by bind(), listen(), accept() and sockopt().

Page 36: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Read/Write Exceptions:

• What if server program crashes and your connection is broken?– On read you get EOF; on write you get EPIPE exception.

Handling the EPIPE signal means print() or syswrite() return false and $! == “Broken Pipe”;

• What if server host crashes while connected to it?– You can’t tell dead host from long network outage. You continue

to write but receive no ACKs. Eventually read() or write() will block.

– Once the host is back up and it gets your data (but has forgotten your connection) it will send RST. Then it looks like a server program crash.

– You can use SO_KEEPALIVE to have your socket give up earlier.

Page 37: Chapter 4  A Tourist’s Guide to Socket Programming in Perl

Read/Write Exceptions (continue):

• What if the network goes down while connection is established?– In this case IO may block but once network connectivity is

restored, things go on as normal.– If a network being down causes another network router to send

an ICMP “network unreachable” error you will get EOF or EPIPE depending on what you are doing.