通过LISP USOCKET接收数据

5
我试图通过USOCKET发送数据。当数据到达服务器时,服务器应该回复。然而,如下所定义的stream-read只有在它被原始数据回显回来时才返回数据。例如,如果我发送hello并且服务器回复相同的数据hello,那么stream-read会返回,但如果服务器回复hi,直到服务器发送接收到的确切缓冲区,stream-read才会返回。

以下是代码:(大部分是从网络上找到的。)

;; 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))

关于服务器,我正在使用稍微修改过的boost阻塞式服务器示例。(c++) 完整代码可以在这里找到: 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";
  }
}
   ...
1个回答

11

没有看到你的服务器代码,所以回答有些推测。但是:

  1. 每次从客户端调用服务器时,您都使用相同的套接字。如果服务器不希望这样做,它就不会按您想要的方式运行。

  2. 您定义的stream-read调用了socket-listen。您是否意味着usocket:socket-listen?这是一个服务器端函数(需要不同的参数)。我可能没有看到您运行的确切代码。

  3. 建议注意事项:(a)my-stream实际上是一个套接字,而不是一个流;(b)我鼓励您使用Quicklisp管理外部库。

这是一个完整的工作示例。这是在LispWorks上;我使用了LW内部功能来使服务器和客户端分别明确。

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

如果您仍然遇到困难,请再次发布帖子,提供服务器源和您实际的stream-read


看起来服务器出了问题,用实用的C++回声服务器替换它,现在一切正常!http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/practical/另外,感谢提供socket-read函数,现在读取正常了。 - W01

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接