[comp.unix.wizards] sockets

gaw@mercury.acc.com (...Glen............) (05/22/89)

Hello everyone.  I am looking into porting the UNIX socket library to
an IBM system running a TCP/IP networking software package.  The socket
library will only provide sockets in the AF_INET domain.  The C-compiler
that I will be using attempts to emulate the UNIX environment as much
as possible on the IBM system.  Many of the standard UNIX function calls
(such as open, fopen, fscanf, etc) are available to the C programmer.
Since some of the built in functions like read and write can work with
an inode and also a socket, I think that I would have to front end these
calls to look at the file descriptor type field and then call either the
built in routine if it is a request for an inode or to the routine that
I will write if the file descriptor references a socket.  I don't see any
problems with that.  How about you????

My next question is: "Is it possible for a user program in UNIX to
use open to acquire a file descriptor and then using another function
convert this file descriptor to a FILE pointer(such as those returned from
the fopen() call)?  The reason I ask this is that if it is possible for a
user process to convert from file descriptors to file pointers it is then
possible to use socket to open a file descriptor, convert it to a FILE pointer
and then attempt to do a fprintf or fscanf on the socket.  If this is possible
I would have to front end these FILE pointer functions also with code
similar to that specified above.  I know it is possible to go from a
FILE pointer to a file descriptor using the fileno(FILE *) macro.  Is it
possible to convert in the other direction?

Other functions which I will have to front end would be ioctl, perror,
and fcntl.  Does anyone see any problems with the above, other areas
of concern, suggestions, etc?

I would like to make this interface as closely UNIX compatible as possible.
I also want to make it versatile enough that futher applications such as
NFS will be able to use the library for all of its networking needs.
Any and all help or information will be greatly appreciated.

Please respond to    gaw@acc-sb-unix.arpa

Thank you,

Glen Warholic
Advanced Computer Communications

bush%prg.oxford.ac.uk@nsfnet-relay.ac.uk (Mark Bush) (08/22/89)

