Question

I have my connection working and data transfer working.... to an extent. I am designing a small program that sets up a client and server socket. Once connected, the client can send files to the server.

My problem is, when I begin to send my "test" file, the server never ends it's while loop. It keeps concatenating data into the output file. Even stranger, the data in the output file is correct, except there is extra white space between the lines.

I know this is because I am not chomping the \n character, and I add another \n character on the server. But if I chomp on the client, then everything is on one line. Therefore the server (regardless of it adding a newline character) outputs it all on one line, because it only received one line. If I chomp on the server side, I get an empty text file... which confuses me.

Furthermore, the server never stops concatenating... it makes an infinite loop even after the client disconnected. The terminal outputs this indefinitely:

Use of uninitialized value $data in concatenation (.) or string at ./tcp_server.pl line 51, <GEN2> line 14.

Here is my code for the server:

#!/usr/bin/perl

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

use warnings;
use strict;
use IO::Socket::INET;
use v5.10;

# Server side information
my $listen_port  = '7070';
my $protocal     = 'tcp';

# Finds IP address of host machine
# Connects to example site on HTTP
my $ip_finder = IO::Socket::INET->new(
   PeerAddr=> "www.google.com",
   PeerPort=> 80,
   Proto   => "tcp"
) or die "The IP can not be resolved: $!\n";

# The found IP address of Host
my $ip_address = $ip_finder->sockhost;

# Creating socket for server
my $server = IO::Socket::INET->new (
    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 IP: $ip_address\n";
print    "Waiting for client connection on port $listen_port\n";

# Accept connection
my $client_socket = $server->accept();

open(my $fh, ">out")
    or die "File can not be opened: $!";
while($client_socket) {

    # Retrieve client information
    my $client_address = $client_socket->peerhost();
    my $client_port    = $client_socket->peerport();
    print "Client accepted: $client_address, $client_port\n";

    my $data = <$client_socket>;
    print $fh "$data\n";

}
close $fh;
$server->close();

and the client:

#!/usr/bin/perl

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

use warnings;
use strict;
use IO::Socket::INET;
use v5.10;

# Client side information
# Works by setting $dest to server address, needs to be on same domain
# my $dest      = '<IP goes here>';
# my $dest      = '<IP goes here>';
my $dest        = '<host>.cselabs.umn.edu';
my $port        = '7070';
my $protocal    = 'tcp';

my $client = IO::Socket::INET->new (
    PeerHost    =>  $dest,
    PeerPort    =>  $port,
    Proto       =>  $protocol,
) or die "Socket could not be created, failed with error: $!\n"; # Prints error code

print "TCP connection established!\n";

open(my $fh, "<test")
    or die "Can't open: $!";
while(my $line = <$fh>) {
    print $client $line;
}
close $fh;
# sleep(10);
$client->close();
Was it helpful?

Solution

You don't add newline at the client. The client just reads a line from the file (including newline) and prints it to the socket, but does not add another newline. But at the server you read the line from the socket (including the newline) and add another newline. Also, the loop condition in the server is not correct. You should not check if the socket exists because it will exists even after the connection got closed. Instead you should check for error while reading (that's where you undefined warnings come from). And, it may be better not to read line by line but instead chunks independent from the lines, e.g.

while (read($client_socket, my $data, 8192)) {
    print $fh $data;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top