gpt4 book ai didi

tcp - Racket ,在不知道什么的情况下从端口读取输入

转载 作者:可可西里 更新时间:2023-11-01 02:45:20 24 4
gpt4 key购买 nike

我目前正在设计一个程序,其中一部分程序文件在 Raspberry Pi 上运行,另一部分在我的计算机上运行。

为了在它们之间进行通信,我通过 TCP/IP 发送消息。因此,要读取收到的消息,我使用 (read port)。然后我进行一些计算并将答案发回。

现在我注意到,当答案是一个数字时,我不会在另一边收到那个答案(我不知道是不是因为它是一个数字,我假设是)。虽然已经寄出。之后它会导致不正确的读取(我想是因为它仍在缓冲区中)。

这就是我发送消息的方式:

#lang racket

; Not important
(require (rename-in racket/tcp
(tcp-connect racket-tcp-connect)
(tcp-listen racket-tcp-listen)))
(define (tcp-connect adress port)
(let-values ([(port-in port-out) (racket-tcp-connect adress port)])
(cons port-in port-out)))
;;;;

(define ports (tcp-connect "localhost" 6667))
(define in (car ports))
(define out (cdr ports))

(define (send destination message expectAnswer? . arguments)
(write-byte destination out) ; Send the destination (is a number < 256) (so that I know on the other side which object I have to send the message to).
(newline out) ; I noticed that if I don't do this, sometimes the message won't be sent.
(write message out)
(newline out)
(write arguments out)
(newline out)
(write expectAnswer? out)
(newline out)

(flush-output out)

(display "destination : ") (display destination) (newline)
(display "Message : ") (display message) (newline)
(display "Arguments : ") (display arguments) (newline)
(display "Expects an answer? ") (display expectAnswer?) (newline)

(when expectAnswer?
(let ((answer (read in)))
(if (eof-object? answer)
'CC ; CC = Connection Closed
(begin (display "Answer : ")(display answer)(newline)(newline)
answer)))))

这就是我读取传入消息(在 Raspberry Pi 上)并发回答复的方式:

#lang racket

; Not important
(require (rename-in racket/tcp
(tcp-listen racket-tcp-listen)
(tcp-accept racket-tcp-accept)))

(define (tcp-accept port)
(let-values ([(port-in port-out) (racket-tcp-accept (racket-tcp-listen port))])
(cons port-in port-out)))
;;;;

(define ports (tcp-accept 6667))
(define in (car ports))
(define out (cdr ports))

(define (executeMessage destination message argumentList expectAnswer?)
(let ((destinationObject (decode destination)) ; This is the object that corresponds to the number we received
(answer '()))

(if (null? argumentList)
(set! answer (destinationObject message))
(set! answer (apply (destinationobject message) argumentList)))

(display "Destination : ")(display destination)(newline)
(display "Message : ")(display message)(newline)
(display "Arguments : ")(display argumentList)(newline)
(display "Expects answer? ")(display expectAnswer?) (newline)
(display "Answer : ")(display answer)(newline)(newline)

; We send the answer back if it is needed.
(when expectAnswer?
(write answer out)
(newline out) ; Because I noticed that if I don't to this, it won't be sent.
(flush-output out))))

; We call this function to skip the newlines that are send "(newline out)"
(define (skipNewline)
(read-byte in))

(define (listenForMessages)
(when (char-ready? in) ; Could be omitted.
; A message was sent
(let ((destination (read-byte in))
(message (begin (skipNewline) (read in)))
(argumentList (begin (skipNewline) (read in)))
(expectAnswer? (begin (skipNewline) (read in))))

(skipNewline)
(executeMessage destination message argumentList expectAnswer?)))

(listenForMessages))

(listenForMessages)

当运行该程序时,我看到了一堆正在发送和正确回答的消息。但后来我看到一条消息,希望得到答案,但没有得到答案。这是树莓派上显示的内容:

Destination : 2
Message : getStationHoogte
Arguments : '()
Expects answer? #t
Answer : 15

所以消息被执行了,结果是 15(我检查了它,这是它应该产生的结果,所以到目前为止我很高兴)。

请注意 Answer : ... 的显示恰好发生在发送答案之前。

但是在我的电脑上我看到了这个:

Destination : 2
Message : getStationHoogte
Arguments : ()
Expects answer? #t
Answer :

我觉得非常奇怪的是,答案什么都没有?这怎么可能?我使用“阅读”来阅读收到的答案,这是一个阻塞操作。它怎么会检测到一个答案(我假设在这个例子中是 15 个)(因为它停止阻塞)并且产生“什么都没有”。

这种行为的原因可能是什么?未发送消息(在本例中为数字)的原因可能是什么?

最佳答案

虽然我无法从您发布的内容中判断出确切的问题是什么,但我有一些建议:

  1. 您可以将 define-valuestcp-connect 的结果一起使用,如下所示:

    (define-values (in out) (tcp-connect "localhost" 6667))
  2. 如果每条消息都是一次writeread 可能会更简单、更可靠。为此,只需将所有值放入 list(或者可能是 #:prefab struct)。您可以使用 match 轻松地再次提取元素。例如像这样的东西(我还没有运行/测试过):

    (define (send destination message expect-answer? . arguments)
    (write (list destination message expect-answer? arguments)
    out)
    (newline out) ;do you actually need this?
    (flush-output out) ;you definitely do want this!
    (when expect-answer?
    (match (read in)
    [(? eof-object?) 'CC] ; CC = Connection Closed
    [answer (printf "Answer : ~a\n" answer)])))

    (define (listen-for-messages)
    (match (read in)
    [(? eof-object?) 'CC]
    [(list destination message expect-answer? arguments)
    (execute-message destination message arguments expect-answer?)
    (listen-for-messages)]))

关于换行的更新:

现在您正在写入读取s-表达式(list),不需要换行符来分隔消息-- 括号现在起到了这个作用。

重要的是缓冲——因此 flush-output。当 expect-answer? 也是 #t 时,请务必在运行的任何代码中使用它。

顺便说一下,你可以用file-stream-buffer-mode改变一些端口(包括TCP端口)的缓冲模式。 .可能它是 'block 默认情况下,这就是你之前需要换行的原因。如果您将模式更改为 'line,它可能会起作用。但既然您使用的是 s 表达式,我认为这应该无关紧要。您应该在每条消息(或回复)发送后使用 flush-output

关于tcp - Racket ,在不知道什么的情况下从端口读取输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29477015/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com