sockets - Recibir datos a través de LISP USOCKET
networking tcp (1)
Sin ver el código de su servidor es difícil responder sin un poco de especulación. Pero:
Utiliza el mismo socket para cada llamada del cliente al servidor. Si el servidor no espera eso, no se comportará como lo desea.
Su definición de llamadas de
stream-read
destream-read
socket-listen
. ¿usocket:socket-listen
decirusocket:socket-listen
? Esta es una función del lado del servidor (y toma diferentes argumentos). Probablemente no estoy viendo el código exacto que estaba ejecutando.Notas de asesoramiento: (a)
my-stream
es en realidad un socket, no un stream; (b) Lo animo a administrar bibliotecas externas usando Quicklisp .
Aquí hay un ejemplo completo de trabajo. Esto está en LispWorks; He utilizado LW internals para el servidor para dejar absolutamente claro cuál es el servidor y cuál es el cliente.
CL-USER 1 > (ql:quickload :usocket)
To load "usocket":
Load 1 ASDF system:
usocket
; Loading "usocket"
(:USOCKET)
CL-USER 2 > (comm:start-up-server
:service 6003
:function (lambda (handle)
(let* ((stream (make-instance ''comm:socket-stream
:socket handle
:direction :io
:element-type ''base-char))
(line (read-line stream)))
(format stream "Hello: ~a~%" line)
(force-output stream))))
#<MP:PROCESS Name "6003 server" Priority 85000000 State "Running">
CL-USER 3 > (defun socket-read (socket)
(read-line (usocket:socket-stream socket)))
SOCKET-READ
CL-USER 4 > (defun socket-print (string socket)
(write-line string (usocket:socket-stream socket))
(force-output (usocket:socket-stream socket)))
SOCKET-PRINT
CL-USER 5 > (defun test (thing)
(let ((socket (usocket:socket-connect "127.0.0.1" 6003)))
(socket-print thing socket)
(socket-read socket)))
TEST
CL-USER 6 > (test "Buttered toast")
"Hello: Buttered toast"
NIL
CL-USER 7 > (test "A nice cup of tea")
"Hello: A nice cup of tea"
NIL
Si aún tiene problemas, publique nuevamente con la fuente de su servidor y su stream-read
real.
Estoy tratando de enviar datos a través de USOCKET . Cuando los datos llegan al servidor, el servidor debe responder de nuevo. Sin embargo, stream-read
(como se define a continuación) solo devuelve los datos cuando se repiten con los datos originales que envió. Por ejemplo, si envío hello
y el servidor responde con la misma información, hello
, luego stream-read
, pero si el servidor responde con hi
, stream-read
no regresa hasta que el servidor envía el buffer exacto que recibió.
Aquí está el código: (Encontré la mayor parte en línea).
;; Load USocket
(load #P"/usr/share/common-lisp/source/cl-asdf/asdf.lisp")
(asdf:operate ''asdf:load-op :usocket)
(defun stream-read (stream)
(socket-listen (usocket:socket-stream stream)))
(defun stream-print (string stream)
(write-line string (usocket:socket-stream stream))
(force-output (usocket:socket-stream stream)))
;; Define a stream
(defparameter my-stream
(usocket:socket-connect "127.0.0.1" 6003))
;; Use the stream
(stream-print "random" my-stream)
(print (stream-read my-stream))
En cuanto al servidor, estoy usando una versión ligeramente modificada del ejemplo del servidor de bloqueo de refuerzo. (c ++) El código completo se puede encontrar aquí: http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/example/echo/blocking_tcp_echo_server.cpp
...
void session(socket_ptr sock)
{
try
{
for (;;)
{
char data[max_length];
boost::system::error_code error;
size_t length = sock->read_some(boost::asio::buffer(data), error);
if (error == boost::asio::error::eof)
break; // Connection closed cleanly by peer.
else if (error)
throw boost::system::system_error(error); // Some other error.
std::vector<char> v(data,data+length);
std::string theStr;
for(unsigned int i=0;i<v.size();i++)
{
if(v[i]<32 || v[i]>=0x7f);//Remove non-ascii char
else theStr.insert(theStr.end(),v[i]);
}
std::cout<<"|"<<theStr<<"|"<<std::endl;
boost::asio::write(*sock, boost::asio::buffer(data, length)); //works
boost::asio::write(*sock, boost::asio::buffer("some", 4)); //doesn''t work
}
}
catch (std::exception& e)
{
std::cerr << "Exception in thread: " << e.what() << "/n";
}
}
...