[comp.unix.questions] What is 'sockets' ???

amigaeb@altger.UUCP (Ronny Hansen) (08/19/88)

Help...

I am trying to learn about socket's, but I cant find anything
to learn from. No books. No magazines. No nothing.
So I am posting this so thet maybe I will find out more
about sockets.

Thanx

/> Ronny />

tsui@silver.bacs.indiana.edu (08/23/88)

/* Written  4:16 pm  Aug 18, 1988 by amigaeb@altger in silver:comp.unix.questions */
/* ---------- "What is 'sockets' ???" ---------- */
Help...

I am trying to learn about socket's, but I cant find anything
to learn from. No books. No magazines. No nothing.
So I am posting this so thet maybe I will find out more
about sockets.

Thanx

/> Ronny />
/* End of text from silver:comp.unix.questions */


try %man sockets

bph@buengc.BU.EDU (Blair P. Houghton) (08/24/88)

In article <916@altger.UUCP> amigaeb@altger.UUCP (Ronny Hansen) writes:
>I am trying to learn about socket's, but I cant find anything
>to learn from. No books. No magazines. No nothing.

Look for "A 4.2BSD Interprocess Communication Primer" by S.J. Leffler,
R.S. Fabry, and Bill Joy.  I was looking for a long time for stuff
on sockets until I found this 23-pager buried in the "supplemental
documentation" volumes of my local Ultrix-32 document set.

It's everything you ever wanted to know about sockets, period.

Pure literary review:  it's one of the hardest things to read I've ever
read.  It ain't the material, either.  It's just a style problem.
Well, noone said computerz was e-z...

				--Blair
				  "Although I once said
				   'computerz iz _too_ e-z'..."

mike@ames.arc.nasa.gov (Mike Smithwick) (08/24/88)

In article <913@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>In article <916@altger.UUCP> amigaeb@altger.UUCP (Ronny Hansen) writes:
>>I am trying to learn about socket's, but I cant find anything
>>to learn from. No books. No magazines. No nothing.
>
>Look for "A 4.2BSD Interprocess Communication Primer" by S.J. Leffler,
>R.S. Fabry, and Bill Joy.  I was looking for a long time for stuff
>on sockets until I found this 23-pager buried in the "supplemental
>documentation" volumes of my local Ultrix-32 document set.
>

You may want to track down a copy of the Networking primer supplied with
the new Sun OS 4.0 manual set. It is surprisingly clear. Even after working
with sockets for over a year, they were still alot like black-boxes to
me until I read that. Also, take a look at Maurice Bach's book, "The
Design of the Unix Operating System". Even though he focusses on Sys V, he
covers important issues in BSD including Sockets.


-- 
			   *** mike (starship janitor) smithwick ***
"You can fool some of the people all of the time, or all of the people
 some of the time, but you can't fool Mom".