I've been trying to get an application running and decided that the most
suitable implementation would be using broadcasting over datagram sockets.
I've produced client/server programs that communicated via sockets before
but then the client process connected to a server running on a specified
host.  I now want to access information in general across a network.
(I'm using Sun3s running SunOS 3.5)

The first step...RTFM:
From "Networking on the Sun Workstation", "IPC Primer":

        To send a broadcast message, an Internet datagram socket should
        be created.

Nothing could be easier.

        and at least a port number should be bound to the socket.

Again, this is clear and straightforward.

        Then the message should be addressed as:

        dst.sin_family = AF_INET;
        inet_makeaddr(net, INADDR_ANY);
        dst.sin_port = DESTPORT;

Say what?  

I can find out what value `net' should be, no problem...this is well
documented, but doesn't `inet_makeaddr()' return an address?  Well, needless
to say, I tried what they said and got nothing.  Perhaps that line should
have said something like:

        dst.sin_addr = inet_makeaddr(net, INADDR_ANY);

I tried that, too.  Low and behold I actually managed to get

        sendto(s, buf, buflen, 0, &dst, sizeof(dst));

to return the same value as buflen!!!  What I want to know is: where did
it go?  My server process is continually `polling' its port...in fact it
does a `recvfrom' on its port (DESTPORT) and never returns.  I get the
feeling that I'm doing something grossly stupid, but what??!!!??

Mark Bush                      bush%uk.ac.oxford.prg@ac.uk
Teaching Support Programmer    bush%prg.oxford.ac.uk@nsfnet-relay.ac.uk
OUCL                           ...!uunet!mcvax!ukc!ox-prg!bush

bush%prg.oxford.ac.uk@nsfnet-relay.ac.uk (Mark Bush) (08/28/89)

Firstly, I would like to thank Paul DuBois for his suggestion.  Unfortunately
it didn't answer my original question which was "how do I get broadcasting
on sockets to work?".  I hadn't worded it like that, but that was the intent.

With a little work (and dbx and those usefully arranged `printf's) I managed
to solve my problem.

It appears that my problem was the line:

     dst.sin_addr = inet_makeaddr(net, INADDR_ANY);

The value I was using for `net' was wrong.  According to section 5.5 of the
"IPC Primer", this value can be obtained from `inet_netof'.  I found out
that this returned an address of the form `129.67.0.0' where I wanted
`129.67.14.0'.  What I did was to use:

     char hostname[15];
     struct hostent *thishost;
     struct in_addr *address;
     struct sockaddr_in dst;

and set the address with the following code:

     gethostname(hostname, 15);
     thishost = gethostbyname(hostname);
     address = (struct in_addr *)(thishost->h_addr);
     address->S_un.S_addr &= 0x0ffffff00;
          :
          :
     dst.sin_addr = *address;

This worked fine.  The same chapter of the documentation mentions use of the
ioctl call `SIOCGICONF'.  I haven't tried this yet, so I don't know if this
method also requires a kludge to work of if it supplies correct information.

Of course, this problem may well just be relevant to SunOS 3.x.  There is
an option (SO_BROADCAST) that can be set with `setsockoption' in 4.x that
probably does this correctly---again, I haven't tried this on 4.x yet.

Section 5.5 of the "IPC Primer" in the SunOS 3.x manuals can thus be happily
disregarded (unless, of course, you know different 8*)

Mark Bush                      bush%uk.ac.oxford.prg@ac.uk
Teaching Support Programmer    bush%prg.oxford.ac.uk@nsfnet-relay.ac.uk
OUCL                           ...!uunet!mcvax!ukc!ox-prg!bush

guy@auspex.auspex.com (Guy Harris) (08/29/89)

>Of course, this problem may well just be relevant to SunOS 3.x.  There is
>an option (SO_BROADCAST) that can be set with `setsockoption' in 4.x that
>probably does this correctly---again, I haven't tried this on 4.x yet.

No, it does not, but it is not intended to.  SO_BROADCAST is a
4.3BSD-ism (unless it was in 4.2BSD as well, in which case I'd expect it
to be in SunOS [123].x) and, as noted in the SunOS 4.x and 4.3-tahoe
(and probably 4.3BSD) GETSOCKOPT(2) manual pages:

     The option SO_BROADCAST requests permission to  send  broad-
     cast  datagrams  on  the socket.  Broadcast was a privileged
     operation in earlier versions of the system.

All it does is request permission to send broadcast datagrams; it does
not set the socket up to always transmit them.

kjh@pollux.usc.edu (Kenneth J. Hendrickson) (05/27/90)

About a year ago, somebody posted a really nice primer on sockets.  I
didn't save it.  Now, I wish I had.  Does anybody still have it?  If you
have any good examples (or that primer on sockets), would you please
post it?  Thanks.

I have to write a program using sockets, and I'm having a problem.  The
Sun IPC manual isn't helping.  I want to use the SOCK_STREAM type.
After creating 5 sockets, bind()ing a unique name to each, and listen()ing
to each of the sockets, I fork off 5 processes.  Each of the forked
processes creates it's own socket, and tries to do a connect() to one of
the previously created and named sockets, while the original routine
tries to accept() connections.  The problem is that one of the forked
routines is not able to connect(), it never returns from the connect()
call.  In addition, I can't send read() or write() any data across the
connected sockets for the other 4 processes.  Help!

Ken Hendrickson N8DGN/6      kjh@usc.edu      ...!uunet!usc!pollux!kjh

thurlow@convex.com (Robert Thurlow) (05/28/90)

kjh@pollux.usc.edu (Kenneth J. Hendrickson) writes:
>About a year ago, somebody posted a really nice primer on sockets.  I
>didn't save it.  Now, I wish I had.  Does anybody still have it?  If you
>have any good examples (or that primer on sockets), would you please
>post it?  Thanks.

Here goes.  I'm not good enough with sockets yet to try to diagnose
your problem, though I'm sure someone will be.

Rob T

-----------------------------------------------------------------------

>From: madd@world.std.com (jim frost)
>Newsgroups: comp.unix.questions,comp.unix.wizards
>Subject: Re: books on sockets, signal, ...
>Message-ID: <1989Dec17.005509.4685@world.std.com>
>Date: 17 Dec 89 00:55:09 GMT
>Organization: Software Tool & Die
>Lines: 367

pcb@usl.usl.edu (Peter C. Bahrs) writes:
>I need a reference (possibly author, title, publisher) to a good 
>(examples and explanations) book on
>socket programming, signal programming et.al.;

I've seen at least one pointer towards a book, but what follows is my
quick-and-dirty sockets primer which many people seemed to appreciate.
There are some minor bug-fixes in the sample code since the last
posting (I still can't believe people cut out the examples and tried
them :-).  If you're just starting it'll probably be very helpful.

Enjoy,

jim frost
saber software
madd@saber.com

-- cut here --
.. this is a pure troff format document.  no macro library is necessary
.. unless you need pagination.
.sp 3
.ce 3
\fIBSD Sockets:  A Quick And Dirty Primer\fR
by Jim Frost
November 22, 1989
.sp
As you delve into the mysteries of UNIX, you find more and more things
that are difficult to understand immediately.  One of these things, at
least for most people, is the BSD socket concept.  This is a short
tutorial that explains what they are, how they work, and gives sample
code showing how to use them.
.sp 3
.ce 2
The Analogy
(or:  What *IS* a socket, anyway?)
.sp
The \fIsocket\fR is the BSD method for accomplishing interprocess
communication (IPC).  What this means is a socket is used to allow one
process to speak to another, very much like the telephone is used to
allow one person to speak to another.
.sp
The telephone analogy is a very good one, and will be used repeatedly
to describe socket behavior.
.sp 3
.ce 2
Installing Your New Phone
(or:  How to listen for socket connections)
.sp
In order for a person to receive telephone calls, he must first have a
telephone installed.  Likewise you must create a socket to listen for
connections.  This process involves several steps.  First you must
make a new socket, which is similar to having a telephone line
installed.  The \fIsocket()\fR command is used to do this.
.sp
Since sockets can have several types, you must specify what type of
socket you want when you create one.  One option that you have is the
addressing format of a socket.  Just as the mail service uses a
different scheme to deliver mail than the telephone company uses to
complete calls, so can sockets differ.  The two most common addressing
schemes are \fIAF_UNIX\fR and \fIAF_INET\fR.  AF_UNIX addressing uses UNIX
pathnames to identify sockets; these sockets are very useful for IPC
between processes on the same machine.  AF_INET addressing uses
Internet addresses which are four byte numbers usually written as four
decimal numbers separated by periods (such as 192.9.200.10).  In
addition to the machine address, there is also a port number which
allows more than one AF_INET socket on each machine.  AF_INET
addresses are what we will deal with here.
.sp
Another option which you must supply when creating a socket is the
type of socket.  The two most common types are \fISOCK_STREAM\fR and
\fISOCK_DGRAM\fR.  SOCK_STREAM indicates that data will come across the
socket as a stream of characters, while SOCK_DGRAM indicates that data
will come in bunches (called datagrams).  We will be dealing with
SOCK_STREAM sockets, which are very common.
.sp
After creating a socket, we must give the socket an address to listen
to, just as you get a telephone number so that you can receive calls.
The \fIbind()\fR function is used to do this (it binds a socket to an
address, hence the name).
.sp
SOCK_STREAM type sockets have the ability to queue incoming connection
requests, which is a lot like having "call waiting" for your telephone.
If you are busy handling a connection, the connection request will
wait until you can deal with it.  The \fIlisten()\fR function is used to set
the maximum number of requests (up to a maximum of five, usually) that
will be queued before requests start being denied.  While it is not
necessary to use the listen() function, it's good practice.
.sp
The following function shows how to use the socket(), bind(), and
listen() functions to establish a socket which can accept calls:
.sp
.nf
\fC  /* code to establish a socket; originally from bzs@bu-cs.bu.edu
   */

  int establish(portnum)
  u_short portnum;
  { char   myname[MAXHOSTNAME+1];
    int    s;
    struct sockaddr_in sa;
    struct hostent *hp;

    bzero(&sa,sizeof(struct sockaddr_in));      /* clear our address */
    gethostname(myname,MAXHOSTNAME);            /* who are we? */
    hp= gethostbyname(myname);                  /* get our address info */
    if (hp == NULL)                             /* we don't exist !? */
      return(-1);
    sa.sin_family= hp->h_addrtype;              /* this is our host address */
    sa.sin_port= htons(portnum);                /* this is our port number */
    if ((s= socket(AF_INET,SOCK_STREAM,0)) < 0) /* create socket */
      return(-1);
    if (bind(s,&sa,sizeof sa,0) < 0) {
      close(s);
      return(-1);                               /* bind address to socket */
    }
    listen(s, 3);                               /* max # of queued connects */
    return(s);
  }\fR
.sp
.fi
After you create a socket to get calls, you must wait for calls to
that socket.  The \fIaccept()\fR function is used to do this.  Calling
accept() is analogous to picking up the telephone if it's ringing.
Accept() returns a new socket which is connected to the caller.
.sp
The following function can be used to accept a connection on a socket
that has been created using the establish() function above:
.sp
.nf
\fC  int get_connection(s)
  int s;                    /* socket created with establish() */
  { struct sockaddr_in isa; /* address of socket */
    int i;                  /* size of address */
    int t;                  /* socket of connection */

    i = sizeof(isa);                   /* find socket's address */
    getsockname(s,&isa,&i);            /* for accept() */

    if ((t = accept(s,&isa,&i)) < 0)   /* accept connection if there is one */
      return(-1);
    return(t);
  }\fR
.sp
.fi
Unlike with the telephone, you may still accept calls while processing
previous connections.  For this reason you usually fork off jobs to
handle each connection.  The following code shows how to use
establish() and get_connection() to allow multiple connections to be
dealt with:
.sp
.nf
\fC  #include <errno.h>       /* obligatory includes */
  #include <signal.h>
  #include <stdio.h>
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <sys/wait.h>
  #include <netinet/in.h>
  #include <netdb.h>

  #define PORTNUM 50000 /* random port number, we need something */

  void fireman(), do_something();

  main()
  { int s, t;

    if ((s= establish(PORTNUM)) < 0) {  /* plug in the phone */
      perror("establish");
      exit(1);
    }

    signal(SIGCHLD, fireman);           /* this eliminates zombies */

    for (;;) {                          /* loop for phone calls */
      if ((t= get_connection(s)) < 0) { /* get a connection */
        if (errno == EINTR)             /* EINTR might happen on accept(), */
          continue;                     /* try again */
        perror("accept");               /* bad */
        exit(1);
      }
      switch(fork()) {                  /* try to handle connection */
      case -1 :                         /* bad news.  scream and die */
        perror("fork");
        close(s);
        close(t);
        exit(1);
      case 0 :                          /* we're the child, do something */
        do_something(t);
        exit(0);
      default :                         /* we're the parent so look for */
        close(t);                       /* another connection */
        continue;
      }
    }
  }

  /* as children die we should get catch their returns or else we get
   * zombies, A Bad Thing.  fireman() catches falling children.
   */

  void fireman()
  { union wait wstatus;

    while(wait3(&wstatus,WNOHANG,NULL) >= 0);
  }

  /* this is the function that plays with the socket.  it will be called
   * after getting a connection.
   */

  void do_something(s)
  int s;
  {
    /* do your thing with the socket here
        :
        :
     */
  }\fR
.sp 3
.ce 2
Dialing
(or:  How to call a socket)
.sp
You now know how to create a socket that will accept incoming calls.
So how do you call it?  As with the telephone, you must first have the
phone before using it to call.  You use the socket() function to do
this, exactly as you establish a socket to listen to.
.sp
After getting a socket to make the call with, and giving it an
address, you use the \fIconnect()\fR function to try to connect to a
listening socket.  The following function calls a particular port
number on a particular host:
.sp
.nf
\fC  int call_socket(hostname, portnum)
  char *hostname;
  { struct sockaddr_in sa;
    struct hostent     *hp;
    int a, s;

    if ((hp= gethostbyname(hostname)) == NULL) { /* do we know the host's */
      errno= ECONNREFUSED;                       /* address? */
      return(-1);                                /* no */
    }

    bzero(&sa,sizeof(sa));
    bcopy(hp->h_addr,(char *)&sa.sin_addr,hp->h_length); /* set address */
    sa.sin_family= hp->h_addrtype;
    sa.sin_port= htons((u_short)portnum);

    if ((s= socket(hp->h_addrtype,SOCK_STREAM,0)) < 0)   /* get socket */
      return(-1);
    if (connect(s,&sa,sizeof sa) < 0) {                  /* connect */
      close(s);
      return(-1);
    }
    return(s);
  }\fR
.sp
.fi
This function returns a connected socket through which data can flow.
.sp 3
.ce 2
Conversation
(or:  How to talk between sockets)
.sp
Now that you have a connection between sockets you want to send data
between them.  The \fIread()\fR and \fIwrite()\fR functions are used to do this,
just as they are for normal files.  There is only one major difference
between socket reading and writing and file reading and writing:  you
don't usually get back the same number of characters that you asked
for, so you usually loop until you have read the number of characters
that you want.  A simple function to read a given number of characters
into a buffer is:
.sp
.nf
\fC  int read_data(s,buf,n)
  int  s;                /* connected socket */
  char *buf;             /* pointer to the buffer */
  int  n;                /* number of characters (bytes) we want */
  { int bcount,          /* counts bytes read */
        br;              /* bytes read this pass */

    bcount= 0;
    br= 0;
    while (bcount < n) {             /* loop until full buffer */
      if ((br= read(s,buf,n-bcount)) > 0) {
        bcount += br;                /* increment byte counter */
        buf += br;                   /* move buffer ptr for next read */
      }
      if (br < 0)                    /* signal an error to the caller */
        return(-1);
    }
    return(bcount);
  }\fR
.sp
.fi
A very similar function should be used to write data; we leave that
function as an exercise to the reader.
.sp 3
.ce 2
Hanging Up
(or:  What to do when you're done with a socket)
.sp
Just as you hang up when you're through speaking to someone over the
telephone, so must you close a connection between sockets.  The normal
\fIclose()\fR function is used to close each end of a socket connection.  If
one end of a socket is closed and the other tries to write to its end,
the write will return an error.
.sp 3
.ce 2
Speaking The Language
(or:  Byte order is important)
.sp
Now that you can talk between machines, you have to be careful what
you say.  Many machines use differing dialects, such as ASCII versus
(yech) EBCDIC.  More commonly there are byte-order problems.  Unless
you always pass text, you'll run up against the byte-order problem.
Luckily people have already figured out what to do about it.
.sp
Once upon a time in the dark ages someone decided which byte order
was "right".  Now there exist functions that convert one to the other
if necessary.  Some of these functions are \fIhtons()\fR (host to network
short integer), \fIntohs()\fR (network to host short integer),
\fIhtoni()\fR (host to network integer), \fIntohi()\fR (network to
host integer), \fIhtonl()\fR (host to network long integer), and
\fIntohl()\fR (network to host long integer).  Before sending an
integer through a socket, you should first massage it with the htoni()
function:
.sp
.nf
\fC  i= htoni(i);
  write_data(s, &i, sizeof(i));\fR
.sp
.fi
and after reading data you should convert it back with ntohi():
.sp
.nf
\fC  read_data(s, &i, sizeof(i));
  i= ntohi(i);\fR
.sp
.fi
If you keep in the habit of using these functions you'll be less
likely to goof it up in those circumstances where it is necessary.
.sp 3
.ce 2
The Future Is In Your Hands
(or:  What to do now)
.sp
Using just what's been discussed here you should be able to build your
own programs that communicate with sockets.  As with all new things,
however, it would be a good idea to look at what's already been done.
Many public domain programs exist which make use of the socket
concept, and many books exist which go into much more depth than I
have here.  In addition I've deliberately left out a lot of details
such as what kinds of things can go wrong; the manual pages for each
of the functions should be consulted for this information.
.sp
If you have further questions about sockets or this primer, please
feel free to ask me at email address madd@bu-it.bu.edu.
.sp
.nf
Jim Frost
Saber Software
(617) 876-7636
madd@saber.com

--
--
Rob Thurlow, thurlow@convex.com or thurlow%convex.com@uxc.cso.uiuc.edu
I haven't lost my mind;  I'm sure it's backed up on tape somewhere!

kjh@pollux.usc.edu (Kenneth J. Hendrickson) (05/28/90)

After much debugging (about 12 hours or so), I have discovered that I am
pushing bytes through the sockets that I have created as expected, but
there is a small problem.

read(socket, buf, sizeof(buf)) is always returning sizeof(buf), even
though that many characters weren't necessarily read into buf.  The man
pages say something about ioctl(), and using "STREAMS message-nondiscard"
mode, but I can't figure out how to do this.  If I can get read() to
return the correct value (the number of bytes actually read from the
socket), then I feel I will be 98% done with the debugging of my
program.  Please help.  If you know how to make read() work correctly,
please let me know.  Thanks.

P.S.	The sockets are AF_UNIX and SOCK_STREAM.  They are created,
bind()ed with a path name, listen()ing for a connection, connect()ed to,
accept()ing a connection, and bytes go across both ways just like they
should.  However, read() doesn't work right as described above.

Ken Hendrickson N8DGN/6      kjh@usc.edu      ...!uunet!usc!pollux!kjh

guy@auspex.auspex.com (Guy Harris) (05/30/90)

>read(socket, buf, sizeof(buf)) is always returning sizeof(buf), even
>though that many characters weren't necessarily read into buf.

Are you absolutely certain of that?

>The man pages say something about ioctl(), and using
>"STREAMS message-nondiscard" mode, but I can't figure out how to do this.

You can't do that.  Sockets are not implemented as streams devices in
SunOS 4.x.

cory@three.MV.COM (Cory Kempf) (05/31/90)

kjh@pollux.usc.edu (Kenneth J. Hendrickson) writes:

>About a year ago, somebody posted a really nice primer on sockets.  I
>didn't save it.  Now, I wish I had.  Does anybody still have it?  If you
>have any good examples (or that primer on sockets), would you please
>post it?  Thanks.

I wrote one a few years ago... I'll see if I can find a soft copy around
somewhere.  From what you have described though, it might be easier to
use the socketpair() call -- creates a pair of connected sockets (SOCK_STREAM,
AF_UNIX).  If you don't need to go over the network, and you are forking
anyway, you might as well use it.

+C
-- 
Cory Kempf				I do speak for the company (sometimes).
Three Letter Company						603 883 2474
email: cory@three.mv.com, harvard!zinn!three!cory

kevinf@infmx.UUCP (Kevin Franden) (06/06/90)

Being incredibly naieve about sockets, I ask this blindly:

Doesn't there exist a function to determin a preexisiting (I've 
heard some call this a "wellknown") service's socket number?

IE:  isn't there somthing like gethostbyname() for sockets?

Also, does anyone have a description of what "wellknown" services 
expect/deliver?  Namely echo, daytime, and time.  I suppose I could 
experiment but I havn't even got a socket connection running yet...


-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Kevin Franden		    UUCP: {pyramid|lll-crg}!infmx!kevinf
Informix Software Inc
disclaimer("I said what I said and not my employer");
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

There are Lies, Damn lies, Statistics, Benchmarks, and Delivery dates

elev26@castle.ed.ac.uk (Gerard A. Allan) (06/06/90)

In article <4421@infmx.UUCP> kevinf@infmx.UUCP (Kevin Franden) writes:
>
>Being incredibly naieve about sockets, I ask this blindly:
>
>Doesn't there exist a function to determin a preexisiting (I've 
>heard some call this a "wellknown") service's socket number?

sounds like you want, 
                    struct servent *getservbyname(name, proto)
                    char *name, *proto;

There seems to have been a lot of questions on sockets recently (I don't
want to discourage them since I learn a lot from the answers), there are a
couple of good sources of information that will answer most users questions

1)   ``An Introductory 4.3BSD Interprocess Communication
     Tutorial.'' (reprinted in UNIX Programmer's Supplementary
     Documents Volume 1, PS1:7)

