使用Golang构建服务器,但在客户端遇到问题。

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

Using Golang to build a server but have issue in client side

问题

这是我的代码:

package main

import (
	"fmt"
	"net"
	"net/http"
	"os"
)

const RECV_BUF_LEN = 1024

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Test")
}

func main() {
	http.HandleFunc("/", handler)
	s := &http.Server{Addr: ":8080", Handler: nil}
	listener, err := net.Listen("tcp", s.Addr)
	if err != nil {
		fmt.Println("Error: ", err.Error())
		fmt.Println("Close Server")
		os.Exit(1)
	}

	for {
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println("Error: ", err.Error())
			continue
		}
		go ClientLogic(conn)
	}
}

func ClientLogic(conn net.Conn) {
	fmt.Println("Connect Successful")
	conn.Close()
}

我知道我可以使用以下代码构建一个服务器,但我想做一些其他的事情,比如打印一些数据。

http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)

当代码运行时,服务器端可以成功打印"Connect Successful"。

然而,客户端没有显示任何内容。

换句话说,客户端的浏览器没有显示任何内容,一直在加载,但服务器端可以显示连接成功的消息。

PS:该代码参考了http://lolikitty.pixnet.net/blog/post/148420590和golang的源代码(http://golang.org/src/pkg/net/http/server.go?s=50405:50451#L1684)。

英文:

This is my code:

package main

import (
        "fmt"
        "net"
        "net/http"
        "os"
)

const RECV_BUF_LEN = 1024

func handler(w http.ResponseWriter, r *http.Request) {
        fmt.Fprint(w, "Test")
}

func main() {
        http.HandleFunc("/", handler)
        s := &http.Server{Addr: ":8080", Handler: nil}
        listener, err := net.Listen("tcp", s.Addr)
        if err != nil {
                fmt.Println("Error: ", err.Error())
                fmt.Println("Close Server")
                os.Exit(1)
        }

        for {
                conn, err := l.Accept()
                if err != nil {
                        fmt.Println("Error: ", err.Error())
                        continue
                }
                go ClientLogic(conn)
        }
}

func ClientLogic(conn net.Conn) {
        fmt.Println("Connect Successful")
        conn.Close()
}

I know I can use following code to build a server but I want do some stuffs, such as printing some datas.

http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)

When the code run, the server-side can print "Connect Successful" successfully.

However, the it doesn't display anything in client-side.

In other words, the client's browser display anything and keep loading but the server-side can display the message about connecting successfully.

PS: The code refer to http://lolikitty.pixnet.net/blog/post/148420590 and the golang's source code ( http://golang.org/src/pkg/net/http/server.go?s=50405:50451#L1684 )

答案1

得分: 2

我不确定你想要实现什么,但是这段代码存在一些主要问题。

  1. http.HandleFunc("/",handler)DefaultServeMux.HandleFunc(pattern, handler) 的别名,但是由于你的代码没有涉及到 DefaultServeMux 或者 http.Server,所以它是无用的。

2.(不是特别相关,但是)你检查了 Accept() 的错误然后继续执行,但是大多数情况下,来自 accept 的错误是致命的,你无法从中恢复。

  1. func ClientLogic(conn net.Conn) 立即关闭了连接,没有对连接做任何操作,你期望发生什么?

如果你只是想要访问原始连接,你可以实现类似于 这样的代码

http.HandleFunc("/hijack", func(w http.ResponseWriter, r *http.Request) {
    hj, ok := w.(http.Hijacker)
    if !ok {
        http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
        return
    }
    conn, bufrw, err := hj.Hijack()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    // 不要忘记关闭连接:
    defer conn.Close()
    bufrw.WriteString("Now we're speaking raw TCP. Say hi: ")
    bufrw.Flush()
    s, err := bufrw.ReadString('\n')
    if err != nil {
        log.Printf("error reading string: %v", err)
        return
    }
    fmt.Fprintf(bufrw, "You said: %q\nBye.\n", s)
    bufrw.Flush()
})
http.ListenAndServe(":8080", nil)

以上是翻译好的内容,请确认是否满意。

英文:

I'm not sure what you're trying to achieve but there are some major problems with that code.

  1. http.HandleFunc("/", handler) is an alias for DefaultServeMux.HandleFunc(pattern, handler), but since your code doesn't involve DefaultServeMux in anyway or even http.Server, it's useless.

  2. (not really related but) you check for errors from Accept() then continue, but any error from accept is fatal pretty much and you can't recover from it most of the time.

  3. func ClientLogic(conn net.Conn) closes the connection immediately without doing anything to it, what did you expect to happen?

