2013-06-23 15 views
5

Próbuję wysłać dane przez USOCKET. Gdy dane docierają do serwera, serwer powinien odpowiedzieć. Jednak stream-read (zgodnie z definicją poniżej) zwraca dane tylko wtedy, gdy są one echo z powrotem z oryginalnymi danymi, które wysłał. Na przykład, jeśli wyślę hello, a serwer odpowie tymi samymi danymi, hello, wtedy stream-read zwróci, ale jeśli serwer odpowie hi, stream-read nie powróci, dopóki serwer nie wyśle ​​dokładnie tego bufora, który otrzymał.Odbieranie danych za pośrednictwem LISP USOCKET

Oto kod: (Znalazłem większość z nich w Internecie.)

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

chodzi o serwer, używam nieco zmodyfikowaną wersję impuls blokujący przykład serwera. (C++) pełny kod można znaleźć tutaj: 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"; 
    } 
} 
    ... 

Odpowiedz

11

Nie widząc kod serwera trudno odpowiedzieć bez odrobiny spekulacji. Ale:

  1. Używasz tego samego gniazda dla każdego połączenia od klienta do serwera. Jeśli serwer się tego nie spodziewa, nie będzie się zachowywać tak, jak tego chcesz.

  2. Twoja definicja stream-read nazywa się socket-listen. Czy miałeś na myśli usocket:socket-listen? Jest to funkcja po stronie serwera (i przyjmuje różne argumenty). Prawdopodobnie nie patrzę na dokładny kod, który właśnie uruchomiłeś.

  3. Wskazówki: (a) my-stream jest w rzeczywistości gniazdem, a nie strumieniem; (b) Zachęcam do zarządzania bibliotekami zewnętrznymi za pomocą Quicklisp.

Oto pełny przykład pracy. To jest na LispWorks; Użyłem wewnętrznych elementów LW dla serwera, aby całkowicie wyjaśnić, który serwer jest i który jest klientem.

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 

Jeśli nadal masz trudności, zakładać ponownie źródło serwera i rzeczywistą stream-read.

+0

Dzięki, dodałem kod serwera do głównego postu. –

+0

Wygląda na to, że serwer był problemem, zastąpił go praktycznym serwerem echo C++ i wszystko działa! http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/practical/ Ponadto, dzięki za funkcję odczytu gniazda, teraz czyta się poprawnie. –

Powiązane problemy