[comp.windows.news] sockets

prove@batcomputer.tn.cornell.edu (Roger Ove) (10/24/89)

Could someone please post an example using a socket connection
between 2 NeWS processes?  I have a pixrect image stored in a string
and want to display it with readcanvas imagecanvas, without going to
disk.  An example receiving the data via separate socket from the C
client would also be useful (to avoid NeWS string length restrictions).

thanks,
Roger Ove   ove@ncsa.uiuc.edu

andrew@isgtec.UUCP (Andrew) (10/26/89)

Roger,
   This sounds very interesting. Could you please post any responses
you receive. (Post to the net, becuase my mailer is down.)

Thanks in advance.

>Could someone please post an example using a socket connection
>between 2 NeWS processes?  I have a pixrect image stored in a string
>and want to display it with readcanvas imagecanvas, without going to
>disk.  An example receiving the data via separate socket from the C
>client would also be useful (to avoid NeWS string length restrictions).


-- 
Andrew MacLean                     ...uunet!mnetor!lsuc!isgtec!andrew
Success is a journey, not an adventure!   ...utzoo!lsuc!isgtec!andrew
ISG Technologies Inc. 3030 Orlando Dr. Mississauga. Ont. Can. L4V 1S8

prove@batcomputer.tn.cornell.edu (Roger Ove) (10/26/89)

In response to my own query:

> Could someone please post an example using a socket connection
> between 2 NeWS processes?  I have a pixrect image stored in a string
> and want to display it with readcanvas imagecanvas, without going to
> disk.  An example receiving the data via separate socket from the C
> client would also be useful (to avoid NeWS string length restrictions).

