toadi has asked for the wisdom of the Perl Monks concerning the following question:

Layout:

I have a server listening on a socket. Ready to spawn a single proces to run. Now I want a client to connect to the server, but immediatly disconnect. The server only starts one process and will only run another one when the first one is finished, regardless how many connects there are from the clients. So I don't want my clients to be waiting!!!

A layout for a simple client(but it keeps waiting):

#!/usr/bin/perl -w use IO::Socket; my ($host,$port) = ("localhost","9000"); $remote = IO::Socket::INET->new( Proto => "tcp", PeerAddr => $host, PeerPort => $port) or die "cannot connect remote"; print STDERR "[Connected to $host:$port]\n"; while ( <$remote> ) { print }
what did I do to stop waiting I commented:

#while ( <$remote> ) { print }

But when 2 clients at the same time connect the server dies wit following error:

Use of uninitialized value at /usr/local/lib/perl5/5.00503/sun4-solaris/Socket.pm line 295. Bad arg length for Socket::unpack_sockaddr_in, length is 0, should be 16 at /usr/local/lib/perl5/5.00503/sun4-solaris/Socket.pm line 295.

I'm in desperared need of help, because my c program also gives the same error if I don't wait for a answer from the server...

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #define PORT 9000 /* the port client will be connecting to */ #define MAXDATASIZE 100 /* max number of bytes we can get at once */ int main(int argc, char *argv[]) { int sockfd, numbytes; char buf[MAXDATASIZE]; struct hostent *he = NULL; struct sockaddr_in their_addr; /* connector's address information +*/ if (argc != 2) { fprintf(stderr,"usage: client hostname\n"); exit(1); } if ((he=gethostbyname(argv[1])) == NULL) { /* get the host info * +/ perror("gethostbyname"); exit(1); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } their_addr.sin_family = AF_INET; /* host byte order */ their_addr.sin_port = htons(PORT); /* short, network byte order * +/ their_addr.sin_addr = *((struct in_addr *)he->h_addr); memset(&(their_addr.sin_zero), '\0', 8); /* zero the rest of the +struct */ if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct +sockaddr)) == -1) { perror("connect"); close(sockfd); exit(1); } close(sockfd); return 0; }
Probably I looked over someting abviously about client/server programming. But can someone with more experience on the subject enlighten me :)

--
My opinions may have changed,
but not the fact that I am right

Edit title by tye

Replies are listed 'Best First'.
Sockets
by jepri (Parson) on Jan 08, 2002 at 15:49 UTC
    You need to 'accept' the socket. The old socket is then reused:

    print "Incoming connection detected!\n"; my $new_sock = $listen_sock->accept or die "Could not accept socket: $!";

    then you should do a

    recv $new_sock,$z,10000,0;

    to read from your socket. tye will tell you that <SOCKET> is bad, mmmmkay?

    Sorry.. too tipsy to do more than cut and paste from my own code.

    As near as I can tell 'accept' clones the socket, then goes back to listening on the old one. If anyone here would care to explain...

    The docs are pretty short on this operation. Going through other people's code is the best way in this case.

    ____________________
    Jeremy
    I didn't believe in evil until I dated it.

Re: Sockets
by rob_au (Abbot) on Jan 08, 2002 at 17:01 UTC
    There are two ways which come to mind immediately as to how you can change this connection behaviour.

    1. The first is to rewrite your code as a "pre-forking" server - That is, your server will fork a number of server processes ready to respond to incoming requests from a number of clients. As requests then come in, each request is handled by one of the pre-forked code threads meaning there is little latency in handling client requests.

      Not surprisingly, merlyn has already written a column employing this technique here.

    2. The second method is to accept the incoming request and make use of select to handle requests so that blocking of further incoming client requests does not occur.

       

    There a number of examples of both types of server code on this site and in some of the staple Perl books including the Perl Cookbook, Advanced Perl Programming and the ever-venerable Network Programming in Perl.

     

    perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

Re: Sockets
by agoth (Chaplain) on Jan 08, 2002 at 15:42 UTC

    If you dont want your client to wait, then can we assume you are not sending a response back from the server to the client?.

    Why not use UDP? shorter and quicker and the server can do what it wants with the message without bothering to connect or reply..?

Re: Sockets
by jebe68 (Initiate) on Jan 08, 2002 at 20:22 UTC
    have you tried a forking server ? (the camelbook, chapter 6 I believe...) Anyway, the server shouldk have an accept...