Go:通过管道发送gob卡住了 – 更新:进程外的http.ResponseWriter正在阻塞

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

Go: Sending gob's over a pipe is hanging - UPDATE: Out-of-process http.ResponseWriter is blocking

问题

我正在编写一个使用Go语言将请求分发给外部进程的Web服务器。我正在使用gob通过管道发送ResponseWriter和Request数据类型。

问题是当接收gob时,外部进程会挂起。

更新 现在gob已成功发送到外部进程,但是外部进程在fmt.Fprintf(request.Resp, "Hello")处阻塞并停在那里。

dispreq.go

package dispreq

import (
    "net/http"
)

type DispReq struct {
    Resp http.ResponseWriter
    Req  *http.Request
}

dispatcher.go

package main

import (
    "encoding/gob"
    "fmt"
    "net/http"
    "os"
    "os/exec"

    "dispreq"
)

func dispatch(w http.ResponseWriter, r *http.Request) {
    process := exec.Command("./hello")
    pipe, piperr := process.StdinPipe()

    if piperr != nil {
        fmt.Fprintf(os.Stderr, piperr.Error())
        return
    }

    encoder := gob.NewEncoder(pipe)

    process.Stdout = os.Stdout

    //更新:encoder.Encode(&dispreq.DispReq{w, r})
    //更新:process.Start()
    process.Start()
    encoder.Encode(&dispreq.DispReq{w, r})
    pipe.Close()
    process.Wait()
}

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

hello.go

package main

import (
    "dispreq"
    "encoding/gob"
    "os"

    "fmt"
)

func main() {
    gobDecoder := gob.NewDecoder(os.Stdin)
    var request dispreq.DispReq
    gobDecoder.Decode(&request)
    fmt.Fprintf(request.Resp, "Hello")
}
英文:

I'm writing a webserver that distributes requests to out-of-process programs in Go. I'm sending the ResponseWriter and Request datatypes through Pipes using gob.

The problem is the external process is hanging when receiving the gob.

UPDATE The gob is now successfully being sent to the external process, but now the external process is blocking at fmt.Fprintf(request.Resp, "Hello") and freezes there.

dispreq.go

package dispreq

import (
    "net/http"
)

type DispReq struct {
	Resp	http.ResponseWriter
	Req	*http.Request
}

dispatcher.go

package main

import (
	"encoding/gob"
	"fmt"
	"net/http"
	"os"
	"os/exec"

	"dispreq"
)

func dispatch(w http.ResponseWriter, r *http.Request) {
	process := exec.Command("./hello")
	pipe, piperr := process.StdinPipe()

	if piperr != nil {
		fmt.Fprintf(os.Stderr, piperr.Error())
		return
	}

	encoder := gob.NewEncoder(pipe)

	process.Stdout = os.Stdout

	//UPDATE: encoder.Encode(&dispreq.DispReq{w, r})
	//UPDATE: process.Start()
	process.Start()
	encoder.Encode(&dispreq.DispReq{w, r})
	pipe.Close()
	process.Wait()
}

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

hello.go

package main

import (
	"dispreq"
	"encoding/gob"
	"os"

	"fmt"
)

func main() {
	gobDecoder := gob.NewDecoder(os.Stdin)
	var request dispreq.DispReq
	gobDecoder.Decode(&request)
	fmt.Fprintf(request.Resp, "Hello")
}

答案1

得分: 2

你应该在发送数据给它之前启动进程(process.Start())。你可能还需要通过关闭管道(pipe.Close())或发送一个\n来刷新管道。

英文:

You should start the process (process.Start()) before sending data to it (encoder.Encode(&dispreq.DispReq{w, r})). You might also need to flush your pipe by closing it (pipe.Close()) or sending a \n.

huangapple
  • 本文由 发表于 2012年10月19日 14:27:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/12968533.html
匿名

发表评论

匿名网友

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

确定