Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client hangs for a minute at first. #20

Open
smegeath opened this issue Feb 8, 2021 · 1 comment
Open

Client hangs for a minute at first. #20

smegeath opened this issue Feb 8, 2021 · 1 comment

Comments

@smegeath
Copy link

smegeath commented Feb 8, 2021

My telnet client is connecting to a non-go-telnet server and uses the basic client code provided in the documentation example. Connecting to my server with a standard telnet client gets an instant reply, but for some reason, my go-telnet client hangs reading for exactly a minute, then is fully interactive. Is there some configuration I should be using or something extra I should be doing with the Conn to flush it?

@9072997
Copy link

9072997 commented Mar 30, 2022

according to the documentation for io.Reader

If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

This library does not follow that convention. It appears to block until it is able to fill the buffer.

This program demonstrates the issue
package main

import (
	"fmt"
	"io"
	"log"
	"net"
	"time"

	"github.com/reiver/go-telnet"
)

// start a TCP server that
// - prints "hello world"
// - waits 60 seconds
// - then hangs up
func DemoServer() {
	listener, err := net.Listen("tcp", ":1111")
	if err != nil {
		panic(err)
	}
	defer listener.Close()

	for {
		conn, err := listener.Accept()
		if err != nil {
			panic(err)
		}
		conn.Write([]byte("hello world\n"))
		time.Sleep(10 * time.Second)
		conn.Close()
	}
}

// ConnectWithBufferSize connects to the server at the given address and
// and prints the output of each call to Read() using the given buffer size.
func ConnectWithBufferSize(bufferSize int) {
	telnetClient, err := telnet.DialTo("localhost:1111")
	if err != nil {
		panic(err)
	}
	defer telnetClient.Close()

	buff := make([]byte, bufferSize)
	for {
		n, err := telnetClient.Read(buff)
		log.Printf("EOF:%t> %#v\n", err == io.EOF, string(buff[:n]))
		if err == io.EOF {
			break
		}
		if err != nil {
			panic(err)
		}
	}
}

func main() {
	go DemoServer()
	fmt.Println("=== Buffer Size 7 ===")
	ConnectWithBufferSize(7)
	fmt.Println("=== Buffer Size 1 ===")
	ConnectWithBufferSize(1)
}

Output:

=== Buffer Size 7 ===
2022/03/30 15:45:06 EOF:false> "hello w"
2022/03/30 15:45:16 EOF:true> "orld\n"
=== Buffer Size 1 ===
2022/03/30 15:45:16 EOF:false> "h"
2022/03/30 15:45:16 EOF:false> "e"
2022/03/30 15:45:16 EOF:false> "l"
2022/03/30 15:45:16 EOF:false> "l"
2022/03/30 15:45:16 EOF:false> "o"
2022/03/30 15:45:16 EOF:false> " "
2022/03/30 15:45:16 EOF:false> "w"
2022/03/30 15:45:16 EOF:false> "o"
2022/03/30 15:45:16 EOF:false> "r"
2022/03/30 15:45:16 EOF:false> "l"
2022/03/30 15:45:16 EOF:false> "d"
2022/03/30 15:45:16 EOF:false> "\n"
2022/03/30 15:45:26 EOF:true> ""

Note that with a buffer size of 7 you immediately get hello w then you have to wait the full 10 seconds to get orld\n. A quick test with a debugger shows that it is hanging here

As a work around, you can use a buffer size of 1

I am not able to re-produce the behavior OP describes where the connection ever becomes interactive.

I have confirmed that this is fixed by either of PR #22 or PR #9.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants