IO::Socket server


D

deadpickle

This is what I got:
server.pl
use strict;
use IO::Socket;
my $sock = new IO::Socket::INET(
LocalHost => 'localhost',
LocalPort => 7890,
Proto => 'tcp',
Listen => SOMAXCONN,
Reuse => 1);
$sock or die "no socket :$!";
my($new_sock, $c_addr, $buf);
while (($new_sock, $c_addr) = $sock->accept()) {
my ($client_port, $c_ip) =
sockaddr_in($c_addr);
my $client_ipnum = inet_ntoa($c_ip);
my $client_host =
gethostbyaddr($c_ip, AF_INET);
print "got a connection from: $client_host",
" [$client_ipnum]\n";
while (defined ($buf = <$new_sock>)) {
print $buf;
}
}

client.pl
use strict;
use IO::Socket;
my $file =
my $host = shift || 'localhost';
my $port = shift || 7890;
my $sock = new IO::Socket::INET(
PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp');
$sock or die "no socket :$!";

What I want it to do is have the server on one computer and the client
on the other. I want the client to connect to the server and request a
file. I want the server to send the file to the client. Its a simple
text file so its not very large. I want it to do this over again until
it is closed. I dont know much about perl programming so any help would
be very appriciated.
 
Ad

Advertisements

S

Sébastien Cottalorda

(e-mail address removed) a écrit :
This is what I got:
server.pl
use strict;
use IO::Socket;
my $sock = new IO::Socket::INET(
LocalHost => 'localhost',
LocalPort => 7890,
Proto => 'tcp',
Listen => SOMAXCONN,
Reuse => 1);
$sock or die "no socket :$!";
my($new_sock, $c_addr, $buf);
while (($new_sock, $c_addr) = $sock->accept()) {
my ($client_port, $c_ip) =
sockaddr_in($c_addr);
my $client_ipnum = inet_ntoa($c_ip);
my $client_host =
gethostbyaddr($c_ip, AF_INET);
print "got a connection from: $client_host",
" [$client_ipnum]\n";
while (defined ($buf = <$new_sock>)) {
print $buf;
}
}

client.pl
use strict;
use IO::Socket;
my $file =
my $host = shift || 'localhost';
my $port = shift || 7890;
my $sock = new IO::Socket::INET(
PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp');
$sock or die "no socket :$!";

What I want it to do is have the server on one computer and the client
on the other. I want the client to connect to the server and request a
file. I want the server to send the file to the client. Its a simple
text file so its not very large. I want it to do this over again until
it is closed. I dont know much about perl programming so any help would
be very appriciated.
Hi,

Here are some clues:

Server side:
============
Examine what you've received from the client (you ever listen first)
1-/ if client sent you "FILE|...", the second column is a filename, open
it (send "NACK|reason" if you're unable to open file) and send it
through the socket with "FIL|" before
2-/ if client sent you "QUIT|", then close the socket (Normally never used)
3-/ Else, reply "NACK|Command not understood"
In every case, after the job, close the socket.

[snip]
while (defined ($buf = <$new_sock>)) {
chomp($buf);
if ($buf=~/^FILE\|/){
my $filename = (split /\|/, $buf)[1];
unless (open (FH, "<", $filename)){
print $new_sock "NACK|File '$filename' do not exists\n";
}
else {
while (my $line =<FH>){
chomp($line);
print $new_sock "FIL|".$line."\n";
}
close(FH);
print $new_sock "EOT|\n";
}
last;
}
elsif ($buf=~/^QUIT\|/){
last;
else {
print $new_sock "NACK|Command not understood\n";
last;
}
}
close ($new_sock);



Client side:
============
The client talk first in every case:

use strict;
use IO::Socket;
my $file =
my $host = shift || 'localhost';
my $port = shift || 7890;
my $sock = new IO::Socket::INET(
PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp');
$sock or die "no socket :$!";
#--------------/ Socket opened \----------------
$filename=......; # the file to be sent by the server side
$fileout=.....; # the file in which we should place received datas
unless (open (FH_RECEPTION, ">", $fileout)){
die "Unable to create $fileout $!";
}
print $sock "FILE|$filename\n";
my @elem=();
my $all_received;
while (my $line=<$sock>){
chomp($line);
@elem = split /\|/, $line;
if ($elem[0]=~/^FIL\|/){
print FH_RECEPTION $elem[1]."\n";
$all_received=0;
}
elsif ($elem[0]=~/^EOT\|/){
print "Normal End of Transmission received\n";
$all_received=1;
last;
}
elsif ($elem[0]=~/^NACK\|/){
print "ERROR: $elem[1]\n";
last;
}
else {
print "Do not understand|$line\n";
last;
}
}
close($sock);
close(FH_RECEPTION);
if ((defined $all_received) and ($all_received==1)){
print "Everything has been received in $fileout\n";
}
elsif (defined $all_received) {
print "some part of the file has been received in $fileout\n";
}

BE CAREFULL0: I consider that you're file didn't contains the '|'
character. If so, you should replace it with another not used character.
BE CAREFULL1: on both server and client side, as coded, you don't manage
timeouts : use IO::Select for that.
BE CAREFULL2: I didn't check the codes.

Hope this helps.

Sebastien
 
D

deadpickle

Sébastien Cottalorda said:
(e-mail address removed) a écrit :
This is what I got:
server.pl
use strict;
use IO::Socket;
my $sock = new IO::Socket::INET(
LocalHost => 'localhost',
LocalPort => 7890,
Proto => 'tcp',
Listen => SOMAXCONN,
Reuse => 1);
$sock or die "no socket :$!";
my($new_sock, $c_addr, $buf);
while (($new_sock, $c_addr) = $sock->accept()) {
my ($client_port, $c_ip) =
sockaddr_in($c_addr);
my $client_ipnum = inet_ntoa($c_ip);
my $client_host =
gethostbyaddr($c_ip, AF_INET);
print "got a connection from: $client_host",
" [$client_ipnum]\n";
while (defined ($buf = <$new_sock>)) {
print $buf;
}
}

client.pl
use strict;
use IO::Socket;
my $file =
my $host = shift || 'localhost';
my $port = shift || 7890;
my $sock = new IO::Socket::INET(
PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp');
$sock or die "no socket :$!";

What I want it to do is have the server on one computer and the client
on the other. I want the client to connect to the server and request a
file. I want the server to send the file to the client. Its a simple
text file so its not very large. I want it to do this over again until
it is closed. I dont know much about perl programming so any help would
be very appriciated.
Hi,

Here are some clues:

Server side:
============
Examine what you've received from the client (you ever listen first)
1-/ if client sent you "FILE|...", the second column is a filename, open
it (send "NACK|reason" if you're unable to open file) and send it
through the socket with "FIL|" before
2-/ if client sent you "QUIT|", then close the socket (Normally never used)
3-/ Else, reply "NACK|Command not understood"
In every case, after the job, close the socket.

[snip]
while (defined ($buf = <$new_sock>)) {
chomp($buf);
if ($buf=~/^FILE\|/){
my $filename = (split /\|/, $buf)[1];
unless (open (FH, "<", $filename)){
print $new_sock "NACK|File '$filename' do not exists\n";
}
else {
while (my $line =<FH>){
chomp($line);
print $new_sock "FIL|".$line."\n";
}
close(FH);
print $new_sock "EOT|\n";
}
last;
}
elsif ($buf=~/^QUIT\|/){
last;
else {
print $new_sock "NACK|Command not understood\n";
last;
}
}
close ($new_sock);



Client side:
============
The client talk first in every case:

use strict;
use IO::Socket;
my $file =
my $host = shift || 'localhost';
my $port = shift || 7890;
my $sock = new IO::Socket::INET(
PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp');
$sock or die "no socket :$!";
#--------------/ Socket opened \----------------
$filename=......; # the file to be sent by the server side
$fileout=.....; # the file in which we should place received datas
unless (open (FH_RECEPTION, ">", $fileout)){
die "Unable to create $fileout $!";
}
print $sock "FILE|$filename\n";
my @elem=();
my $all_received;
while (my $line=<$sock>){
chomp($line);
@elem = split /\|/, $line;
if ($elem[0]=~/^FIL\|/){
print FH_RECEPTION $elem[1]."\n";
$all_received=0;
}
elsif ($elem[0]=~/^EOT\|/){
print "Normal End of Transmission received\n";
$all_received=1;
last;
}
elsif ($elem[0]=~/^NACK\|/){
print "ERROR: $elem[1]\n";
last;
}
else {
print "Do not understand|$line\n";
last;
}
}
close($sock);
close(FH_RECEPTION);
if ((defined $all_received) and ($all_received==1)){
print "Everything has been received in $fileout\n";
}
elsif (defined $all_received) {
print "some part of the file has been received in $fileout\n";
}

BE CAREFULL0: I consider that you're file didn't contains the '|'
character. If so, you should replace it with another not used character.
BE CAREFULL1: on both server and client side, as coded, you don't manage
timeouts : use IO::Select for that.
BE CAREFULL2: I didn't check the codes.

Hope this helps.

Sebastien

I copied this program and it works but the file that is transfered does
not contain any data.
 
S

Sébastien Cottalorda

Hi,

Here is a full, tested, couple of program that work on an html file.

client_side.pl
==============
#!/usr/bin/perl -w
#
#
use strict;
use IO::Socket;
$|=1;
my $file =
my $host = shift || 'localhost';
my $port = shift || 7890;
my $sock = new IO::Socket::INET(
PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp');
$sock or die "no socket :$!";
#--------------/ Socket opened \----------------
my $filename=.....; # the file to be sent by the server side
my $fileout=$filename."_RECEIVED"; # the file in which we should place
received datas
unless (open (FH_RECEPTION, ">", $fileout)){
die "Unable to create $fileout $!";
}
print $sock "FILE|$filename\n";
my @elem=();
my $all_received;
while (my $line=<$sock>){
chomp($line);
#
# Remove the next line in production
#
print "RECEIVED>$line\n";
@elem = split /\|/, $line;
if ($line=~/^FIL\|/){
$elem[1]='' unless (defined $elem[1]);
print FH_RECEPTION $elem[1]."\n";
$all_received=0;
}
elsif ($line=~/^EOT\|/){
print "Normal End of Transmission received\n";
$all_received=1;
last;
}
elsif ($line=~/^NACK\|/){
print "ERROR: $elem[1]\n";
last;
}
else {
print "Do not understand|$line\n";
last;
}
}
close($sock);
close(FH_RECEPTION);
if ((defined $all_received) and ($all_received==1)){
print "Everything has been received in $fileout\n";
}
elsif (defined $all_received) {
print "some part of the file has been received in $fileout\n";
}
exit;



server_side
===========
#!/usr/bin/perl -w
use strict;
use IO::Socket;
my $sock = new IO::Socket::INET(
LocalHost => 'localhost',
LocalPort => 7890,
Proto => 'tcp',
Listen => SOMAXCONN,
Reuse => 1);
$sock or die "no socket :$!";
$|=1;
my($new_sock, $c_addr, $buf);
while (($new_sock, $c_addr) = $sock->accept()) {
my ($client_port, $c_ip) = sockaddr_in($c_addr);
my $client_ipnum = inet_ntoa($c_ip);
my $client_host = gethostbyaddr($c_ip, AF_INET);
print "got a connection from: $client_host"," [$client_ipnum]\n";
while (defined ($buf = <$new_sock>)) {
chomp($buf);
if ($buf=~/^FILE\|/){
my $filename = (split /\|/, $buf)[1];
unless (open (FH, "<", $filename)){
print $new_sock "NACK|File '$filename'
do not exists\n";
}
else {
while (my $line =<FH>){
chomp($line);
print $new_sock "FIL|".$line."\n";
#
# Remove/comment next line in production
#
print "SENT>FIL|".$line."\n";
}
close(FH);
print $new_sock "EOT|\n";
}
last;
}
elsif ($buf=~/^QUIT\|/){
last;
}
else {
print $new_sock "NACK|Command not understood\n";
last;
}
}
close($new_sock);
}
exit;



Hope this helps again.....

Sebastien
 
D

deadpickle

Sébastien Cottalorda said:
Hi,

Here is a full, tested, couple of program that work on an html file.

client_side.pl
==============
#!/usr/bin/perl -w
#
#
use strict;
use IO::Socket;
$|=1;
my $file =
my $host = shift || 'localhost';
my $port = shift || 7890;
my $sock = new IO::Socket::INET(
PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp');
$sock or die "no socket :$!";
#--------------/ Socket opened \----------------
my $filename=.....; # the file to be sent by the server side
my $fileout=$filename."_RECEIVED"; # the file in which we should place
received datas
unless (open (FH_RECEPTION, ">", $fileout)){
die "Unable to create $fileout $!";
}
print $sock "FILE|$filename\n";
my @elem=();
my $all_received;
while (my $line=<$sock>){
chomp($line);
#
# Remove the next line in production
#
print "RECEIVED>$line\n";
@elem = split /\|/, $line;
if ($line=~/^FIL\|/){
$elem[1]='' unless (defined $elem[1]);
print FH_RECEPTION $elem[1]."\n";
$all_received=0;
}
elsif ($line=~/^EOT\|/){
print "Normal End of Transmission received\n";
$all_received=1;
last;
}
elsif ($line=~/^NACK\|/){
print "ERROR: $elem[1]\n";
last;
}
else {
print "Do not understand|$line\n";
last;
}
}
close($sock);
close(FH_RECEPTION);
if ((defined $all_received) and ($all_received==1)){
print "Everything has been received in $fileout\n";
}
elsif (defined $all_received) {
print "some part of the file has been received in $fileout\n";
}
exit;



server_side
===========
#!/usr/bin/perl -w
use strict;
use IO::Socket;
my $sock = new IO::Socket::INET(
LocalHost => 'localhost',
LocalPort => 7890,
Proto => 'tcp',
Listen => SOMAXCONN,
Reuse => 1);
$sock or die "no socket :$!";
$|=1;
my($new_sock, $c_addr, $buf);
while (($new_sock, $c_addr) = $sock->accept()) {
my ($client_port, $c_ip) = sockaddr_in($c_addr);
my $client_ipnum = inet_ntoa($c_ip);
my $client_host = gethostbyaddr($c_ip, AF_INET);
print "got a connection from: $client_host"," [$client_ipnum]\n";
while (defined ($buf = <$new_sock>)) {
chomp($buf);
if ($buf=~/^FILE\|/){
my $filename = (split /\|/, $buf)[1];
unless (open (FH, "<", $filename)){
print $new_sock "NACK|File '$filename'
do not exists\n";
}
else {
while (my $line =<FH>){
chomp($line);
print $new_sock "FIL|".$line."\n";
#
# Remove/comment next line in production
#
print "SENT>FIL|".$line."\n";
}
close(FH);
print $new_sock "EOT|\n";
}
last;
}
elsif ($buf=~/^QUIT\|/){
last;
}
else {
print $new_sock "NACK|Command not understood\n";
last;
}
}
close($new_sock);
}
exit;



Hope this helps again.....

Sebastien

Sorry to keep bothering you like this but I am very new to perl. The
program works great. I want the client script to sleep for 5 seconds
then run and get the file again. I tried entering the sleep value at
the end of the script and removing the exit but all that happens is
that the client sleeps for 5 then closes.
 
Ad

Advertisements

S

Sébastien Cottalorda

Jim Gibson a écrit :
[snip]

for(;;) {

while (my $line=<$sock>){
chomp($line);
[snip]


sleep(5);
}


Sorry to keep bothering you like this but I am very new to perl. The
program works great. I want the client script to sleep for 5 seconds
then run and get the file again. I tried entering the sleep value at
the end of the script and removing the exit but all that happens is
that the client sleeps for 5 then closes.


Put another loop around the existing while loop as indicated above. The
above will run forever until killed. Modify it as needed.
Hi,

It won't work because server side close the socket when he finish.
Client need to re-open the entire socket every 5 sec, so the program
becomes:

while (1){
if ! open socket ?
print warning
else
if ! open fileout ?
print warning
else
send FIL|filename
CONNECT: while reception{
blah blah
}
close fileout
endif
close socket
endif
sleep 5
}

so .........


client_side.pl
==============
#!/usr/bin/perl -w
#
#
use strict;
use IO::Socket;
$|=1;
my $host = shift || 'localhost';
my $port = shift || 7890;
my $sock;
#--------------/ Socket opened \----------------
my $filename=.....; # the file to be sent by the server side
my $fileout=$filename."_RECEIVED";
my @elem=();
my $all_received;
while (1){
$sock = new IO::Socket::INET(
PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp');
unless (defined $sock){
print "Unable to find server: $!";
}
else {
print $sock "FILE|$filename\n";
@elem=();
undef $all_received;
unless (open (FH_RECEPTION, ">", $fileout)){
print "Unable to create $fileout $!";
}
else {
CONNECT: while (my $line=<$sock>){
chomp($line);
#
# Remove the next line in production
#
print "RECEIVED>$line\n";
@elem = split /\|/, $line;
if ($line=~/^FIL\|/){
$elem[1]='' unless (defined $elem[1]);
print FH_RECEPTION $elem[1]."\n";
$all_received=0;
}
elsif ($line=~/^EOT\|/){
print "Normal End of Transmission received\n";
$all_received=1;
last CONNECT;
}
elsif ($line=~/^NACK\|/){
print "ERROR: $elem[1]\n";
last CONNECT;
}
else {
print "Do not understand|$line\n";
last CONNECT;
}
}
close(FH_RECEPTION);
}
close($sock);
if ((defined $all_received) and ($all_received==1)){
print "Everything has been received in $fileout\n";
}
elsif (defined $all_received) {
print "some part of the file has been received in $fileout\n";
}
}
sleep 5;
}
exit;


BECAREFUL, this code is not tested.

Sebastien
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top