From: Yarden Katz
Subject: [Maybe OT?] using the socket interface
Date: 
Message-ID: <86znocozh8.fsf@underlevel.net>
Hi,

  I am trying to open a socket to communicate with a local server
  running on my machine on port 8088, to send back and forth simple
  Lisp text.  I am using Allegro CL, although I am almost certain that
  whatever I'm doing wrong here is a universal error on all Lisps :)

  I tried the following snippet, based on what I read in
  <http://www.cl.cam.ac.uk/ailanguages/allegro5/socket.htm>:

  [1] CL-USER(2): (setf s (socket:make-socket :remote-host "localhost"
  :connect :active :remote-port 8088))
  #<MULTIVALENT stream socket connected from localhost/56894 to
    localhost/8088 @ #x7150cf42>

  When I try to write to the server, this happens:
    
  [1] CL-USER(3): (format s "(concept? simple-test)\r\n")
  NIL

  (I also tried (format s "(concept? simple-test)~C~C" #\Linefeed #\Newline))

  [1] CL-USER(4): (read-char-no-hang s)
  NIL

  ..(read s) and (read-char s) both hang.

  When I tried what seems to be the equivalent of the above in Python[1],
  it worked, so I know the server is not at fault.  I'm sure I'm
  misunderstanding something simple about the socket interface.  Could
  someone please explain what I'm doing wrong?    

Thanks a lot,
-- 
Yarden Katz <····@underlevel.net>  |  Mind the gap

[1] I used the following bit of Python:

>>> from socket import *
>>> s = socket(AF_INET, SOCK_STREAM)
>>> s.connect(('127.0.0.1', 8088))
>>> s.send('(concept? simple-test)\r\n')
24
>>> s.recv(1024)
':answer 1 "NIL" ""\n'

-- 
Yarden Katz <····@underlevel.net>  |  Mind the gap

From: Matthew Danish
Subject: Re: [Maybe OT?] using the socket interface
Date: 
Message-ID: <20030303171142.D20083@lain.cheme.cmu.edu>
[Meant to send the answer here, sorry Yarden]:

Check out FORCE-OUTPUT and related functions.  Allegro is probably
buffering the stream.

-- 
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
From: Yarden Katz
Subject: Re: [Maybe OT?] using the socket interface
Date: 
Message-ID: <86vfz0ovtj.fsf@underlevel.net>
Matthew Danish <·······@andrew.cmu.edu> writes:

> [Meant to send the answer here, sorry Yarden]:
>
> Check out FORCE-OUTPUT and related functions.  Allegro is probably
> buffering the stream.

I looked at
<http://www.lispworks.com/reference/HyperSpec/Body/f_finish.htm> and
from what I can tell, force-output is the most relevant function as
you suggest.  However, (force-output s) did not fix it.  It evaluates
to nil and reading/writing to the stream results in the same
behavior.  Do you have any other ideas?  I'm quite lost on this.

Thanks a lot!
-- 
Yarden Katz <····@underlevel.net>  |  Mind the gap
From: Chris Beggy
Subject: Re: [Maybe OT?] using the socket interface
Date: 
Message-ID: <87wujg0xt1.fsf@lackawana.kippona.com>
Yarden Katz <····@underlevel.net> writes:

> Matthew Danish <·······@andrew.cmu.edu> writes:
>
>> [Meant to send the answer here, sorry Yarden]:
>>
>> Check out FORCE-OUTPUT and related functions.  Allegro is probably
>> buffering the stream.
>
> I looked at
> <http://www.lispworks.com/reference/HyperSpec/Body/f_finish.htm> and
> from what I can tell, force-output is the most relevant function as
> you suggest.  However, (force-output s) did not fix it.  It evaluates
> to nil and reading/writing to the stream results in the same
> behavior.  Do you have any other ideas?  I'm quite lost on this.

Consider trying something like:

(with-output-to-string (s)
  (format s  "i present ~a" "a simple test\n"))

Chris
From: Drew McDermott
Subject: Re: [Maybe OT?] using the socket interface
Date: 
Message-ID: <b411hm$3bm$1@news.ycc.yale.edu>
Yarden Katz wrote:
> 
> I looked at
> <http://www.lispworks.com/reference/HyperSpec/Body/f_finish.htm> and
> from what I can tell, force-output is the most relevant function as
> you suggest.  However, (force-output s) did not fix it.  It evaluates
> to nil and reading/writing to the stream results in the same
> behavior.  Do you have any other ideas?  I'm quite lost on this.
> 

What does the code look like on the server side?

A no-op client I use in teaching Lisp looks more or less exactly like 
your code:


;-*- Mode: Common-lisp; Package: cl-user; -*-
(in-package :cl-user)

(defvar cs472-port 5720)

(defun client-sock ()
    (let ((socket-stream nil) from-server from-user
          server-host)
       (format t "Name or IP address of server machine: ")
       (setq server-host
             (string-trim " \t" (read-line *standard-input*)))
       (unwind-protect
          (progn
             (setq socket-stream (acl-socket:make-socket
                                    :connect ':active
                                    :remote-host server-host
                                    :remote-port cs472-port))
             (format t "Found server~%")
             (loop
                (format t "Input a string: ")
                (setq from-user (read-line *standard-input*))
                (format t "     [Sending to server]~%")
                (format socket-stream "~a~%" from-user)
                (force-output socket-stream)
                (format t "     [Reading from server]~%")
                (setq from-server (read-line socket-stream))
                (format t "From server: ~a~%" from-server)))
          (progn
             (format t "Abort!~%")
             (cond (socket-stream
                       (close socket-stream)))))))

You type a string on the client side, which sends it to the server, 
which prompts for a string and sends it back.  To illustrate that you 
can talk to anyone, the server is in Java, which doesn't require forcing 
anything (but I seem to recall does require a \n before it actually 
sends anything).  If you wrote the server in Lisp, it probably would 
have to force-output when sending back to the client.

import java.net.*;
import java.io.*;
import java.util.*;

public class Serv_sock
{
   static int cs572_port = 5720;

    public static void main(String[] argv) throws IOException
   {
      String Dataset = null;
      try
      {
        InetAddress local_addr = InetAddress.getLocalHost();
        String host_name = local_addr.getHostName();
        String host_addr = local_addr.getHostAddress();
        byte[] raw_addr = local_addr.getAddress();
        System.out.println("Server host name = " + host_name);
        System.out.println("Server IP address = " + host_addr);
        int int_addr = 0;
        for (int i=0;i<=3;i++)
          {
            System.out.println("raw[" + i + "] = " + raw_addr[i]);
            int_addr = (int_addr << 8) | raw_addr[i];
          }

        System.out.println("Server integer address = " + int_addr);
      }
      catch (Exception e)
      {
        System.out.println("Can't get server host data\n because of "
                           + e);
      }

      ServerSocket serverSocket = null;
      try {
          serverSocket = new ServerSocket(cs572_port);
      } catch (IOException e) {
          System.err.println("Could not listen on port: " + cs572_port);
          System.exit(1);
      }

      while(true)
      {
         System.out.println("Waiting.....");

         Socket clientSocket = null;
         PrintWriter out_to_client = null;
         BufferedReader in_from_client = null;
         BufferedReader
            in_from_user
             = new BufferedReader(new InputStreamReader(System.in));
         try
         {
             clientSocket = serverSocket.accept();
         }
         catch (IOException e)
         {
             System.err.println("Accept failed.");
             System.exit(1);
         }
         String from_cli = null, from_user = null;
         try
         {
            out_to_client
               = new PrintWriter(clientSocket.getOutputStream(), true);
            in_from_client
             = new BufferedReader
                     (new InputStreamReader(clientSocket.getInputStream()));
         }
         catch (IOException e)
         {
             System.err.println("Accept failed.");
             System.exit(1);
         }
         try
           {
              System.out.println("    [Reading from client]");
              while ((from_cli = in_from_client.readLine()) != null)
                {
                  System.out.println("From client: " + from_cli);
                  System.out.println("Input a string: ");
                  try
                    {
                      from_user = in_from_user.readLine();
                      System.out.println("     [Sending to client]");
                      out_to_client.println(from_user);
                    }
                  catch(IOException e)
                  {
                    System.err.println
                         ("Can't read from user; not sending to client");
                  }
                }
           }
         catch(IOException e)
         {
           System.err.println("Can't communicate with client");
         }
         out_to_client.close();
         in_from_client.close();
         clientSocket.close();
      }
  }
}

Before the to-and-fro interchange gets going, the server tells you its 
IP address, which you can tell to the client if you don't want to type a 
symbolic hostname.

         -- Drew McDermott
From: Henrik Motakef
Subject: Re: [Maybe OT?] using the socket interface
Date: 
Message-ID: <877kbgm6y8.fsf@interim.henrik-motakef.de>
Yarden Katz <····@underlevel.net> writes:

>   I am trying to open a socket to communicate with a local server
>   running on my machine on port 8088, to send back and forth simple
>   Lisp text.  I am using Allegro CL, although I am almost certain that
>   whatever I'm doing wrong here is a universal error on all Lisps :)

Well, socket interfacess are implementation-specific.

>   [1] CL-USER(3): (format s "(concept? simple-test)\r\n")
>   NIL
> 
>   (I also tried (format s "(concept? simple-test)~C~C" #\Linefeed #\Newline))
> 
>   [1] CL-USER(4): (read-char-no-hang s)
>   NIL
> 
>   ..(read s) and (read-char s) both hang.

Wild guess: Maybe (force-output s) helps?

hth
Henrik