This give a *very* clear introduction to sockets (University Libs should
have a copy)

Follow up by reading,

2)   ``An Advanced 4.3BSD Interprocess
     Communication Tutorial.'' (reprinted in UNIX Programmer's
     Supplementary Documents Volume 1, PS1:8)

Once you've read these you could probably answer most of the socket
related questions ask here recently.

Gerard A. Allan                                 | Post:  EMF
elev26@castle.ed.ac.uk                          |        Kings Buildings
JANET:elev26@uk.ac.ed.castle                    |        University of Edinburgh
Internet:elev26%castle.ed.ac.uk@cunyvm.cuny.edu |        Edinburgh
EARN/BITNET:elev26%castle.ed.ac.uk@UKACRL       |        Scotland
UUCP:elev26%castle.ed.ac.uk@ukc.uucp            |        EH9 3JL

jsloan@ncar.ucar.edu (John Sloan,8292,X1243,ML44E) (06/07/90)

From article <4529@castle.ed.ac.uk>, by elev26@castle.ed.ac.uk (Gerard A. Allan):
> In article <4421@infmx.UUCP> kevinf@infmx.UUCP (Kevin Franden) writes:
	:
>>Doesn't there exist a function to determin a preexisiting (I've 
>>heard some call this a "wellknown") service's socket number?
	:
