[comp.lang.c] Unix Sockets and Accept

lxg@cs.bham.ac.uk (GriffithsL>) (07/15/90)

  Hi, I wonder if anyone out there can help me. As my masters project I have to 
  write a communication tool on some Suns we have. I've only just started, but
  am having problems with this elementary client-server program. Basically, it
  uses Unix sockets and Curses, and the idea is just to create a simple one-way
  communication from client to server. The problem arises when the server tries
  to "accept" a call from the client. If the Unix socket is already present in 
  the directory, the error message states :

                 "server:accept: No such file or directory"

  It does, however, create the appropriate socket entry in the directory.

  However, if the socket is already present, the error message is : 

                 "server:accept: Error 0"

  Which is a bit puzzling.

  The following is a listing of the server process :

  SERVER.C

#include  "CSdemo.h"
#include  "win.h"
#define   AUTO_PROTOCOL 0
#define   HANDSHAKE "hello" 
#define   BACKLOG 5


    /* PROTOTYPES */

    int get_socket ();
    struct sockaddr_un create_sun_socket_address();
    int address_length ();     
    void bind_to_address ();
    void listen_for_requests();
    int accept_requests();
    int set_tty ();
    WINDOW * get_win();
    void server_drive_scr();

main()
{

     register int Server_Socket, Working_Socket;
     struct sockaddr_un sun_address;
     WINDOW *servers_working_window;


    Server_Socket = get_socket(AF_UNIX, SOCK_STREAM, AUTO_PROTOCOL);

    sun_address = create_sun_socket_address(AF_UNIX, ADDRESS);

    bind_to_address(Server_Socket, sun_address, ADDRESS);

    listen_for_requests(Server_Socket);

    Working_Socket = accept_requests(Server_Socket);

    set_tty(TRUE,TRUE,FALSE);

    servers_working_window = get_win(TRUE, TRUE, WIN_LENGTH, WIN_WIDTH, START_Y, START_X);

    server_drive_scr(servers_working_window, Server_Socket, Working_Socket);

    exit(0);

}


int get_socket (socket_family, socket_type, protocol)
int socket_family, socket_type, protocol;

/* returns a socket see page 125 in "using C"*/ 

{

     register int cs;

     if ((cs=socket(socket_family,socket_type, protocol)) < 0)
	  {
	       perror("client:socket");
	       exit(1);
	  }
     return(cs);
}

struct sockaddr_un create_sun_socket_address(sun_family,address)
int sun_family;
char *address;


     /* Creates and returns socket address which is a struct comprised of 
        the sun family type and the path name */

{

     struct sockaddr_un sun_socket_address;

     sun_socket_address.sun_family = AF_UNIX;
     strcpy(sun_socket_address.sun_path, address);
     return(sun_socket_address); 
}

int address_length (sun_socket_address)
struct sockaddr_un sun_socket_address;

  /* returns the length of the socket address - the structures length, not
                    just the length of the address */

{
     int len;

     len = sizeof(sun_socket_address.sun_family) + 
	           strlen(sun_socket_address.sun_path);
     return(len);
}
  


void bind_to_address (server_socket, sun_socket_address, address)
int server_socket;
struct sockaddr_un sun_socket_address;
char *address;

  /* 
   *  Try to bind the socket to this socket address. Unlink the path address first so that
   *  bind will not fail.
   */

{
     int len;

     unlink(address);

     len = address_length(sun_socket_address);
 
     if (bind(server_socket, &sun_socket_address, len) < 0)   /* connect to the address */
	{ 
	     perror("server:bind");
	     exit(1);
	}
}

void listen_for_requests(server_socket)
int server_socket;

     /* "listen" for requests */

{

   if (listen(server_socket, BACKLOG) < 0)   /* listen for a connect */
	{
	  perror("server:listen");
          exit(1);     
        }
}

int accept_requests (server_socket)
int server_socket;

     /* accept requests. Reference client process thro' working_socket */

{     

   struct sockaddr_un working_socket_address;
   register int working_socket;
   int working_socket_length;

   working_socket_length = sizeof(working_socket_address);

   if ((working_socket = accept(server_socket, &working_socket_address,
                                                           &working_socket_length)) < 0);
       {
	 perror("server:accept");
	 exit(1);
       }
    return(working_socket);
}

/*****  The remaining functions are mostly Curses-window specific *****/


int set_tty (new_line_mapped, echo_on, raw_mode)
bool new_line_mapped, echo_on, raw_mode;

     /* Set tty chracteristics such as newline mapping, echoing and raw mode */

{
          initscr();
	       refresh();
	       if (new_line_mapped == TRUE) nl(); else nonl();
	       if (echo_on == TRUE) echo(); else noecho();
	       if (raw_mode == TRUE) raw(); else noraw();
     }

WINDOW * get_win(scroll_it, stand_out, win_length, win_width, start_y, start_x)
bool scroll_it, stand_out;
int win_length, win_width, start_y, start_x;

     /*
       *  returns a pointer to a newly created WINDOW with scroll enabled
       *  if scroll_it is TRUE and in stand out mode if stand_out is TRUE
       */

{
       WINDOW *new_window;
       new_window = newwin(win_length, win_width, start_y, start_x);
       scrollok(new_window,scroll_it);
       wstandout(new_window, stand_out);
       return(new_window);

  }

void server_drive_scr(win, server_socket, working_socket)
WINDOW *win;
int server_socket, working_socket;

 /* Send the "handshake" to the client process. Then get stream from
    the client process and echo it on to the servers window */

