在Go中从套接字读取时遇到问题

huangapple go评论102阅读模式
英文:

Trouble reading from a socket in go

问题

我正在尝试学习Go语言,并编写一个简单的回显服务器。但是我在使其工作时遇到了困难。

func listen(server string) {
	var buf []byte

	listener, ok := net.Listen("tcp", server)
	if ok != nil {
		fmt.Fprintf(os.Stderr, "无法在套接字上监听:%s\n", ok.String())
		return
	}
	conn, ok := listener.Accept()
	if ok != nil {
		fmt.Fprintf(os.Stderr, "无法接受套接字连接:%s\n", ok.String())
		return
	}

	writelen, ok := conn.Write(strings.Bytes("准备接收\n"))
	if ok != nil {
		fmt.Fprintf(os.Stderr, "无法写入套接字:%s\n", ok.String())
	} else {
		fmt.Printf("已向套接字写入%d字节\n", writelen)
	}

	for ;; {
		readlen, ok := conn.Read(buf)
		if ok != nil {
			fmt.Fprintf(os.Stderr, "从套接字读取时出错:%s\n", ok.String())
			return
		}
		if readlen == 0 {
			fmt.Printf("连接被远程主机关闭\n")
			return
		}

		fmt.Printf("来自%s的客户端说:%s\n", conn.RemoteAddr().String(), buf)
	}
}

我从这个函数中得到以下输出:

[nathan@ebisu ~/src/go/echo_server] ./6.out 1234
使用端口1234
已向套接字写入17字节
从套接字读取时出错:EOF

这是我在客户端上看到的:

[nathan@ebisu ~] telnet 127.0.0.1 1234
正在尝试连接到127.0.0.1...
已连接到127.0.0.1。
转义字符为'^]'。
准备接收
连接被远程主机关闭。

任何帮助将不胜感激(或者指向资源的指针;关于套接字API的Go文档还有待改进)。

谢谢,

Nathan

英文:

I'm trying to learn the go language, and I'm writing a simple echo server. I'm having difficulty making it work, though.

func listen(server string) {
	var buf []byte

	listener, ok := net.Listen("tcp", server)
	if ok != nil {
		fmt.Fprintf(os.Stderr, "Could not listen on socket: %s\n", ok.String())
		return
	}
	conn, ok := listener.Accept()
	if ok != nil {
		fmt.Fprintf(os.Stderr, "Could not accept connection on socket: %s\n", ok.String())
		return
	}

	writelen, ok := conn.Write(strings.Bytes("Ready to receive\n"))
	if ok != nil {
		fmt.Fprintf(os.Stderr, "Could not write to socket: %s\n", ok.String())
	} else {
		fmt.Printf("Wrote %d bytes to socket\n", writelen)
	}

	for ;; {
		readlen, ok := conn.Read(buf)
		if ok != nil {
			fmt.Fprintf(os.Stderr, "Error when reading from socket: %s\n", ok.String())
			return
		}
		if readlen == 0 {
			fmt.Printf("Connection closed by remote host\n")
			return
		}

		fmt.Printf("Client at %s says '%s'\n", conn.RemoteAddr().String(), buf)
	}
}

I get the following output from this function:

[nathan@ebisu ~/src/go/echo_server] ./6.out 1234
Using port 1234
Wrote 17 bytes to socket
Error when reading from socket: EOF

This is what I see on the client:

[nathan@ebisu ~] telnet 127.0.0.1 1234
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Ready to receive
Connection closed by foreign host.

Any help would be appreciated (or pointers to resources; the go documentation on the sockets API leaves a little to be desired).

Thanks,

Nathan

答案1

得分: 8

在你的例子中,buf需要有一个确定的大小。你将它声明为一个长度为0的切片。

将其声明为:

var buf = make([]byte, 1024)
英文:

In your example, buf needs to have a definite size. You've declared it as a 0-length slice.

Declare it as:

var buf = make([]byte, 1024)

答案2

得分: 3

当然,如果你想学习的话,最好自己写,但如果有帮助的话,这是我自己用Go语言编写的回显服务器。

package main

import (
    "net";
    "os";
    "fmt";
)

func handle(conn *net.TCPConn) {
    fmt.Printf("来自 %s 的连接\n", conn.RemoteAddr());
    message := make([]byte, 1024);
    // TODO: 循环读取,我们可以有 >1024 字节的数据
    n1, error := conn.Read(message);
    if error != nil {
        fmt.Printf("无法读取:%s\n", error);
        os.Exit(1);
    }
    n2, error := conn.Write(message[0:n1]);
    if error != nil || n2 != n1 {
        fmt.Printf("无法写入:%s\n", error);
        os.Exit(1);
    }
    fmt.Printf("回显了 %d 字节\n", n2);
    conn.Close();    // TODO: 等待看是否有更多数据?用telnet会更好...
}

func main() {
    listen := ":7";
    addr, error := net.ResolveTCPAddr("tcp", listen);
    if error != nil {
        fmt.Printf("无法解析 \"%s\":%s\n", listen, error);
        os.Exit(1);
    }
    listener, error := net.ListenTCP("tcp", addr);
    if error != nil {
        fmt.Printf("无法监听:%s\n", error);
        os.Exit(1);
    }
    for {    // 永远...
        conn, error := listener.AcceptTCP();
        if error != nil {
            fmt.Printf("无法接受连接:%s\n", error);
            os.Exit(1);
        }
        go handle(conn);
    }
}
英文:

Of course, if you want to learn, it is better to write it yourself but, if it helps, here is my own echo server in Go.

package main

import (
    "net";
    "os";
    "fmt";
)

func handle(conn *net.TCPConn) {
    fmt.Printf("Connection from %s\n", conn.RemoteAddr());
    message := make([]byte, 1024);
    // TODO: loop the read, we can have >1024 bytes
    n1, error := conn.Read(message);
    if error != nil {
	    fmt.Printf("Cannot read: %s\n", error);
	    os.Exit(1);
    }
    n2, error := conn.Write(message[0:n1]);
    if error != nil || n2 != n1 {
	    fmt.Printf("Cannot write: %s\n", error);
	    os.Exit(1);
    }
    fmt.Printf("Echoed %d bytes\n", n2);
    conn.Close();	// TODO: wait to see if more data? It would be better with telnet...
}

func main() {
    listen := ":7";
    addr, error := net.ResolveTCPAddr(listen);
    if error != nil {
	    fmt.Printf("Cannot parse \"%s\": %s\n", listen, error);
	    os.Exit(1);
    }
    listener, error := net.ListenTCP("tcp", addr);
    if error != nil {
	    fmt.Printf("Cannot listen: %s\n", error);
	    os.Exit(1);
    }
    for {	// ever...
	    conn, error := listener.AcceptTCP();
	    if error != nil {
		    fmt.Printf("Cannot accept: %s\n", error);
		    os.Exit(1);
	    }
	    go handle(conn);
    }
}

huangapple
  • 本文由 发表于 2010年2月16日 12:36:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/2270670.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定