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

Write方法返回时不能保证数据写到了对方缓冲区 #233

Open
ryanrain2016 opened this issue Oct 19, 2022 · 7 comments
Open

Write方法返回时不能保证数据写到了对方缓冲区 #233

ryanrain2016 opened this issue Oct 19, 2022 · 7 comments

Comments

@ryanrain2016
Copy link

下面的测试代码

func demo() {
	// listener, _ := net.Listen("tcp", "127.0.0.1:50001")
	listener, _ := kcp.Listen("127.0.0.1:50001")
	clientChan := make(chan net.Conn, 1)
	go func() {
		// conn, _ := net.Dial("tcp", "127.0.0.1:50001")
		conn, _ := kcp.Dial("127.0.0.1:50001")
		clientChan <- conn
	}()
	conn, _ := listener.Accept()
	clientConn := <-clientChan
	clientConn.Write([]byte("123abc"))
	clientConn.Close()

	buf := make([]byte, 10)
	n, err := conn.Read(buf)
	fmt.Printf("err: %v\n", err)
	fmt.Printf("buf: %v\n", string(buf[:n]))
	fmt.Println("again")
	n, err = conn.Read(buf)
	fmt.Printf("err: %v\n", err)
	fmt.Printf("buf: %v\n", string(buf[:n]))
}

使用tcp的时候conn可以读到数据;使用kcp时,不能。这里是否有相关配置控制这个行为?

@ryanrain2016
Copy link
Author

试了下隔壁的tokio_kcp可以实现,可惜库本身不支持加密,要加密还要自己加

@2435043xia
Copy link

这里是你测试方法的问题
出现这个情况的原因是kcp-go本身是没有握手操作的,你dial以后并没有建立连接,你需要发送一条消息。当服务器接收到消息,发现连接不在SessionMap里才会创建Session,通知AcceptChan。所以你的例子里Accept过不去

@ryanrain2016
Copy link
Author

ryanrain2016 commented Jul 26, 2023

这里是你测试方法的问题 出现这个情况的原因是kcp-go本身是没有握手操作的,你dial以后并没有建立连接,你需要发送一条消息。当服务器接收到消息,发现连接不在SessionMap里才会创建Session,通知AcceptChan。所以你的例子里Accept过不去

感谢回复,上面的代码确认是卡在accept,我修改了下测试代码:

func main() {
	// listener, _ := net.Listen("tcp", "127.0.0.1:50001")
	listener, _ := kcp.Listen("127.0.0.1:50001")
	clientChan := make(chan net.Conn, 1)
	go func() {
		// conn, _ := net.Dial("tcp", "127.0.0.1:50001")
		conn, _ := kcp.Dial("127.0.0.1:50001")
		conn.Write([]byte("123"))
		clientChan <- conn
	}()
	conn, _ := listener.Accept()
	fmt.Println("accpet?")
	clientConn := <-clientChan
	clientConn.Write([]byte("123abc"))
	clientConn.Close()

	buf := make([]byte, 10)
	n, err := conn.Read(buf)
	fmt.Printf("err: %v\n", err)
	fmt.Printf("buf: %v\n", string(buf[:n]))
	fmt.Println("again")
	n, err = conn.Read(buf)
	fmt.Printf("err: %v\n", err)
	fmt.Printf("buf: %v\n", string(buf[:n]))
}

然而还是只收到123,后面的123abc收不到

@2435043xia
Copy link

尝试调试了一下,明白了是什么问题,简单来说就是窗口满了,第二个write没有等到第一个write的ack就被close了,自然没发出去。你可以在第二个write之前加个一秒的等待。

@ryanrain2016
Copy link
Author

尝试调试了一下,明白了是什么问题,简单来说就是窗口满了,第二个write没有等到第一个write的ack就被close了,自然没发出去。你可以在第二个write之前加个一秒的等待。

我指导这个等待可以解决,只是这样不确定等待时间,网络不好的时候等待1秒可能都不够。

@2435043xia
Copy link

我以为我说的挺清楚了,你设置nocwnd=1也可以解决这个问题。说白了就是窗口满了在队列里没有发出去

@ryanrain2016
Copy link
Author

我以为我说的挺清楚了,你设置nocwnd=1也可以解决这个问题。说白了就是窗口满了在队列里没有发出去

多谢指点,我不太了解其中的配置细节,我加了下面的代码,demo运行符合期望了

c := conn.(*kcp.UDPSession)
c.SetWindowSize(1, 1)

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