{
        char c;
	FILE *working_socket_ptr;
	
	working_socket_ptr = fdopen(working_socket,"r");

        printf("hello");
	if ((send(server_socket,HANDSHAKE,sizeof(HANDSHAKE),0)) == -1)
            {
		 perror("server:send");
	         exit(1);
	    }
	while ((c = fgetc(working_socket_ptr)) != 'q')
	     {
	       waddch(win,c);
	     }
	close(server_socket);
        endwin();
}  


================================================================================================


  And this is the client process.

  CLIENT.C

#include "CSdemo.h"
#include "win.h"
#define   AUTO_PROTOCOL 0
 
    /* PROTOTYPES */

    int get_socket ();
    struct sockaddr_un create_sun_socket_address();
    int address_length ();
    FILE *connect_to_address ();
    int set_tty ();
    WINDOW * get_win();
    void drive_scr();

main()
{


     register int Client_Socket;
     struct sockaddr_un sun_address;
     WINDOW *clients_working_window;
     FILE *socket_descriptor;


    Client_Socket = get_socket(AF_UNIX, SOCK_STREAM, AUTO_PROTOCOL);

    sun_address = create_sun_socket_address(AF_UNIX, ADDRESS);

    socket_descriptor = connect_to_address(Client_Socket, sun_address);

    set_tty(TRUE,TRUE,FALSE);

    clients_working_window = get_win(TRUE, TRUE, WIN_LENGTH, WIN_WIDTH, START_Y, START_X);

    drive_scr(clients_working_window, socket_descriptor, Client_Socket);

    exit(0);

}


int get_socket (socket_family, socket_type, protocol)
int socket_family, socket_type, protocol;

/* returns a socket see page 125 in "using C"*/ 

{

     register int cs;

     if ((cs=socket(socket_family,socket_type, protocol)) < 0)
	  {
	       perror("client:socket");
	       exit(1);
	  }
     return(cs);
}

struct sockaddr_un create_sun_socket_address(sun_family, address)
int sun_family;
char *address;

     /* Creates and returns socket address which is a struct comprised of 
        the sun family type and the path name */

{

     struct sockaddr_un sun_socket_address;

     sun_socket_address.sun_family = AF_UNIX;
     strcpy(sun_socket_address.sun_path, address);
     return(sun_socket_address); 
}

int address_length (sun_socket_address)
struct sockaddr_un sun_socket_address;

  /* returns the length of the socket address - the structures length, not
                    just the length of the address */

{
     int len;

     len = sizeof(sun_socket_address.sun_family) + 
	           strlen(sun_socket_address.sun_path);
     return(len);
}
  


FILE* connect_to_address (client_socket,  sun_socket_address)
register int client_socket;
struct sockaddr_un sun_socket_address;


  /* try to connect to the sun_socket_address. To succeed, the server process
     must have already bound to this address and issued a "listen". Returns a
     pointer to an open stream for reading */

{
     int len;
     FILE *socket_ptr;

     len = address_length(sun_socket_address);

     if (connect(client_socket, &sun_socket_address, len) < 0)   /* connect to the address */
	{ 
	     perror("client:connect");
	     exit(1);
	}
     socket_ptr = fdopen(client_socket,"r");       /* use stdio to open the socket */
     return(socket_ptr);
}



/* The remaining functions are mostly Curses-window specific */


int set_tty ( new_line_mapped, echo_on,  raw_mode)
bool new_line_mapped,  echo_on,  raw_mode;

     /* Set tty chracteristics such as newline mapping, echoing and raw mode */

{
          initscr();
	       refresh();
	       if (new_line_mapped == TRUE) nl(); else nonl();
	       if (echo_on == TRUE) echo(); else noecho();
	       if (raw_mode == TRUE) raw(); else noraw();
     }

WINDOW * get_win( scroll_it, stand_out, win_length, win_width, start_y,  start_x)
bool scroll_it, stand_out;
int  win_length, win_width, start_y, start_x;


     /*
       *  returns a pointer to a newly created WINDOW with scroll enabled
       *  if scroll_it is TRUE and in stand out mode if stand_out is TRUE
       */

{
       WINDOW *new_window;
       new_window = newwin(win_length, win_width, start_y, start_x);
       scrollok(new_window,scroll_it);
       wstandout(new_window, stand_out);
       return(new_window);

  }

void drive_scr(win, socket_ptr, client_socket )
WINDOW *win;
FILE *socket_ptr;
register int client_socket;


 /* Get the "handshake" from the server process. Then send stream to 
    the server process and echo it on to the clients window */

{
        char c;
	
        while ((c = fgetc(socket_ptr)) != EOF) waddch(win,c); /* get handshake */
		    
	while ((c=wgetch(win)) !='q')
        { 
          waddch(win,c);
	  if ((send(client_socket,&c,1,0)) == -1)  /* send in error */
	       {
		  perror("client:send");
                  exit(1);
               }
        }
	close(client_socket);
        endwin();
}  


=============================================================================================


  These are the two include files :

  CSdemo.h

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <errno.h>

#define ADDRESS       "mysock"  /* address to connect */


  win.c

#include <curses.h>
#define scroll_true TRUE
#define WIN_LENGTH (LINES - 2)
#define WIN_WIDTH  (COLS - 2)
#define START_Y 1
#define START_X 1
#define ALLOW_SCROLL TRUE
#define STAND_OUT TRUE



  As you might guess from the above I am a newcomer to C programming. I know that this is a
  bit naff, expecting others to solve my problems, but any help would be greatly appreciated.
  Incidentally, any critisism of the above on other grounds would also be welcome. Thanks
  in advance,

  Griff, University of Birmingham.