There is no difficulty in passing data between the C Client and
NeWS process via a secondary socket connection, the most obvious
thing works (I'll mail the example if anyone is interested).
Help with the first question would still be appreciated.

thanks,
Roger Ove   ove@ncsa.uiuc.edu

sjs@spectral.ctt.bellcore.com (Stan Switzer) (10/27/89)

In article <9150@batcomputer.tn.cornell.edu> prove@batcomputer.tn.cornell.edu (Roger Ove) writes:
> In response to my own query:
> 
> > Could someone please post an example using a socket connection
> > between 2 NeWS processes?  I have a pixrect image stored in a string
> > and want to display it with readcanvas imagecanvas, without going to
> > disk.  An example receiving the data via separate socket from the C
> > client would also be useful (to avoid NeWS string length restrictions).
> 
> There is no difficulty in passing data between the C Client and
> NeWS process via a secondary socket connection, the most obvious
> thing works (I'll mail the example if anyone is interested).
> Help with the first question would still be appreciated.
> 
> thanks,
> Roger Ove   ove@ncsa.uiuc.edu

OK, here's an example.

The trick is that file names of the form (%socket[cl]nnn[.nnnnn]) are
special.  "c" means connect.  "l" means listen.  The first number is
the socket number.  The second number, if present, is the internet
address (in decimal!).  If the address is left off, localhost is the
default.

I have the opposite problem.  I want to send a rasterfile via
writecanvas to a C client from NeWS.  I basically know how to do it,
but I haven't done much socket hacking (in C) so an example would be
greatly appreciated.

I don't think you can do UDP sockets though, which is too bad since I
am sorely tempted to write a SunRPC handler in NeWS so that I can
write a yellow-pages client.

Example follows.  I haven't the foggiest idea why normal EOF detection
on "currentfile" doesn't work.

Stan Switzer  sjs@bellcore.com

----------
#!/usr/NeWS/bin/psh
% simple socket I/O example

/buff1 100 string def
/buff2 100 string def

/receiver {
    /insocket (%socketl2345) (r) file acceptconnection def
    { % loop...
	insocket buff1 readline not { exit } if  % read a line from socket
	==	% print a line
    } loop
    (End of Input) ==
} fork def

pause pause % give the process a chance to get launched

{ % sender:
    /outsocket (%socketc2345) (w) file def
    { % loop...
	currentfile buff2 readline not { exit } if % read a line from stdin
	dup (EOF) eq { exit } if
	outsocket exch writestring
	outsocket (\n) writestring
	outsocket flushfile
    } loop
    /outsocket null def % close output socket
    receiver waitprocess
} exec
line 1
another line
line 3
last line
EOF

prove@batcomputer.tn.cornell.edu (Roger Ove) (10/27/89)

Here is a demo with the C client sending data to the NeWS process
by an independent socket.  The file show.c isn't used by the demo,
it is an interface to fortran on a Cray.  I thinkg the Makefile will
have to be modified to compile the demo on anything but a Cray.

Roger Ove

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by tralfaz!ove on Fri Oct 27 10:09:09 EST 1989
# Contents:  Makefile README opensock.c replay.c show.c show.cps
 
echo x - Makefile
sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
# C/NeWS pixrect image displayed over network

OBJ = 	replay.o opensock.o
LIBS =	$(NEWSHOME)/clientsrc/lib/NeWS/libcps.a /usr/lib/libnet.a

@.SUFFIXES :
@.SUFFIXES : .o .c

replay : $(OBJ)
	cc -o replay $(OBJ) $(LIBS)

replay.o : show.h

show.o : show.h

show.h : show.cps
	cps show.cps

@.c.o :
	cc -O -c -I$(NEWSHOME)/clientsrc/include $*.c

@//E*O*F Makefile//
chmod u=rw,g=rw,o=rw Makefile
 
echo x - README
sed 's/^@//' > "README" <<'@//E*O*F README//'
This is an example of sending data from the C client to a NeWS
process by a secondary socket connection.  It displays a sequence
of pixrect image files (names read from the command line).  The
Makefile is for a Cray, some changes will be necessary to compile
it on a Sun (source should require no changes).  This example
sets up a new socket connection for each image, which probably
isn't such a great idea.


@//E*O*F README//
chmod u=rw,g=,o= README
 
echo x - opensock.c
sed 's/^@//' > "opensock.c" <<'@//E*O*F opensock.c//'
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>


/* Open a socket to NeWS_addr.(port+1), for writing.  Return the 
 * stream.
 */
FILE	*open_socket_handle()
{
FILE	*handle ;
char	*server ;
int	fd ;
char	*semi, *dot ;
struct sockaddr_in	sin ;

	server = (char *) getenv("NEWSSERVER") ;
	fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) ;
	if (server && fd >= 0) {
		extern char *rindex() ;
		register char *t ;
		if (semi = rindex(server, ';')) *semi = 0 ;
		if (dot = rindex(server, '.')) {	/* 1 plus NeWS port */
			*dot = 0 ;
			sin.sin_port = htons(atoi(dot + 1)+1);
		}
		sin.sin_addr.s_addr = htonl(inet_addr(server)) ;
		if (dot) *dot = '.' ;
		if (semi) *semi = ';' ;
	}
	else return(0) ;

	sin.sin_family = AF_INET ;
	if (connect(fd, &sin, sizeof(sin)) < 0) {
		close(fd) ;
		return(0) ;
	}
	handle = fdopen(fd, "w") ;

	return (handle) ;
}

@//E*O*F opensock.c//
chmod u=rw,g=rw,o=rw opensock.c
 
echo x - replay.c
sed 's/^@//' > "replay.c" <<'@//E*O*F replay.c//'
/* Replay
*
*	Simple NeWS display of pixrect files across a network.
*	Invoke as
*		replay file1 file2 ....  filen
*	where the files are pixrect image files
*/

#include <stdio.h>
#include "show.h"

#define MAXLENGTH	(512*1024)

main(argc, argv)
int	argc ;
char	*argv[] ;
{
int	i, j, len ;
char	s[MAXLENGTH] ;
char	filename[100] ;
FILE	*in, *sock, *open_socket_handle() ;

	for (i=1; i<argc; i++) {
		sprintf(filename, "%s", argv[i]) ;
		fprintf(stderr, "filename %s\n", filename) ;
		if ( (in = fopen(filename, "r")) == 0 ) break ;
		if ( (len = fread(s, 1, MAXLENGTH, in)) <= 0 ) break ;

		/* initialize PS on 1st entry */
		if (i == 1) {
			ps_open_PostScript() ;
			ps_initialize("Pixrect Image Demo") ;
			ps_flush_PostScript() ;
		}

		/* open socket connection */
		for (j=0; j<10; j++) {
			sock = open_socket_handle() ;
			if (sock != 0) break ;
			sleep(2) ;
		}
		if (sock==0) {
			fprintf(stderr, "Connection timeout\n") ;
			exit() ;
		}

		/* write pixrect data */
		fwrite(s, 1, len, sock) ;
		fflush(sock) ;
	}
	sleep(10) ;
	ps_close_PostScript() ;
}

@//E*O*F replay.c//
chmod u=rw,g=rw,o=rw replay.c
 
echo x - show.c
sed 's/^@//' > "show.c" <<'@//E*O*F show.c//'
/* Show
*	simple NeWS display of an array
*/

#include <stdio.h>
#include <malloc.h>
#include <math.h>
#include "show.h"
#include <fortran.h>

#define max(a,b)	(a>=b ? a : b)


NEWSSTOP()
{
	ps_close_PostScript() ;
}



/* Display a field using NeWS.  Creates a string representation of a
 * Pixrect file and uses the NeWS readimage facility.
 */
#define RAS_MAGIC	0x59a66a95
struct rasterfile {
	long	ras_magic ;
	long	ras_width ;
	long	ras_height ;
	long	ras_depth ;
	long	ras_length ;
	long	ras_type ;
	long	ras_maptype ;
	long	ras_maplength ;
} ;

NEWSSHOW(mxp, myp, array_fcd)
int	*mxp, *myp ;
_fcd	array_fcd ;		/* fortran character descriptor */
{
static int	entered = 0 ;
FILE	*mapfile, *sock, *open_socket_handle() ;
int	mx = *mxp, my = *myp ;
int	i ;
int	len = mx*my + 4*8 + 3*256 ;
unsigned char *array = (unsigned char*)_fcdtocp(array_fcd);
unsigned char *s = malloc(len + 1) ;
unsigned char *data = &s[4*8 + 3*256] ;
unsigned char *red = &(s[4*8]) ;
unsigned char *green = &(s[4*8+256]) ;
unsigned char *blue = &(s[4*8+2*256]) ;
struct rasterfile pixrect ;

	/* set up the pixrect header */
	pixrect.ras_magic = RAS_MAGIC ;
	pixrect.ras_width = mx ;
	pixrect.ras_height = my ;
	pixrect.ras_depth = 8 ;
	pixrect.ras_length = mx*my ;
	pixrect.ras_type = 1 ;
	pixrect.ras_maptype = 1 ;
	pixrect.ras_maplength = 3*256 ;

	/* copy the header into s, can't just memcpy, struct on 64bit boundaries */
	((long*)s)[0] = (pixrect.ras_magic << 32) + pixrect.ras_width ;
	((long*)s)[1] = (pixrect.ras_height << 32) + pixrect.ras_depth ;
	((long*)s)[2] = (pixrect.ras_length << 32) + pixrect.ras_type ;
	((long*)s)[3] = (pixrect.ras_maptype << 32) + pixrect.ras_maplength ;
	
	/* add the rgb color map */
	if ( NULL == (mapfile = fopen( "color.map", "rb" )) )
		abort( "shit, where did the color.map file go?" ) ;
	for ( i=0; i<256; i++ ) red[i] = (unsigned char)fgetc(mapfile) ;
	for ( i=0; i<256; i++ ) green[i] = (unsigned char)fgetc(mapfile) ;
	for ( i=0; i<256; i++ ) blue[i] = (unsigned char)fgetc(mapfile) ;
	fclose( mapfile ) ;

	/* copy the data, reversing rows to undo pixrect convention */
	for (i=0; i<my; i++)
		memcpy(&data[mx*(my-1-i)], &array[mx*i], mx) ;

	/* initialize PS end on 1st entry */
	if (!entered) {
		entered = 1 ;
		ps_open_PostScript() ;
		ps_initialize("Electron Density") ;
		ps_flush_PostScript() ;
	}

	/* open socket connection */
	for (i=0; i<10; i++) {
		if (sock = open_socket_handle()) break ;
		sleep(2) ;
	}
	if (!sock) {
		fprintf(stderr, "Connection timeout\n") ;
		exit() ;
	}

	/* write pixrect data */
	fwrite(s, 1, len, sock) ;
	fflush(sock) ;

	savepix(s, len) ;	/* dump numbered file to disk */
	free(s) ;
}



/* SAVEPIX
 *
 * Dump a numbered file to disk, containing the pixrect image
 */
savepix(s, len)
unsigned char	*s ;
int		len ;
{
static int	count = 0 ;
FILE		*o ;
char		filename[16] ;

	sprintf(filename, "%04d.img", count++) ;
	o = fopen(filename, "w") ;
	fwrite(s, 1, len, o) ;
	fclose(o) ;
}




/* COMPACT
 *
 * Reduce an array so that it will fit in a box (done in place).  A
 * no-op if the box is already bigger.  This is written for speed,
 * no averaging over nearby values is done (or should be).
 */
#define x_dim	(*x_dimp)	/* we want to update xy_dim in caller */
#define y_dim	(*y_dimp)

compact( data, x_dimp, y_dimp, x_size, y_size )
unsigned char	*data ;
int	*x_dimp, *y_dimp ;	/* original dimensions (could change) */
int	x_size, y_size ;	/* requested dimensions */
{
register int	x ;
register int	y ;
int		xindex, xslope, xinter, xfact ;
int		yindex, yslope, yinter, yfact ;

	/* calculate the linear coefficients */
	if ( x_size > 1 ) {
		xslope = x_dim - 1 ;
		xinter = x_dim - 1 ;
		xfact = x_size ;
	}
	else {
		xslope = 1 ;
		xinter = 0 ;
		xfact = 1 ;
	}

	if ( y_size > 1 ) {
		yslope = y_dim - 1 ;
		yinter = y_dim - 1 ;
		yfact = y_size ;
	}
	else {
		yslope = 1 ;
		yinter = 0 ;
		yfact = 1 ;
	}

	/* compress the data to fit the window */
	if ( x_dim > x_size & y_dim > y_size ) {
		for ( y = 0; y < y_size; y++ ) {
		yindex = ( yslope*y + yinter )/yfact ;
		for ( x = 0; x < x_size; x++ ) {
		xindex = ( xslope*x + xinter )/xfact ;
			data[x + y*x_size] = data[xindex + yindex*x_dim] ;
		}}
		x_dim = x_size ;
		y_dim = y_size ; }

	else {
	if ( x_dim > x_size ) {
		for ( y = 0; y < y_dim; y++ ) {
		for ( x = 0; x < x_size; x++ ) {
		xindex = ( xslope*x + xinter )/xfact ;
			data[x + y*x_size] = data[xindex + y*x_dim] ;
		}}
		x_dim = x_size ; }

	else {
	if ( y_dim > y_size ) {
		for ( y = 0; y < y_size; y++ ) {
		yindex = ( yslope*y + yinter )/yfact ;
		for ( x = 0; x < x_dim; x++ ) {
			data[x + y*x_dim] = data[x + yindex*x_dim] ;
		}}
		y_dim = y_size ; }

	}}
}

@//E*O*F show.c//
chmod u=rw,g=rw,o=rw show.c
 
echo x - show.cps
sed 's/^@//' > "show.cps" <<'@//E*O*F show.cps//'
%! show.cps
%
% Definitions for simple array display program


% Initialize pixrect viewer.  Data received via socket on port 2001
cdef ps_initialize(string flabel)


	/painter {	% Paint routine for client or icon canvas
		setcanvas clippath pathbbox scale pop pop
		Pixcanvas imagecanvas
		pause
	} def

	/win framebuffer /new DefaultWindow send def	% Create a window
	{						% Install display src
		/Pixcanvas currentcanvas newcanvas def
		/FrameLabel flabel def
		/PaintClient {
			ClientCanvas painter
		} def
		/PaintIcon {
			IconCanvas painter
		} def
	} win send
	/reshapefromuser win send			% Shape it.

	% define routine to get the data via socket
	/getimage {
		clear
		(%socketl2001) (r) file
		acceptconnection	% should be waiting here a lot
		dup readcanvas 
		/Pixcanvas exch store
		PaintClient
		closefile		% close socket
	} def

	% fork a process to receive data
	/listener_pid {
		{{getimage} win send} loop
	} fork def

	% Activate window (Damage causes PaintClient to be called)
	/map win send
@//E*O*F show.cps//
chmod u=rw,g=rw,o=rw show.cps
 
exit 0