英文:
How I can receive data for ever from TCP server
问题
我尝试创建一个TCP客户端来接收来自TCP服务器的数据,但是在服务器发送数据后,我只能接收到一条数据,即使服务器发送了多条数据,我希望能够一直接收数据,但我不知道问题出在哪里。
客户端:
func main() {
tcpAddr := "localhost:3333"
conn, err := net.DialTimeout("tcp", tcpAddr, time.Second*7)
if err != nil {
log.Println(err)
}
defer conn.Close()
connBuf := bufio.NewReader(conn)
for {
bytes, err := connBuf.ReadBytes('\n')
if err != nil {
log.Println("接收错误:", err)
}
if len(bytes) > 0 {
fmt.Println(string(bytes))
}
time.Sleep(time.Second * 2)
}
}
我正在按照这个示例创建TCP测试服务器。
服务器:
// 处理传入的请求。
func handleRequest(conn net.Conn) {
// 创建一个缓冲区来保存传入的数据。
buf := make([]byte, 1024)
// 将传入的连接读取到缓冲区中。
_, err := conn.Read(buf)
if err != nil {
fmt.Println("读取错误:", err.Error())
}
fmt.Println(buf)
// 向联系我们的人发送响应。
var msg string
fmt.Scanln(&msg)
conn.Write([]byte(msg))
// 使用完连接后关闭它。
conn.Close()
}
英文:
I try to create TCP client to receive data from TCP server,
but after server sending data only I receive data one even if server send many data, and I want to receive data forever, and I don't know what is my problem,and
Client:
func main() {
tcpAddr := "localhost:3333"
conn, err := net.DialTimeout("tcp", tcpAddr, time.Second*7)
if err != nil {
log.Println(err)
}
defer conn.Close()
// conn.Write([]byte("Hello World"))
connBuf := bufio.NewReader(conn)
for {
bytes, err := connBuf.ReadBytes('\n')
if err != nil {
log.Println("Rrecv Error:", err)
}
if len(bytes) > 0 {
fmt.Println(string(bytes))
}
time.Sleep(time.Second * 2)
}
}
I'm following this example to create TCP test server
Server:
// Handles incoming requests.
func handleRequest(conn net.Conn) {
// Make a buffer to hold incoming data.
buf := make([]byte, 1024)
// Read the incoming connection into the buffer.
_, err := conn.Read(buf)
if err != nil {
fmt.Println("Error reading:", err.Error())
}
fmt.Println(buf)
// Send a response back to person contacting us.
var msg string
fmt.Scanln(&msg)
conn.Write([]byte(msg))
// Close the connection when you're done with it.
conn.Close()
}
答案1
得分: 2
Read需要在连接的另一端进行Write操作
> 想要无限接收数据
那么你就需要无限发送数据。在接收端有一个for
循环,但发送端没有循环。服务器只发送一次消息并关闭连接。
服务器期望从客户端接收消息,但客户端没有发送
>
> // conn.Write([]byte("Hello World"))
>
这应该向服务器提供msg
值。
>
> _, err := conn.Read(buf)
>
所以这两行不匹配。
客户端期望有一个换行符,但服务器没有发送
fmt.Scanln
期望将每个以空格分隔的值放入相应的参数中。它不会捕获空格。所以:
- 你在服务器的标准输入中输入的内容只会存储到第一个空格之前的部分。
- 换行符不会存储在
msg
中。
但是你的客户端代码是这样的:
>
> bytes, err := connBuf.ReadBytes('\n')
>
\n
从未出现。客户端无法完成对第一个msg
的读取。
bufio.NewScanner
是从标准输入中收集数据的更好方法,因为你可能还想捕获空格。不要忘记在发送的每一行文本后附加换行符,因为客户端期望它!
工作代码
我将这些更改整合到了playground上的一个可运行示例中。为了在该环境中使其工作,我还进行了一些其他更改。
- 在同一个进程中运行服务器和客户端
- 硬编码了3个客户端,以便程序在有限的时间内结束
- 硬编码了10次客户端接收,以便程序可以结束
- 硬编码了3个服务器连接处理,以便程序可以结束
- 删除了
fmt.Scanln
,并让服务器只返回发送的原始消息(因为playground没有提供标准输入机制)
这应该足够让你开始了。
英文:
Read requires a Write on the other side of the connection
> want to receive data forever
Then you have to send data forever. There's a for
loop on the receiving end, but no looping on the sending end. The server writes its message once and closes the connection.
Server expects to get msg from client but client doesn't send it
>
> // conn.Write([]byte("Hello World"))
>
That's supposed to provide the msg
value to the server
>
> _, err := conn.Read(buf)
>
So those two lines don't match.
Client expects a newline but server isn't sending one
fmt.Scanln
expects to put each whitespace separated value into the corresponding argument. It does not capture the whitespace. So:
- Only up to the first whitespace of what you type into server's stdin will be stored in
msg
- Newline will not be stored in
msg
.
But your client is doing
> ```
> bytes, err := connBuf.ReadBytes('\n')
The \n
never comes. The client never gets done reading that first msg
.
bufio.NewScanner
would be a better way to collect data from stdin, since you're likely to want to capture whitespace as well. Don't forget to append the newline to each line of text you send, because the client expects it!
Working code
I put these changes together into a working example on the playground. To get it working in that context, I had to make a few other changes too.
- Running server and client in the same process
- Hard coded 3 clients so the program ended in limited amount of time
- Hard coded 10 receives in the client so program can end
- Hard coded 3 server connections handled so program can end
- Removed
fmt.Scanln
and have server just return the original message sent (because playground provides no stdin mechanism)
Should be enough to get you started.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论