Unix sockets
GriffithsL>
lxg at cs.bham.ac.uk
Sun Jul 15 05:40:54 AEST 1990
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.
More information about the Comp.lang.c
mailing list