> sounds like you want, 
>                     struct servent *getservbyname(name, proto)
>                     char *name, *proto;

This is probably what he _needs_, although I'll probably be the
Nth among M to point out that it's not what he asked for.

getservbyname() returns the _port_ number for a "well known" service
(i.e. defined in /etc/services, or if you have Yellow Pages, in the YP
services file). A service's "socket" has no meaning outside the context
of a particular process since a socket is merely a file descriptor
(integer) that is specific to a paticular process. You must create your
own socket (via socket()).  Once you have the host address (e.g. via
gethostbyname()) and port number (e.g. via getservbyname()) you can
bind or connect your socket to that address and port.

--
John Sloan              +1 303 497 1243                   ...!ncar!jsloan
NCAR/SCD, POB 3000      AMA#515306, DoD#0011         jsloan@ncar.ucar.edu
Boulder CO 80307        1990 BMW K75S Pilot     jsloan%ncar@ncario.BITNET
Logical Disclaimer:  belong(opinions,jsloan). belong(opinions,_):-!,fail.

kevinf@infmx.UUCP (Kevin Franden) (06/07/90)

Thanks to all who replied to me.  (blush, blush) Shame on me for not 
reading the man pages more carefully (blush).


Still being incredibly naieve about sockets, I attempt again:
Since last time, I have managed to get somthing flying (ok, limping =-)
I have managed to talk between an unused port (I happened to be using
6000) and I managed to steal the date/time off another machine by calling
port 13.