If all you want is access to the raw connection for some reason you can always implement something like this:

http.HandleFunc("/hijack", func(w http.ResponseWriter, r *http.Request) {
	hj, ok := w.(http.Hijacker)
	if !ok {
		http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
		return
	}
	conn, bufrw, err := hj.Hijack()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	// Don't forget to close the connection:
	defer conn.Close()
	bufrw.WriteString("Now we're speaking raw TCP. Say hi: ")
	bufrw.Flush()
	s, err := bufrw.ReadString('\n')
	if err != nil {
		log.Printf("error reading string: %v", err)
		return
	}
	fmt.Fprintf(bufrw, "You said: %q\nBye.\n", s)
	bufrw.Flush()
})
http.ListenAndServe(":8080", nil)

答案2

得分: 0

你应该使用handler或accept,但如果你使用accept,这将处理新的连接,并且你会忽略handler。你将进入http连接的较低抽象级别。

以下代码片段将按照你的期望工作:

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Test")
    fmt.Println("Connect Successful")
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

当你调用ListenAndServe时,它会正确地进行接受,所以你不需要担心。

英文:

You should use the handler or the accept, but if you use the accept this will be handled the new connection and you are ignoring the handler. You are going to a lower abstraction level of the http connection.

This piece of code work as you expect:

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Test")
    fmt.Println("Connect Successful")
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

When you call to ListenAndServe, he make the correct Accept so you dont need to worry about.

答案3

得分: 0

>OneOfOne:
>> 我不确定你想要实现什么,但是你的代码存在一些主要问题。
>
>> 1) http.HandleFunc("/",handler)DefaultServeMux.HandleFunc(pattern, handler) 的别名,但是由于你的代码没有涉及到 DefaultServeMux 或者 http.Server,所以它是无用的。
>>
>> 3) func ClientLogic(conn net.Conn) 立即关闭连接而没有对其进行任何操作,你期望会发生什么?

  1. 在 Golang 的包中,DefaultServeMux 是 handler 的默认值。因此我从来不关心它。

  2. http://lolikitty.pixnet.net/blog/post/148420590 中的代码可以显示如下的数据:

    接收 409 個 byte 資料: GET / HTTP/1.1
    Host: localhost:8080
    User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110422 Ubuntu/9.10 (karmic) Firefox/3.6.17
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Connection: keep-alive
    Cache-Control: max-age=0

我想要做的是让我的服务器能够显示这些信息。

>mcuadros:
>> 你应该使用 handler 或者 accept,但是如果你使用 accept,这将处理新的连接,而你正在忽略 handler。你正在降低 http 连接的抽象级别。
>>
>> 当你调用 ListenAndServe 时,它会正确地进行 Accept,所以你不需要担心。

谢谢你的代码,它可以实现我想要的功能。

我想要确认一下。我的代码的问题是我使用了 listener.Accept() 来创建一个新的连接。因此我的 handler 被忽略了。服务器可以显示一些内容是因为有新的连接。客户端无法显示任何内容是因为它来自旧的 handler,对吗?

英文:

>OneOfOne:
>> I'm not sure what you're trying to achieve but there are some major problems with that code.
>
>> 1) http.HandleFunc("/", handler) is an alias for DefaultServeMux.HandleFunc(pattern, handler), but since your code doesn't involve DefaultServeMux in anyway or even http.Server, it's useless.
>>
>> 3) func ClientLogic(conn net.Conn) closes the connection immediately without doing anything to it, whatdid you expect to happen?

  1. in golang's package, it says the DefaultServeMux is the default value of handler. Therefore I never care about it.

  2. The code in http://lolikitty.pixnet.net/blog/post/148420590 can display the data like following:

    接收 409 個 byte 資料: GET / HTTP/1.1
    Host: localhost:8080
    User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110422 Ubuntu/9.10 (karmic) Firefox/3.6.17
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Connection: keep-alive
    Cache-Control: max-age=0

What I want to do is that my server can display those information.

>mcuadros:
>>You should use the handler or the accept, but if you use the accept this will be handled the new connection and you are ignoring the handler. You are going to a lower abstraction level of the http connection.
>>
>>When you call to ListenAndServe, he make the correct Accept so you dont need to worry about.

Thanks for your code, it can do what I want.

I want to make sure. The issue of my code is I use listener.Accept() to make a new connection. Therefore my handler is ignored. The server can display something because of the new connection. The client side cannot display anything because it is from the old handler, doesn't it?

huangapple
  • 本文由 发表于 2014年9月3日 17:29:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/25640824.html
匿名

发表评论

匿名网友

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

确定