[disclaimer : nope, I don't work for NASA, I take full blame for my ideas]

madd@bu-cs.BU.EDU (Jim Frost) (08/25/88)

In article <913@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
|In article <916@altger.UUCP> amigaeb@altger.UUCP (Ronny Hansen) writes:
|>I am trying to learn about socket's, but I cant find anything
|>to learn from. No books. No magazines. No nothing.
|
|Look for "A 4.2BSD Interprocess Communication Primer" [...]
|Pure literary review:  it's one of the hardest things to read I've ever
|read.  It ain't the material, either.  It's just a style problem.
|Well, noone said computerz was e-z...

I found that it was nice for info once I understood what was happening
but it's not the kind of thing to unleash on a beginner.  Here's my
quick primer.

There are only a couple of UNIX commands which take care of handling
sockets.  These are:

	socket()
	bind()
	connect()
	accept()
	read()
	write()
	close()

close() does exactly what you'd expect.

socket() is used to create a file descriptor that is used to refer to
a new socket.  You have to tell it what kind of socket you are using,
usually SOCK_STREAM or SOCK_DGRAM.  TCP/IP connections are
SOCK_STREAM; all of this info will be based on using stream-type
sockets.

The bind() command is used to bind the local address to the socket,
much like establishing the phone number of the phone you're using.

connect() calls another system to bind the far address to the socket,
much like dialing the phone.  accept() is used by the other end of the
connection; it's analogous to someone picking up the phone.  It binds
the caller's address to the socket.  Once both addresses are known to
the socket, data can flow.

An example routine that creates a socket and calls to another is:

  int hopen(hostname)
  char *hostname;
  { struct sockaddr_in sa;
    struct hostent     *hp;
    int a, sock;

    /* find host table entry
     */

    if((hp= gethostbyname(hostname)) == NULL) {
      errno= ECONNREFUSED; /* return some reasonable error */
      return(-1);
    }

    /* get communications protocol
     */

    bzero(&sa,sizeof(sa));
    if (getprotobyname("tcp") == NULL) {
      errno= ENOPROTOOPT;
      return(-1);
    }

    /* set up local address (host and port number)
     */

    bcopy(hp->h_addr,(char *)&sa.sin_addr,hp->h_length);
    sa.sin_family= hp->h_addrtype;
    sa.sin_port= htons((u_short)PORTNUM);

    /* create socket and do connection
     */

    if ((sock= socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) /* get socket */
      return(-1);
    if (connect(sock,&sa,sizeof sa) < 0)                 /* connect */
      return(-1);
    return(sock);
  }

To accept a connection, things are a little different.  The following
two functions do it:

  int get_connection() {
    struct sockaddr_in isa;
    int i, sock;

    if ((s= establish(PORTNUM)) < 0) {
      return(-1);

    i = sizeof(isa);                   /* find socket's "name" */
    getsockname(sock,&isa,&i);

    if ((t = accept(sock,&isa,&i)) < 0)
      return(-1);
    return(sock);
  }

  /* 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;

    gethostname(myname,MAXHOSTNAME);            /* who are we? */
    bzero(&sa,sizeof(struct sockaddr_in));
    hp= gethostbyname(myname);                  /* get our address info */
    if (hp == NULL)                             /* we don't exist !? */
      return(-1);
    sa.sin_family= hp->h_addrtype;              /* set up info for new socket */
    sa.sin_port= htons(portnum);
    if ((s= socket(AF_INET,SOCK_STREAM,0)) < 0) /* make new socket */
      return(-1);
    if (bind(s,&sa,sizeof sa,0) < 0)
      return(-1);                               /* bind socket */
    return(s);
  }

Usually the accept() call is done in a loop and programs are forked
off to handle the connected sockets.  This is a little more complex so
I'm not throwing in the code here.

After you have a socket you have to dump things through it.  Sockets
are bidirectional so either end can read or write to it.

Writing to a socket is done through the normal file I/O functions.  I
recommend checking to make sure the write actually wrote all that you
told it to; more in read().

Reading is handled the same way as normal WITH ONE EXCEPTION.  People
expect a read() to return the amount of data that it read, but usually
they also expect it to read as much as they tell it to.  This is almost
always not the case with sockets.  The correct way to read a specific
amount of information is to keep reading in a loop until you hit some
limit.  This is the function I use to read "n" characters into a buffer:

  int hread(s,buf,n)
  int  s;
  char *buf;
  int  n;
  { 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);
  }

I recommend using a very similar routine to handle writes.

If you forget the looping part you end up losing characters.  It took
me quite some time to track this down the first time I was writing
networking code and I'd like to help newcomers avoid that.

This ought to give you enough information to start using sockets for
networking applications.  It's not complete by any means since it
deals with only TCP/IP stream connections and ignores datagram-style
connections but most of the ideas are similar except datagram
connections (at least UDP) do not guarantee delivery of datagrams and
things get much tougher.  Take a look at real applications for other
examples.

jim frost
madd@bu-it.bu.edu

david@geac.UUCP (David Haynes) (08/26/88)

In article <24549@bu-cs.BU.EDU> madd@bu-it.bu.edu (Jim Frost) writes:
>In article <913@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>|In article <916@altger.UUCP> amigaeb@altger.UUCP (Ronny Hansen) writes:
>|>I am trying to learn about socket's, but I cant find anything
>|>to learn from. No books. No magazines. No nothing.
>|
>|Look for "A 4.2BSD Interprocess Communication Primer" [...]
>|Pure literary review:  it's one of the hardest things to read I've ever
>|read.  It ain't the material, either.  It's just a style problem.
>|Well, noone said computerz was e-z...
>
>I found that it was nice for info once I understood what was happening
>but it's not the kind of thing to unleash on a beginner.  Here's my
>quick primer.
>
[Jim's Primer Deleted]

I have found the following document to be of use to the folks here.
It is formatted for LaTeX, but can be quickly modified to, say, nroff.

-david-

---------------------( cut here )---------------------------
\documentstyle[fullpage,11pt]{article}
\title{A Cookbook Approach to\\ Interprocess Communication}
\author{David Haynes}
\date{November 19, 1987}
\begin{document}
\maketitle
\newpage
\tableofcontents
\newpage
\section{Introduction}
In the following document samples of structured code  are presented as
a cookbook approach for the creation of programs utilizing interprocess
communication of the Berkeley socket variety. There are three types of
interprocess communication presented in this paper for completeness.
\newpage
\section{UNIX Domain Communication}
\subsection{Client}
\begin{verbatim}
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

main()
{
        char *msg, ack[2];
        int i, sd;
        struct sockaddr_un sin;
/*
 *      set up a unix domain socket
 */
        strcpy(sin.sun_path, "./socket");
        if((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
                perror("socket");
                exit(1);
        }
/*
 *      connect to the UNIX socket ./socket
 */
        if(connect(sd, 0, 0) == -1) {
                perror("connect");
                exit(1);
        }
/*
 *      send a message to the server
 */
        if(send(sd, msg, sizeof(msg), 0) == -1) {
                perror("send");
                exit(1);
        }
/*
 *      wait for a message to come back from the server
 */
        if(recv(sd, ack, 2, 0) == -1) {
                perror("recv");
                exit(1);
        }
/*
 *      close the socket connection
 */
        close(sd);
}
\end{verbatim}
\newpage
\subsection{Server}
\begin{verbatim}
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

main()
{
        char *msg, ack[2];
        register int i;
        int sd, sd_current, count;
        struct sockaddr_un sin;
/*
 *      get a UNIX domain socket
 */
        strcpy(sin.sun_path, "./socket");
        if((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
                perror("socket");
                exit(1);
        }
/*
 *      bind the socket to the socket name ./socket
 */
        if(bind(sd, &sin, sizeof(sin)) == -1) {
                perror("bind");
                exit(1);
        }
/*
 *      show that we are willing to listen
 */
        if(listen(sd, 5) == -1) {
                perror("listen");
                exit(1);
        }
/*
 *      wait for someone to talk to us
 */
        if((sd_current = accept(sd, 0, 0)) == -1) {
                perror("accept");
                exit(1);
        }
/*
 *      get a message from the client
 */
        if(recv(sd_current, msg, MSG_SIZE, 0) == -1) {
                perror("recv");
                exit(1);
        }
/*
 *      acknowledge the message
 */
        if(send(sd_current, ack, 2, 0) == -1) {
                perror("send");
                exit(1);
        }
/*
 *      close it up
 */
        close(sd_current);
        close(s);
}
\end{verbatim}
\newpage
\section{Internet Domain Communication}
\subsection{Client}
\begin{verbatim}
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define PORT        0x1234
#define HOST        "fileserver"

main()
{
        char *msg, ack[2];
        int i, sd;
        struct sockaddr_in sin;
        struct sockaddr_in pin;
        struct hostent *hp;
/*
 *      go find out about the desired host machine
 */
        if((hp = gethostbyname(HOST)) == 0) {
                perror("gethostbyname");
                exit(1);
        }
/*
 *      fill in the socket structure with host information
 */
        memset(&pin, 0, sizeof(pin));
        pin.sin_family = AF_INET;
        pin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
        pin.sin_port = htons(PORT);
/*
 *      grab an internet domain socket
 */
        if((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
                perror("socket");
                exit(1);
        }
/*
 *      connect to PORT on HOST
 */
        if(connect(sd, &pin, sizeof(pin)) == -1) {
                perror("connect");
                exit(1);
        }
/*
 *      send a message to the server PORT on machine HOST
 */
        if(send(sd, msg, sizeof(msg), 0) == -1) {
                perror("send");
                exit(1);
        }
/*
 *      wait for an acknowledgement handshake
 */
        if(recv(sd, ack, 2, 0) == -1) {
                perror("recv");
                exit(1);
        }
/*
 *      shut it down
 */
        if(shutdown(sd, 2) == -1) {
                perror("shutdown");
                exit(1);
        }
        close(sd);
}
\end{verbatim}
\newpage
\subsection{Server}
\begin{verbatim}
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define PORT 0x1234

main()
{
        char *msg, ack[2];
        register int i;
        int sd, count, cc, fromlen, tolen;
        int addrlen;
        struct sockaddr_in sin;
        struct sockaddr_in pin;
/*
 *      get an internet domain socket
 */
        if((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
                perror("socket");
                exit(1);
        }
/*
 *      complete the socket structure
 */
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = INADDR_ANY;
        sin.sin_port = htons(PORT);
/*
 *      bind the socket to the port number
 */
        if(bind(sd, &sin, sizeof(sin)) == -1) {
                perror("bind");
                exit(1);
        }
/*
 *      show that we are willing to listen
 */
        if(listen(sd, 5) == -1) {
                perror("listen");
                exit(1);
        }
/*
 *      wait for someone to talk to us
 */
        if((sd_current = accept(sd, &pin, &addrlen)) == -1) {
                perror("accept");
                exit(1);
        }
/*
 *      get a message from the client
 */
        if(recv(sd_current, msg, conf.size, 0) == -1) {
                perror("recv");
                exit(1);
        }
/*
 *      send an acknowledgement message
 */
        if(send(sd_current, ack, 2, 0) == -1) {
                perror("send");
                exit(1);
        }
/*
 *      close it up
 */
        close(sd_current);
        close(sd);
}
\end{verbatim}
\newpage
\section{UDP Domain Communication}
\subsection{Client}
\begin{verbatim}
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <signal.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>

void t_nop() {signal(SIGALRM, t_nop);}

main()
{
        char buf[512], ack[2];
        int s, retry;
        extern int errno;                /* error type */
        struct hostent *hp;                /* our port descriptor */
        struct servent *sp;                /* server's port descriptor */
        struct sockaddr_in myaddr;        /* our internet descriptor */
        struct sockaddr_in svaddr;        /* server's internet descriptor */
/*
 *      clear and initialize the socket descriptors
 */
        memset((char *)&myaddr, 0, sizeof(struct sockaddr_in));
        memset((char *)&svaddr, 0, sizeof(struct sockaddr_in));
        svaddr.sin_family = AF_INET;
        hp = gethostbyname("fileserver");
        if(hp == NULL) {
                fprintf(stderr, "fileserver not found in /etc/hosts\n");
                exit(1);
        }
        svaddr.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
        sp = getservbyname("example", "udp");
        if(sp == NULL) {
                fprintf(stderr, "example not found in /etc/services\n");
                exit(1);
        }
        svaddr.sin_port = sp->s_port;
/*
 *      create the socket
 */
        s = socket(AF_INET, SOCK_DGRAM, 0);
        if(s == -1) {
                perror("socket");
                exit(1);
        }
/*
 *      add some home truths about ourselves
 */
        myaddr.sin_family = AF_INET;
        myaddr.sin_port = 0;
        myaddr.sin_addr.s_addr = INADDR_ANY;
/*
 *      bind the socket to our port
 */
        if(bind(s, &myaddr, sizeof(struct sockaddr_in)) == -1) {
                perror("bind");
                exit(1);
        }
/*
 *      attempt to send a message to the server
 */
                signal(SIGALRM, t_nop);
                retry = 5;
again:        a        if(sendto(s, &obs, sizeof(OBS), 0,
                        &svaddr, sizeof(struct sockaddr_in)) == -1) {
                        perror("sendto");
                        exit(1);
                }
                alarm(5);
                if(recv(s, ack, 2, 0) == -1) {
                        if(errno == EINTR) {
                                if(--retry) {
                                        goto again;
                                }
                                else {
                                        perror("recv");
                                        exit(1);
                                }
                        }
                        else {
                                perror("recv");
                                exit(1);
                        }
                }
                alarm(0);
        }
}
\end{verbatim}
\subsection{Server}
\begin{verbatim}
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>

main()
{
        char *msg;                        /* message pointer */
        char ack[2];                        /* ack buffer */
        int s, cc, addrlen;
        struct sockaddr_in myaddr;        /* my internet location */
        struct sockaddr_in claddr;        /* the client's internet location */
        struct servent *sp;                /* the port map for my service */
/*
 *      clear and initialize the socket decriptors
 */
        memset((char *)&myaddr, 0, sizeof(struct sockaddr_in));
        memset((char *)&claddr, 0, sizeof(struct sockaddr_in));
        myaddr.sin_family = AF_INET;
        myaddr.sin_addr.s_addr = INADDR_ANY;
        sp = getservbyname("example", "udp");
        if(sp == NULL) {
                printf("Can not find example in /etc/services\n");
                exit(1);
        }
        myaddr.sin_port = sp->s_port;
/*
 *      grab an internet socket descriptor
 */
        if((s = socket(AF_INET, SOCK_DGRAM, 0)) == ERROR) {
                perror("socket");
                exit(1);
        }
/*
 *      bind the socket to our port description as specified above
 */
        if(bind(s, &myaddr, sizeof(struct sockaddr_in)) == ERROR) {
                perror("bind");
                exit(1);
        }
/*
 *      wait for a message to arrive
 */
        errno = 0;  /* no errors at this point */
        addrlen = sizeof(struct sockaddr_in);
/*
 *      get the message which is being sent
 */
        cc = recvfrom(s, &msg, sizeof(msg), 0, &claddr, &addrlen);
        if(cc == -1) {
                perror("recv");
                exit(1);
        }
/*
 *      send an acknowledgement message
 */
        if(sendto(s, ack, 2, 0, &claddr, addrlen) == -1) {
                perror("sendto");
                exit(1);
        }
/*
 *      close it up
 */
        close(s);
}
\end{verbatim}
\end{document}

squires@hpcvlx.HP.COM (Matt Squires) (08/26/88)

/ hpcvlx:comp.unix.questions /
amigaeb@altger.UUCP (Ronny Hansen)
/  2:16 pm  Aug 18, 1988 /

Help...

I am trying to learn about socket's, but I cant find anything
to learn from. No books. No magazines. No nothing.
So I am posting this so thet maybe I will find out more
about sockets.

Thanx

/> Ronny />
----------

I have recently written two socket programs, one that uses DGRAMS, and one
that uses STREAM type sockets.  All they do is return any input they get
backwards.  If you like, I could mail them to you.  Then you could look
at the programs, look at various man pages, and then attempt to write a
socket program of your own.  That's how I learned.

mcs

hulsebos@philmds.UUCP (Rob Hulsebos) (08/29/88)

In article <916@altger.UUCP> amigaeb@altger.UUCP (Ronny Hansen) writes:
>I am trying to learn about socket's, but I cant find anything
>to learn from. No books. No magazines. No nothing.

Not quite true: _almost_ nothing. But I have been able to find some existing
doc. Not much, but it's better than the BSD primer.

More info on sockets can be found in:

   C Programming In The Berkeley Environment
   R. Nigel Horspool
   Prentice-Hall Canada
   ISBN 0-13-109760-1
   price for my copy was 54 Dutch guilders

This book tries to teach you C but also treats some of the BSD features.
In chapter 12, the programs and explanations are given for a computerized
bulletin-board system consisting of a client- and a server-part.

The book also mentions more literature:

   Tutorial Examples of Interprocess Communication in Berkeley 4.2BSD
   Stuart Sechrest
   Report UCB/CSD84/191
   Computer Science Division of University of California
   Berkeley 94720

Also,the following book gives some info about 4.3's interface to IP:

   Internetworking with TCP/IP
   Douglas Comer
   Prentice-Hall International
   ISBN 0-13-470188-7
   price for my copy was 80 Dutch guilders

Hope this helps.

------------------------------------------------------------------------------
R.A. Hulsebos                                       ...!mcvax!philmds!hulsebos
Philips I&E Automation Modules                            phone: +31-40-785723
Building TQ-III-1, room 11
Eindhoven, The Netherlands                                # cc -O disclaimer.c
------------------------------------------------------------------------------