← Архив: Common Lisp

tcp/ip socket

Author: · 19.11.2009 20:47
· original author: atamaan
Понадобилось использовать сокеты, почитал sbclовскую документацию слабо что понял, стал пробовать, так ничего и не смог запустить, ни одно выражение не заработало, все вываливается в дебагер...
Мои познания с лиспом маленькие, работал только с логикой, то есть ни каких сокетов и gui не затрагивал, а только консоль да с файлами...
Был бы благодарен, если бы написали мне пару строк кода, как принимать и отсылать данные...
Если вдруг захотите узнать что хочу сделать, могу описать...
Заранее всем спасибо, даже если и не поможете...
· original author: treep
Может у вас сеть плохо работает? У меня так было - вроде все сетевые программы работают а sbcl не мог найти tcp-протокол.
Следующий код должен работать независимо от ОС:
(require :sb-bsd-sockets)
(setf socket (sb-bsd-sockets:make-inet-socket :stream :tcp))
              ; вернёт объект сокет, потом по этому дескриптору нужно осуществить соединение

; тоже самое, inet-socket это класс
(setf socket (make-instance 'sb-bsd-sockets:inet-socket :type :stream :protocol :tcp)))
; теперь нужно выполнить соединение
(sb-bsd-sockets:socket-connect socket
    (sb-bsd-sockets:host-ent-address (sb-bsd-sockets:get-host-by-name "localhost"))
    80
)

; должен работать сервер на 80 порту localhost
; можно соединиться с любой точкой, например wwww.google.com вместо localhost

(setf stream (sb-bsd-sockets:socket-make-stream socket
                  :input t
                  :output t
                  :buffering :full
                  :element-type :default
                  :external-format :iso-8859-1
)

; теперь с потоком stream можно работать, читать и писать с помощью обычных format и read-line
; или более "правильно", с помощью tcp-print-raw + print и tcp-read-raw + read

А как это использовать, зависит от того, что вы хотите написать - клиент или сервер.
· original author: treep
ихъ как у меня скопировалось :)
· original author: archimag
прикольно, как дойдут руки - сделаю sanitize процеду :)
· original author: treep
может сделать кнопочку "копировать", только это на js. Или, если на js сделать кнопку "расцветить" прямо тут в редакторе?
· original author: archimag
Да всё можно сделать, только сейчас некому :)
· original author: treep
Что значит некому? Если я к примеру попробую сделать что-нибудь, это будет принято к рассмотрению?
· original author: archimag
> Что значит некому? Если я к примеру попробую сделать что-нибудь, это будет принято к рассмотрению?
Конечно. Я кажется нигде не говорил, что проектом буду заниматься я и только я :) Наоборот, и исходники для того сразу были открыты, что бы может нашлись желающие помочь, правда таких  пока нет. Ну да у меня задуман рефакторинг (на базе последних разработок), после которого исходники станут лучше и проще, может тогда желающие появяться? ;)
· original author: Love5an
Сокеты лучше пользовать через usocket.
Кроссплатформенность потому что.
Вот пример:
(defun simple-server (&optional (port 0)) ;;0 - random port
 (let ((server (usocket:socket-listen "127.0.0.1" port
                                       :element-type 'base-char
)
)

        (crlf (map 'string #'code-char '(13 10)))
        (ws   '(#\Space #\Tab #\Newline #\Return))
)

    (format t "~&Server listening on port ~a~%"
            (usocket:get-local-port server)
)

    (unwind-protect
      (loop for connection = (usocket:socket-accept server)
            for connection-stream = (usocket:socket-stream connection)
            do (loop for line = (progn
                                  (format connection-stream
                                          "Write something('quit' - close connection):~a"
                                          crlf
)

                                  (force-output connection-stream)
                                  (read-line connection-stream nil nil)
)

                     initially                     
                     (format t "~%Accepted connection~%")
                     while line
                     if (string-equal "quit" (string-trim ws line))
                     do (format connection-stream "kthxbye~a" crlf)
                        (force-output connection-stream)
                        (loop-finish)
                     else
                     do (format t "User wrote: ~a~&" line)
                     finally
                     (usocket:socket-close connection)
                     (write-line "Connection closed")
)
)

      (usocket:socket-close server)
)
)
)
· original author: marsijanin
>Сокеты лучше пользовать через usocket.
Или iolib
· original author: archimag
> Или iolibДа, iolib по нынешним временам более перспективное решение.
to marsijanin:
 Кстати, насчет iolib, пересаживайся на git ;), ну его этот mercurial...
· original author: atamaan
Спасибо всем! )
· original author: Love5an
а iolib только unix-like системы поддерживает?
· original author: treep
Да, там все к glibc идёт через cffi, а частей с #+sbcl, #+ccl и т.д. почти нет, поэтому нет и windows-работающих функций, которые есть у реализаций.