Socket Programming in Solaris 2.6 update

FYI,

Since posting the first Summary I received additional information. It

seems that if you are using inetd, then you don't need to worry about

socket programming since inetd handles all the socket stuff for you:

Bryan Blackburn <blb@rmi.net>

Since you've setup your server to go through inetd, you don't

need to have it worry about any socket programming; inetd will do that

for you. With inetd, you just have your server use stdin/stdout to talk

through the socket, which reduces your server script to:

$| = 1; # Or autoflush STDOUT 1...

while (<STDIN>) {

chomp;

print scalar(reverse($_)), "\r\n";

}

Also, thanks to: "David Evans" <DJEVANS@au.oracle.com>

The socket version was presented below.

Later...

Thanks to:

Robert G. Ferrell

Frank Fiamingo - Col

Russ Poffenberger

Bill Hathaway

Charles Best

John Bradley

Michael Kriss

Robert G. Ferrell

John Berninger

The solution and code are presented below. The server program can be

terminated... with ^C or killed and the port is recycled/. I can now

concentrate on the rest of the program... wich will send a start signal

on that port from a VAX machine to a SPARC20 which runs a set of EMC

disks. The server in turn will return a completed signal to the VAX

workstation. Thanks to all the people and their prompt responses.

Frank Fiamingo - Columbus <frank.fiamingo@ssds.com>... sugested that I

kill the inetd daemon with:

kill -HUP `ps -e|grep -w inetd|awk '{print $1}'`

After doing this the server program worked. However, everytime that I

kill the program... it would take serveral minutes for the socket to be

released by the OS (ndd variable).

THE FIXED SERVER CODE:

"Robert G. Ferrell" <rferrell@usgs.gov>

I don't see anything wrong with either of the config files, so

long as the server doesn't require any command line arguments like the

client does. The first thing I would try is adding a socket option to

allow

reuse of the port (just in case something is grabbing it):

#!/usr/local/bin/perl

#THIS IS THE SERVER

use strict;

use Socket;

use FileHandle;

my $port = shift || 9876;

socket (SOCKET, PF_INET, SOCK_STREAM, (getprotobyname('tcp'))[2]);

setsockopt(SOCKET, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) || die

"Setsockopt error: $!\n";

bind (SOCKET, pack('Sna4x8', AF_INET, $port, "\0\0\0\0")) || die

"Can't bind to port $port!"; listen (SOCKET, 5);

NEW_SOCKET->autoflush();

SOCKET->autoflush();

while (1) {accept(NEW_SOCKET, SOCKET);

while (<NEW_SOCKET>) {chomp; print NEW_SOCKET scalar(reverse($_)),

"\r\n"; }

}

I am suspecting that what so many of you said about not needing entries

on /etc/inetd.conf is true. I removed the entry for server1 from

inetd.conf and restarted inetd daemon with a -HUP; Then I started the

server program (with the fixed presented below). The server program

works fine without an entry in the inetd.conf file:

poffen@San-Jose.ate.slb.com (Russ Poffenberger)...

"The reason why is because of the way inetd works. Inetd is already

bound to the port, so you can't bind to it again. There is no need,

however, because inetd will hand you off a socket already connected to

the requestor. This socket is the file descriptor 0 (stdin)...

You may have been able to get it running briefly after sending

HUP to inetd since it will have released all ports and taken a few

seconds to re-initialize. inetd will keep the port bound. You do not

need to create a socket, bind or listen to it. inetd has already done

all that for you. Pretty much all you need to do is use FD 0 as your

socket file descriptor."

Bill Hathaway <wdh@poss.com>

you don't actually say what your error is, but I'm guessing

that it seems your server is not listening to the port. It looks like

your server tries to listen on a port using bind(), but if you are

trying to run from inetd, inetd does all the bind() stuff for you, and

hands you the connected socket as stdin/stdout. So I'd either

A) use your program as is, but not run it from inetd

B) take out all the network specific code from your program,

have it launched from inetd and have it read/write stdin/out

If you want to verify that inetd works that way, try replacing

the madserver inetd line with one that launches /usr/bin/cat, telnet

to it, then type a few things and hit return.

John Berninger <jberninger@bbtnet.com>

I'm not sure if this will help, but here goes... I just did

some real quick-and-dirty socket type 'research'... Took a

script I'd written using STDIN and put in entries for it in the

inetd.conf and services files. Then I telnet'ed to the port

port I'd set it for in services, and put in a line of text. The

program took the socket input from the telnet session as STDIN,

I didn't need to bind to any sockets. What I think (and this is only a

WAG based on that limited experiment) is that when you telnet to the

port, it starts one instance of the script and binds it to your port,

then you attempt to re-bind the port within the script, causing an

error. You might want to try removing the bind commands and such and

just take in STDIN at the server side unless you can launch it

as a daemon and remove the bindings in /etc/services and

/etc/inetd.conf.

                

Conner.

Ps. Yes, I'll read up on the RPC from O'Reilly and TCP/IP Second

edition from Stevens.

ORIGINAL E-MAIL:

This is a Solaris Question (for those fanatics that belive in the purity

of the Mailing list):

I am writing a socket under Solaris 2.6 (SPARC20) using perl 5.004_4.

The server and client workstation are the same.

I have defined the entries for the server portion of the inetd.conf

file:

"server1 stream tcp nowait root /opt/socket_prg/server

server1"

Where server1 is the socket /opt/socket_prg/server is the full path to

the socket program (in perl).

I also added the port under /etc/services:

"server1 9876/tcp # madserver"

I been debudding by telneting to the port "telnet server 9876". I also

have been using "perl -d server" to debug the program. I don't believe

that there is something wrong with the programs. They are copied from

documented and tested samples in literature. I am incline to belive

that it is something that I am defining wrong in the /etc/inetd.conf or

/etc/services. Can someone point out to me the proper way to create

entries in these files... if the files are wrong. I have included the

server and client programs that I am using.

If my errors are not on the files... but in the code; please be

especific as to the changes.

Conner

#!/usr/local/bin/perl

#THIS IS THE SERVER

use strict;

use Socket;

use FileHandle;

my $port = shift || 9876;

socket (SOCKET, PF_INET, SOCK_STREAM, (getprotobyname('tcp'))[2]);

bind (SOCKET, pack('Sna4x8', AF_INET, $port, "\0\0\0\0"))

       || die "Can't bind to port $port!";

listen (SOCKET, 5);

NEW_SOCKET->autoflush();

SOCKET->autoflush();

while (1) {

    accept(NEW_SOCKET, SOCKET);

    while (<NEW_SOCKET>) {

        chomp;

        print NEW_SOCKET scalar(reverse($_)), "\r\n";

    }

}

#!/usr/local/bin/perl

#THIS IS THE CLIENT

use Socket;

use FileHandle;

# Command-line arguments: the server's port and the server's name.

($port, $server) = @ARGV;

$port && $server or die "Please supply both port and server.";

socket (SOCKET, PF_INET, SOCK_STREAM, (getprotobyname('tcp'))[2]);

connect (SOCKET, pack('Sna4x8', AF_INET, $port,

(gethostbyname($server))[4]))

   || die "Can't connect to server $server on port $port.\n";

SOCKET->autoflush();

$pid = fork;

if ($pid == 0) { print STDOUT while (<SOCKET>); } # Read from the

server

else { print SOCKET while (<STDIN>); close SOCKET; exit} #

Write to the server

______________________________________________________

Get Your Private, Free Email athttp://www.hotmail.com

[9980 byte] By [CodeProf.com] at [2007-12-25 11:23:00]