Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Re: IO Socket buffer flushing

by desemondo (Hermit)
on Jan 29, 2010 at 11:22 UTC ( #820342=note: print w/replies, xml ) Need Help??


in reply to IO Socket buffer flushing

1. use strict; use warnings; They are your friends, and will save you many many many hours of troubleshooting and head scratching. They aren't perfect, you'll still have to do some work, but certainly a lot less...

2. Keep your code layout tidy paying particular attention to indentation. It may feel awkward, even unnessesary at first, but it'll get easier and easier until you find yourself writing well layed out code without even thinking about it... In short, well layed out code will make your life easier.

3. Well done for posting a short example of your code that demonstrates the problem. In this particuar case it would also be worth posting an example of the output you are seeing. Often its easy to just stick __END__ on the end of your code post and paste your output below it.

4. I tried your code (modified slightly to conform to strict rules) and it seems to work fine. No weird buffering issues are apparent... If the revised code below don't solve the problem your having, please clarify with further details and what output your seeing. Cheers!


Your code slightly modified:
#server use strict; use warnings; use IO::Socket; $| = 1; my $nonblocking = 1; my $sock = new IO::Socket::INET( LocalHost => "localhost", LocalPort => 7890, Proto => "tcp", Listen => SOMAXCONN, Reuse => 1, Timeout => 20, ); if ($sock) { print "A socket created on LocalHost listening on LocalPort\n"; } else { die "Error - no listening socket created : $!"; } my $flush = 1; while (my ($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"; + print "Created new socket for reading or writing data to Client\n" +; ioctl($new_sock, 0x8004667e, \$nonblocking); my $buf; sysread($new_sock, $buf, 10); print "$buf\n"; syswrite($new_sock, $buf, 10); $new_sock->flush; sysread($new_sock, $buf, 1); print "$buf\n"; $new_sock->flush; syswrite($new_sock, "12", 2); }

#client use strict; use warnings; use IO::Socket; #To flush the buffer print statements $| = 1; my $sock = new IO::Socket::INET( PeerAddr => 'localhost', PeerPort => +7890, Proto => 'tcp'); if ($sock) { print "A tcp socket on localhost connected to 7890\n"; } else { die "Error: $!"; } my $nonblocking = 1; ioctl($sock, 0x8004667e, \$nonblocking); my $buf = "1234567890"; syswrite($sock, $buf, 10); sysread($sock, $buf, 10); $sock->flush; print "Bytes 10 = $buf\n"; syswrite($sock, "1", 1); print "\n"; $sock->flush; sysread($sock, $buf, 2); print "Bytes 2 = $buf\n"; __END__ C:\Temp>perl client.pl A tcp socket on localhost connected to 7890 Bytes 10 = 1234567890 Bytes 2 = 1234567890 C:\Temp>perl client.pl A tcp socket on localhost connected to 7890 Bytes 10 = 1234567890 Bytes 2 = 1234567890 C:\Temp>perl client.pl A tcp socket on localhost connected to 7890 Bytes 10 = 1234567890 Bytes 2 = 1234567890 C:\Temp>

Replies are listed 'Best First'.
Re^2: IO Socket buffer flushing
by eric256 (Parson) on Jan 29, 2010 at 16:55 UTC

    Just playing around with sockets (cause its fun) I worked up the following code. Its not better realy, just different, and doesn't count on send a specific amount of info each time, intead it uses ->say and ->getline to send whole lines of data. I had to use chomp a couple times and i'm wondering if that could be avoided, but here you have it.

    #!/usr/bin/perl #server use strict; use warnings; use IO::Socket; $| = 1; my $nonblocking = 1; my $sock = new IO::Socket::INET( LocalHost => "localhost", LocalPort => 7890, Proto => "tcp", Listen => SOMAXCONN, Reuse => 1, Timeout => 20, ); if ($sock) { print "A socket created on LocalHost listening on LocalPort\n"; } else { die "Error - no listening socket created : $!"; } my $flush = 1; while (my ($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"; print "Created new socket for reading or writing data to Client\n" +; $new_sock->blocking(1); my $buf; $buf = $new_sock->getline(); chomp($buf); print "Recieved 1 '$buf'\n"; $new_sock->say($buf); $buf = $new_sock->getline(); chomp($buf); print "Recieved 2 '$buf'\n"; $new_sock->say("12"); }
    #!/usr/bin/perl #client use strict; use warnings; use IO::Socket; #To flush the buffer print statements $| = 1; my $sock = new IO::Socket::INET( PeerAddr => 'localhost', PeerPort => +7890, Proto => 'tcp'); if ($sock) { print "A tcp socket on localhost connected to 7890\n"; } else { die "Error: $!"; } my $buf = "1234567890"; $sock->say($buf); print "Sent '$buf'\n"; $buf = $sock->getline(); chomp($buf); print "Bytes 10 = '$buf'\n"; $sock->say("1"); $buf = $sock->getline(); chomp($buf); print "Bytes 2 = '$buf'\n";

    ___________
    Eric Hodges

      TCP provides a stream of bytes. You need to do your own record delimiting. readline works because it waits until a delimiter is found.

      If you need a sysread version (perhaps so you can use select), see Re^3: Can a socket listen for multiple hosts? for an example.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://820342]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2023-05-28 14:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?