I've got a process listening to the port on host A and then somthing 
talking to the port on host B.  the pairs purpose is to have A send 
a string to B and have B answer back w/ a diffrent string.

I have a couple new questions now:

	1) When does /etc/services come into play?  I was able to talk
	   over port 6000 w/ no trouble (SOCK_STREAM) WITHOUT having
	   an entry in /etc/services.  Which leads me to wonder what 
	   exactly /etc/services does anyway.  Was this a cardinal sin?
	   Very dangerous?  Very stupid?  All of the above?

	2) If I understnd correctly (which I probably don't) I can 
	   use inetd to start up my executable if there's a request
	   on that port.  Will one of the true net.wizards help this
	   fledgling.wizard by explaining the functions of all these 
	   files?


-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Kevin Franden		    UUCP: {pyramid|lll-crg}!infmx!kevinf
Informix Software Inc
disclaimer("I said what I said and not my employer");
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

There are Lies, Damn lies, Statistics, Benchmarks, and Delivery dates

jik@athena.mit.edu (Jonathan I. Kamens) (06/08/90)

In article <4444@infmx.UUCP>, kevinf@infmx.UUCP (Kevin Franden) writes:
|> 	1) When does /etc/services come into play?  I was able to talk
|> 	   over port 6000 w/ no trouble (SOCK_STREAM) WITHOUT having
|> 	   an entry in /etc/services.  Which leads me to wonder what 
|> 	   exactly /etc/services does anyway.  Was this a cardinal sin?
|> 	   Very dangerous?  Very stupid?  All of the above?

