inter-process-communications
Andrew Hodgson
ash at aaii.oz.au
Mon May 7 10:43:05 AEST 1990
barshay at stars.reston.unisys.com ( Unisys):
> I have a Lucid Lisp process running on a Sun Workstation that needs to be
> able to communicate with a C process running on either the same Sun
> Workstation or another workstation on the same network. Does anybody have
> any suggestions? What I really am hoping for is the way to use sockets
> from Lucid Lisp.
It is simple enough using the a bit of 'C' code and the foreign function
interface.
Here is the 'C' code I use
cut it out put it in socket.c and run
cc -c socket.c
move socket.o to socket_sparc.o or socket_68000.o depending on machine type.
I haven't tried it on a 386i but I presume it would work.
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
/*
* Connect to a socket by service name or port number.
* If port is 0, service will be used.
* Returns a file descriptor for the socket.
*/
int
connect_to_socket(hostname, service, port)
char *hostname;
char *service;
u_int port;
{
struct sockaddr_in remote_addr; /* remote inet socket address */
struct servent *serv; /* returned by getservbyname() */
struct hostent *host; /* returned by gethostbyname() */
int sock;
if (strlen(service) <= 0)
service = NULL;
if ((host = gethostbyname(hostname)) == NULL) {
perror("gethostbyname");
return (-1);
}
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return (-1);
}
if (service != NULL) {
if ((serv = getservbyname(service, "tcp")) == NULL) {
if (port <= 0) {
fprintf(
stderr,
"Unknown serv %s/tcp. No default port given\n",
service
);
return(-1);
}
remote_addr.sin_port = htons((u_short) port);
}
else
remote_addr.sin_port = serv->s_port;
}
else
remote_addr.sin_port = htons((u_short) port);
remote_addr.sin_family = host->h_addrtype;
bcopy(host->h_addr, &remote_addr.sin_addr, host->h_length);
if (connect(sock, &remote_addr, sizeof(remote_addr)) < 0) {
perror("connect");
return (-1);
}
return(sock);
}
Here is the lisp code I use.
#+SUN
(in-package 'cv)
(export '(#+SUN connect-to-socket open-socket))
#+SUN
(def-foreign-function (connect-to-socket
(:return-type :signed-32bit))
(host-name :simple-string)
(service :simple-string)
(port-number :unsigned-32bit)
)
#+SUN
(load-foreign-files #+SPARC "socket_sparc.o"
#+MC68000 "socket_68000.o"
)
;;; OPEN-SOCKET
;;;
;;; Return a lisp stream connected to a socket on
;;; host with the given service name or number.
;;;
#+SUN
(defun open-socket (host
service
&key input output (auto-force T) (default-port 0)
&aux fd)
(when (numberp service)
(setq default-port service)
(setq service ""))
(if (minusp (setq fd (connect-to-socket host
service default-port)))
nil
(let* ((in (if input fd nil))
(out (if output fd nil)))
(make-lisp-stream :input-handle in
:output-handle out
:auto-force auto-force))))
So to open a connection to the 'C' process simply do
(setq socket-stream (open-socket
"XXX.reston.unisys.com" 3000
:input t
:output t
))
then use it as a normal lisp stream.
One warning. Since the the auto-force flag is by default true on the
stream every output operation will actually go out on the net. So when
doing a lot of output on the stream make sure you have a
(with-buffered-output ...
around the code or you will get lots of small packets going out on your
net. Eg tepri will output a packet with 1 char it it. (Expensive and
slow).
As an example we got 10X improvement in throughput simply by putting
with-buffered-output around one critical function
More information about the Comp.sys.sun
mailing list