2

On CCL toplevel, running:

(make-socket :LOCAL-PORT 6666 :LOCAL-HOST "127.0.0.1")

OR

(make-socket :LOCAL-PORT 6666 :LOCAL-HOST (lookup-hostname "localhost"))

outputs the following:

> Error: There is no applicable method for the generic function:
>          #<STANDARD-GENERIC-FUNCTION CCL::SOCKADDR #x30200043F91F>
>        when called with arguments:
>          (NIL)
> While executing: #<CCL::STANDARD-KERNEL-METHOD NO-APPLICABLE-METHOD (T)>, in process listener(1).
> Type :GO to continue, :POP to abort, :R for a list of available restarts.
> If continued: Try calling it again
> Type :? for other options.

I can't make sense of the error (new to CL). What does it mean? And what am I doing wrong?

Capstone
  • 2,254
  • 2
  • 20
  • 39
  • 2
    You have specified too few parameters. By default your call creates a stream over a TCP connection, and require the specification of a remote address. See the meaning of the different parameters in the [documenation](http://ccl.clozure.com/docs/ccl.html#overview_in_programming-with-sockets). – Renzo Dec 10 '16 at 07:05
  • That seems incorrect. It mentions that a listener socket need only specify local port and local host. This seems to be sensible considering as a server you don't know the remote client address. If I were creating a client then I would need to specify the remote address. That's how I understand it. – Capstone Dec 10 '16 at 07:10
  • 2
    It also says that the default is an active socket. Use `:CONNECT :PASSIVE` to create a listener. – jkiiski Dec 10 '16 at 07:11
  • 2
    To create a listener socket the :connect parameter must be :passive, but since you have not specified it, it :is active by default. It is specified in the documentation link. – Renzo Dec 10 '16 at 07:15
  • 1
    Got it! Thanks guys. But for future ref, how could I have figured this from the error? Is the only way to have carefully read through the documentation? Could I have debugged my way to the solution? – Capstone Dec 10 '16 at 07:19
  • 2
    The error is pretty bad, since it's not actually an error intentionally signalled by the `MAKE-SOCKET` function, but rather a case they didn't handle properly. The error message says that it's trying to call a generic function `CCL::SOCKADDR` with the argument `NIL`. That's a good hint that you're missing a keyword/optional argument that's required in your case. Checking the docs is the best way to proceed. You could also try looking at the source code for `MAKE-SOCKET` (`M-.` should work in Emacs if you have the source available) to see where it calls `SOCKADDR`, and with what argument. – jkiiski Dec 10 '16 at 07:30
  • 3
    You could use a something more advanced and more portable API like usocket: https://common-lisp.net/project/usocket/ – Rainer Joswig Dec 10 '16 at 09:20
  • For general functions like CCL:MAKE-SOCKET, it might be a good idea to have some upfront checking in its implementation, whether the provided/defaulted arguments actually make sense. – Rainer Joswig Dec 10 '16 at 09:22

1 Answers1

5

The problem in your code is that the key parameters provided to MAKE-SOCKET require the creation of an active TCP socket, and not a passive one (listener socket), as you have specified in a comment. This is because, by default, the key :connect, that specifies if the socket is active or passive, is assigned the value :active.

The error message specifies that the system encountered a call to CCL:SOCKADDR with argument NIL, for which no method exists. So the reason is that a socket address is required but none is provided.

By using Emacs with SLIME you could have found:

  1. the trace of the last calls on the stack: MAKE-SOCKET, that calls MAKE-TCP-SOCKET, that calls %SOCKET-CONNECT (that produces the error);

  2. the values of the variables inside each call, seeing for instance that inside the call to %SOCKET-CONNECT the parameter SOCKET-ADDRESS is NIL;

  3. the code of all the three functions, by inspecting it you could have found that MAKE-TCP-SOCKET require a socket-address, and if this is not provided as value to the key parameter :remote-address, a call to resolve address is made with remote-host and remote-port.

Renzo
  • 26,848
  • 5
  • 49
  • 61