/etc/services is a database which links services (and protocols) to port
numbers.  You don't *have* to use /etc/services to connect to any
particular port.  Its purpose is to give you a record of which ports are
reserved and which are not, and also to allow you to refer to services
by their names rather than by their port numbers.

Let's say that you and I are developing new services that will
eventually be used a lot on the Internet.  We need to choose ports to
work on until we're assigned one officially, and by coincidence (we
don't know each other, of course :-), we both choose the same port.

Well, when we bump into each other and discover that one of us has to
change ports, then either it's going to be very easy (editing
/etc/services to change the port number, since the program looks up the
service by name rather than having the number hard-coded), or a bit
harder (recompiling the program because the port is hard-coded.

|> 	2) If I understnd correctly (which I probably don't) I can 
|> 	   use inetd to start up my executable if there's a request
|> 	   on that port.  Will one of the true net.wizards help this
|> 	   fledgling.wizard by explaining the functions of all these 
|> 	   files?

The file /etc/inetd.conf associates service names from /etc/services
with the programs which should be run when a connection is established
on a service port.  When a daemon is run by inetd after inetd gets a
connection on that daemon's port, the stdin and stdout of the daemon are
connected to the socket which inetd get when it accepted the connection.

This is explained pretty clearly (all except the part about stdin and
stdout, which you're just supposed to know :-) in the man page for inetd.

Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8495			      Home: 617-782-0710

ciancarini-paolo@cs.yale.edu (paolo ciancarini) (04/22/91)

I would like to pass a socket from a process to another;
the two processes in general are unrelated
(they could even be on different machines, say sharing an NSF FS).

To be a little more concrete, I have a concurrent server
that uses a connection-oriented protocol
using the sequence: socket/bind/listen/accept/fork.
I have other processes, not created by the server, that would like to get
the particular socket obtained after accept.

So, is it possible to pass such a socket among unrelated processes?

Please answer by E-mail. I will summarize if there is any interest
(and any answer!).

Paolo Ciancarini