Welcome to EZDefinition.com
Technological Concepts, Abbreviations & Definitions
Main Menu
Main categories
  • Operating Systems
  • Computer Hardware
  • Internet
  • Programming Languages
  • Multimedia
  • Software
  • Security and Encryption
  • Communications and Networking
  • Organizations
  • Books
  • Databases
  • Games
  • E-commerce

    [an error occurred while processing this directive]

  • EZDefinition Sponsor
    Please visit our sponsor Parosoft.com
    Related Links to Socket streams
    [an error occurred while processing this directive]
    Socket streams
    [an error occurred while processing this directive]
    Computer Technologies  Operating Systems  UNIX Socket streams

    Socket streams

    Socket streams

    Analogous to filestreams are sockets or TCP/IP network connections. A socket is a two-way (read/write) pseudo-file node. An open socket stream is like an open file-descriptor. Berkeley sockets are part of the standard C library.
    There are two main kinds of socket: TCP/IP sockets and UNIX domain sockets. UNIX sockets can be used to provide local interprocess communication using a filestream communication protocol. TCP/IP sockets open file descriptors across the network. A TCP/IP socket is a file stream associated with an IP address and a port number. We write to a socket descriptor just as with a file descriptor, either with write() or using send().
    When sending binary data over a network we have to be careful about machine level representations of data. Operating systems (actually the hardware they run on) fall into two categories known as big endian and little endian. The names refer to the byte-order of numerical representations. The names indicate how large integers (which require say 32 bits or more) are stored in memory. Little endian systems store the least significant byte first, while big endian systems store the most significant byte first. For example, the representation of the number 34,677,374 has either of these forms.

    -----------------------------------
    Big | 2 | 17 | 34 | 126 |
    -----------------------------------

    -----------------------------------
    Little | 126 | 34 | 17 | 2 |
    -----------------------------------

    Obviously if we are transferring data from one host to another, both hosts have to agree on the data representation otherwise there would be disastrous consequences. This means that there has to be a common standard of network byte ordering. For example, Solaris (SPARC hardware) uses network byte ordering (big endian), while GNU/Linux (Intel hardware) uses the opposite (little endian). This means that Intel systems have to convert the format every time something is transmitted over the network. UNIX systems provide generic functions for converting between host-byteorder and network-byteorder for small and long integer data:

    htonl, htons, ntohl, ntohs

    Here we list two example programs which show how to make a client-server pair. The server enters a loop, and listens for connections from any clients (the generic address ´INADDR_ANY' is a wildcard for any address on the current local network segment). The client program sends requests to the server as a protocol in the form of a string of the type ´a + b'. Normally ´a' and ´b' are numbers, in which case the server returns their sum to the client. If the message has the special form ´halt + *', where the star is arbitrary, then the server shuts down. Any other form of message results in an error, which the server signals to the client.
    The basic structure of the client-server components in terms of system calls is this:

    Client:

    socket() Create a socket
    connect() Contact a server socket (IP + port)

    while (?)
    {
    send() Send to server
    recv() Receive from server
    }

    Server:

    socket() Create a socket
    bind() Associates the socket with a fixed address
    listen() Create a listen queue

    while()
    {
    reply=accept() Accept a connection request
    recv() Receive from client
    send() Send to client
    }

    /**********************************************************************/
    /* */
    /* The client part of a client-server pair. This simply takes two */
    /* numbers and adds them together, returning the result to the client */
    /* */
    /* Compiled with: */
    /* cc server.c */
    /* */
    /* User types: */
    /* 3 + 5 */
    /* a + b */
    /* halt + server */
    /**********************************************************************/

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>

    #define PORT 9000 /* Arbitrary non-reserved port */
    #define HOST "nexus.iu.hio.no"
    #define bufsize 20

    /**********************************************************************/
    /* Main */
    /**********************************************************************/

    main (argc,argv)

    int argc;
    char *argv[];

    { struct sockaddr_in cin;
    struct hostent *hp;
    char buffer[bufsize];
    int sd;

    if (argc != 4)
    {
    printf("syntax: client a + b\n");
    exit(1);
    }

    if ((hp = gethostbyname(HOST)) == NULL)
    {
    perror("gethostbyname: ");
    exit(1);
    }

    memset(&cin,0,sizeof(cin)); /* Another way to zero memory */

    cin.sin_family = AF_INET;
    cin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
    cin.sin_port = htons(PORT);

    printf("Trying to connect to %s = %s\n",HOST,inet_ntoa(cin.sin_addr));

    if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)
    {
    perror("socket");
    exit(1);
    }

    if (connect(sd,&cin,sizeof(cin)) == -1)
    {
    perror("connect");
    exit(1);
    }

    sprintf(buffer,"%s + %s",argv[1],argv[3]);

    if (send(sd,buffer,strlen(buffer),0) == -1)
    {
    perror ("send");
    exit(1);
    }

    if (recv(sd,buffer,bufsize,0) == -1)
    {
    perror("recv");
    exit (1);
    }

    printf ("Server responded with %s\n",buffer);

    close (sd);
    unlink("./socket");
    }

    /**********************************************************************/
    /* */
    /* The server part of a client-server pair. This simply takes two */
    /* numbers and adds them together, returning the result to the client */
    /* */
    /* Compiled with: */
    /* cc server.c */
    /* */
    /**********************************************************************/

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>

    #define PORT 9000
    #define bufsize 20
    #define queuesize 5
    #define true 1
    #define false 0

    /**********************************************************************/
    /* Main */
    /**********************************************************************/

    main ()

    { struct sockaddr_in cin;
    struct sockaddr_in sin;
    struct hostent *hp;
    char buffer[bufsize];
    int sd, sd_client, addrlen;

    memset(&sin,0,sizeof(sin)); /* Another way to zero memory */
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY; /* Broadcast address */
    sin.sin_port = htons(PORT);

    if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)
    {
    perror("socket");
    exit(1);
    }

    if (bind(sd,&sin,sizeof(sin)) == -1) /* Must have this on server */
    {
    perror("bind");
    exit(1);
    }

    if (listen(sd,queuesize) == -1)
    {
    perror("listen");
    exit(1);
    }

    while (true)
    {
    if ((sd_client = accept(sd,&cin,&addrlen)) == -1)
    {
    perror("accept");
    exit(1);
    }

    if (recv(sd_client,buffer,sizeof(buffer),0) == -1)
    {
    perror("recv");
    exit(1);
    }

    if (!DoService(buffer))
    {
    break;
    }

    if (send(sd_client,buffer,strlen(buffer),0) == -1)
    {
    perror("send");
    exit(1);
    }

    close (sd_client);
    }

    close (sd);
    printf("Server closing down...\n");
    }

    /**************************************************************/

    DoService(buffer)

    char *buffer;

    /* This is the protocol section. Here we must */
    /* check that the incoming data are sensible */

    { int a=0,b=0;

    printf("Received: %s\n",buffer);
    sscanf(buffer,"%d + %d\n",&a,&b);

    if (a > 0 && b> 0)
    {
    sprintf(buffer,"%d + %d = %d",a,b,a+b);
    return true;
    }
    else
    {
    if (strncmp("halt",buffer,4) == 0)
    {
    sprintf(buffer,"Server closing down!");
    return false;
    }
    else
    {
    sprintf(buffer,"Invalid protocol");
    return true;
    }
    }
    }

    In the example we use ´streams' to implement a typical input/output behaviour for C. A stream interface is a so-called reliable protocol. There are other kinds of sockets too, called unrealiable, or UDP sockets. Features to notice on the server are that we must bind to a specific address. The client is always implicitly bound to an address since a socket connection always originates from the machine on which the client is running. On the server however we want to know which addresses we shall be receiving requests from. In the above example we use the generic wildcard address ´INADDR_ANY' which means that any host can connect to the server. Had we been more specific, we could have limited communication to two machines only.
    By calling ´listen()' we set up a queue for incoming connections. Rather than forking a separate process to handle each request we set up a queue of a certain depth. If we exceed this depth then new clients rtying to connect will be refused connection.
    The ´accept' call is the mechanism which extracts a ´reply handle' from the socket. Using the handle obtained from this call we can reply to the client without having to open a special socket explicitly.
    An improved server side connection can be setup, reading the service name from ´/etc/services' and setting reusable socket options to avoid busy signals, like this:

    struct sockaddr_in cin, sin;
    struct servent *server;
    int sd, addrlen = sizeof(cin);
    int portnumber, yes=1;

    if ((server = getservbyname(service-name,"tcp")) == NULL)
    {
    CfLog(cferror,"Couldn't get cfengine service","getservbyname");
    exit (1);
    }

    bzero(&cin,sizeof(cin));

    /* Service returns network byte order */

    sin.sin_port = (unsigned short)(server->s_port);
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_family = AF_INET;

    if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)
    {
    CfLog(cferror,"Couldn't open socket","socket");
    exit (1);
    }

    if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR,
    (char *) &yes, sizeof (int)) == -1)
    {
    CfLog(cferror,"Couldn't set socket options","sockopt");
    exit (1);
    }


    if (bind(sd,(struct sockaddr *)&sin,sizeof(sin)) == -1)
    {

    }

    /* etc */


    [an error occurred while processing this directive]

    [an error occurred while processing this directive]
     

    All Rights Reserved

    Terms of usage   Please read our privacy stetment
    Copyright © 1999-2006 EZDefinition.com

     

    [an error occurred while processing this directive]