2

Afternoon,

I am writing a small UDP Client/Server in Perl and am having some issues sending files. I understand I need to break the file into chunks (datagrams) and send them to the server.

I am stuck figuring out how to break the file up into datagrams and send them. As of now, I can establish a UDP connection just fine, the server reports when it is received a UDP packet. This is what I have so far, any help would be greatly appreciated!

Server:

#!/usr/bin/perl

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

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

# Server side information
my $listen_port     = 7070;
my $protocal        = 'udp';
my $received_data   = undef;

# Creating UDP socket for server
my $server = IO::Socket::INET->new (
    LocalPort   => $listen_port,
    Proto       => $protocal,
    Type        => SOCK_DGRAM
) or die "Socket could not be created, failed with error $!\n";

print "Waiting for client connection on port $listen_port\n";

open(FILE, ">output.UDP")
  or die "File can not be opened: $!";

while($server->recv($received_data, 1024)) {
    my $peer_address = $server->peerhost();
    my $peer_port    = $server->peerport();
    print "Message was received from: $peer_address, $peer_port\n";
    print FILE "$received_data";
}
close FILE;

print "Closing socket...\n";
$server->close();

Client:

#!/usr/bin/perl

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

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

# Client side information
my $host        = 'apollo.cselabs.umn.edu';
my $port        = 7070;
my $protocal    = 'udp';
my $datagram    = undef;

# Creating UDP socket for client
my $client = IO::Socket::INET->new (
    PeerAddr    => $host,
    PeerPort    => $port,
    Proto       => $protocal,
    Type        => SOCK_DGRAM
) or die "Socket could not be created, failed with error: $!\n";

# Open and specified file
open(FILE, "10MBfile.dat")
    or die "Fine can not be opened: $!";
$client->send("test");

# Send file line by line
while (<FILE>) {
    $datagram = $_;
    $client->send("$datagram");
}
close FILE;
# sleep(10);
$client->close();
rusty
  • 307
  • 1
  • 4
  • 16

1 Answers1

4

Your code is already breaking up the file into chunks. By calling <FILE> each chunk will be one line. But there are several problems:

  • If the line gets too long and will not fit into a packet it cannot be transferred
  • UDP does not guarantee the delivery, so you receiver might miss data or might even duplicate data
  • UDP does not guarantee the order of delivery, so your receiver might get later data first

These drawbacks are probably not acceptable with file transfer, so you need to add layers on top of UDP to work around them, e.g. sequence numbers to detect duplicates and reordering and acknowledgments to trigger resubmissions on lost data. Or you could simply use TCP instead which has all these and more built in already.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • I have a TCP one working, and prefer it to this. I just want to figure out both protocols. I think instead of file transfer I'll try a data stream. The implementations you suggest sound like it would make for a difficult Sunday at my current comprehension level. Thank you for your reply! – rusty Mar 09 '14 at 19:32
  • @Russell, TCP provides a stream (which is what you want). UDP doesn't (just unrelated datagrams), so you have to implement your own. For starters, you'd have to add a sequence number to the packets. You'll have to signal the end of the stream. (Actually, you need that for TCP too or you'll end up missing the end of the file when the FIN arrives before the last packet.) – ikegami Mar 10 '14 at 03:00
  • With TCP you can just read until sysread returns 0 (e.g. no bytes but no error), that's the end of the stream. You can do a one-sided stream-end with shutdown. That's used for instance with FTP or some kinds of HTTP (where no content-length and no chunked mode is specified). – Steffen Ullrich Mar 10 '14 at 05:52
  • I understand ;) as I said I have a TCP server/client working in Perl, but for an assignment we were supposed to also look into getting a UDP server/client working. I was attempting to figure out a way to transfer X amount of bytes from the client to the server, and I had just created a file of all 0s. It wasn't really for integrity, as I understand you have no guarantee unless you implement certain features as suggested into the server/client. I did figure out a way to get it to blast away 0's. The replies here helped me figure that out :) Thanks everyone! – rusty Mar 10 '14 at 13:28