ошибка make-socket в Clozure Common Lisp

На верхнем уровне CCL выполняется:

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

OR

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

выводит следующее:

> 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.

Я не могу понять ошибку (новый для CL). Что это означает? И что я делаю неправильно?


person Capstone    schedule 10.12.2016    source источник
comment
Вы указали слишком мало параметров. По умолчанию ваш вызов создает поток через TCP-соединение и требует указания удаленного адреса. См. значение различных параметров в документации.   -  person Renzo    schedule 10.12.2016
comment
Это кажется неправильным. В нем упоминается, что сокет прослушивателя должен указывать только локальный порт и локальный хост. Это кажется разумным, учитывая, что вы, как сервер, не знаете адрес удаленного клиента. Если бы я создавал клиента, мне нужно было бы указать удаленный адрес. Вот как я это понимаю.   -  person Capstone    schedule 10.12.2016
comment
Он также говорит, что по умолчанию используется активный сокет. Используйте :CONNECT :PASSIVE для создания прослушивателя.   -  person jkiiski    schedule 10.12.2016
comment
Чтобы создать сокет прослушивателя, параметр :connect должен быть :passive, но, поскольку вы его не указали, он :активен по умолчанию. Это указано в ссылке на документацию.   -  person Renzo    schedule 10.12.2016
comment
Понятно! Спасибо, парни. Но на будущее, как я мог понять это по ошибке? Единственный способ внимательно прочитать документацию? Мог ли я отладить свой путь к решению?   -  person Capstone    schedule 10.12.2016
comment
Ошибка довольно серьезная, поскольку на самом деле это не ошибка, преднамеренно сигнализируемая функцией MAKE-SOCKET, а скорее случай, который они не обработали должным образом. В сообщении об ошибке говорится, что он пытается вызвать общую функцию CCL::SOCKADDR с аргументом NIL. Это хороший намек на то, что вам не хватает ключевого слова/дополнительного аргумента, необходимого в вашем случае. Проверка документов — лучший способ продолжить. Вы также можете попробовать посмотреть исходный код MAKE-SOCKET (M-. должен работать в Emacs, если у вас есть доступный исходный код), чтобы увидеть, где он вызывает SOCKADDR и с каким аргументом.   -  person jkiiski    schedule 10.12.2016
comment
Вы можете использовать более продвинутый и переносимый API, такой как usocket: common-lisp.net/project/usocket   -  person Rainer Joswig    schedule 10.12.2016
comment
Для общих функций, таких как CCL:MAKE-SOCKET, может быть хорошей идеей иметь некоторую предварительную проверку в своей реализации, действительно ли имеют смысл предоставленные аргументы/аргументы по умолчанию.   -  person Rainer Joswig    schedule 10.12.2016


Ответы (1)


Проблема в вашем коде заключается в том, что ключевые параметры, предоставленные MAKE-SOCKET, требуют создания активного сокета TCP, а не пассивного (сокет прослушивателя), как вы указали в комментарии. Это связано с тем, что по умолчанию ключу :connect, указывающему, является ли сокет активным или пассивным, присваивается значение :active.

Сообщение об ошибке указывает, что система обнаружила вызов CCL:SOCKADDR с аргументом NIL, для которого не существует метода. Итак, причина в том, что требуется адрес сокета, но он не указан.

Используя Emacs со SLIME, вы могли бы найти:

  1. трассировка последних вызовов в стеке: MAKE-SOCKET, который вызывает MAKE-TCP-SOCKET, который вызывает %SOCKET-CONNECT (выдает ошибку);

  2. значения переменных внутри каждого вызова, поскольку, например, внутри вызова %SOCKET-CONNECT параметр SOCKET-ADDRESS равен NIL;

  3. код всех трех функций, изучив его, вы могли бы обнаружить, что MAKE-TCP-SOCKET требуется адрес сокета, и если он не указан в качестве значения ключевого параметра :remote-address, вызов для разрешения адреса выполняется с помощью удаленного- хост и удаленный порт.

person Renzo    schedule 10.12.2016