在GO中使用长轮询(Long Polling),服务器没有适当地响应吗?

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

Long Polling in GO, Server Not Responding Appropriately?

问题

我正在尝试实现一个简单的“全局”计数器,它根据每个用户在其浏览器上点击按钮而更新。例如,如果你访问网站并点击按钮,如果我也在同一个网站上,我将看到计数器增加。我尝试使用长轮询来实现这一点,但遇到了一些问题。主要问题是服务器变量没有按照我认为的方式返回。

服务器端代码如下:

package main

import (
	"net/http"
	"log"
	"io"
	"io/ioutil"
)

var messages chan string = make(chan string, 100)

var counter = 0

func PushHandler(w http.ResponseWriter, req *http.Request) {

	body, err := ioutil.ReadAll(req.Body)
	
	if err != nil {
		w.WriteHeader(400)
	}
	counter += 1
	messages <- string(counter)
}


func PollResponse(w http.ResponseWriter, req *http.Request) {
	
	io.WriteString(w, <-messages)
}

func main() {
	http.Handle("/", http.FileServer(http.Dir("./")))
	http.HandleFunc("/poll", PollResponse)
	http.HandleFunc("/push", PushHandler)
	err := http.ListenAndServe(":8005", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

客户端代码如下:

<html>
<script language=javascript>

function longpoll(url, callback) {

	var req = new XMLHttpRequest (); 
	req.open ('GET', url, true); 

	req.onreadystatechange = function (aEvt) {
		if (req.readyState == 4) { 
			if (req.status == 200) {
				callback(req.responseText);
				longpoll(url, callback);
			} else {
				alert ("long-poll connection lost");
			}
		}
	};

	req.send(null);
}

function recv(msg) {

	var box = document.getElementById("counter");
	
	box.value += msg + "\n";
}
function send() {

	
	var box = document.getElementById("counter");

  var req = new XMLHttpRequest (); 
	req.open ('POST', "/push?rcpt=", true); 

	req.onreadystatechange = function (aEvt) {
		if (req.readyState == 4) { 
			if (req.status == 200) {
			} else {
				alert ("failed to send!");
			}
		}
  };
  req.send("hi")
	
  //box.innerHTML += "test" ;  
}
</script>
<body onload="longpoll('/poll', recv);">

<h1> Long-Poll Chat Demo </h1>
 
<p id="counter"></p>
<button onclick="send()" id="test">Test Button</button>
</body>
</html>

出于某种原因,计数器变量没有从服务器返回。我认为每次点击按钮时我都在改变状态,所以长轮询函数应该获取到最新更新的计数器变量。如果你有任何建议,请告诉我!

英文:

I am trying to implement a simple "global" counter that updates based on every user that clicks the button on their browsers button. For example, if you go to the website and click the button, I will see the counter increase on my side if I'm on the same website. I sought to do this with long polling, but am facing some issues. Mainly the server variable is not coming back as I think it should.

The server:

package main
import (
&quot;net/http&quot;
&quot;log&quot;
&quot;io&quot;
&quot;io/ioutil&quot;
)
var messages chan string = make(chan string, 100)
var counter = 0
func PushHandler(w http.ResponseWriter, req *http.Request) {
body, err := ioutil.ReadAll(req.Body)
if err != nil {
w.WriteHeader(400)
}
counter += 1
messages &lt;- string(counter)
}
func PollResponse(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, &lt;-messages)
}
func main() {
http.Handle(&quot;/&quot;, http.FileServer(http.Dir(&quot;./&quot;)))
http.HandleFunc(&quot;/poll&quot;, PollResponse)
http.HandleFunc(&quot;/push&quot;, PushHandler)
err := http.ListenAndServe(&quot;:8005&quot;, nil)
if err != nil {
log.Fatal(&quot;ListenAndServe: &quot;, err)
}
}

The client:

&lt;html&gt;
&lt;script language=javascript&gt;
function longpoll(url, callback) {
var req = new XMLHttpRequest (); 
req.open (&#39;GET&#39;, url, true); 
req.onreadystatechange = function (aEvt) {
if (req.readyState == 4) { 
if (req.status == 200) {
callback(req.responseText);
longpoll(url, callback);
} else {
alert (&quot;long-poll connection lost&quot;);
}
}
};
req.send(null);
}
function recv(msg) {
var box = document.getElementById(&quot;counter&quot;);
box.value += msg + &quot;\n&quot;;
}
function send() {
var box = document.getElementById(&quot;counter&quot;);
var req = new XMLHttpRequest (); 
req.open (&#39;POST&#39;, &quot;/push?rcpt=&quot;, true); 
req.onreadystatechange = function (aEvt) {
if (req.readyState == 4) { 
if (req.status == 200) {
} else {
alert (&quot;failed to send!&quot;);
}
}
};
req.send(&quot;hi&quot;)
//box.innerHTML += &quot;test&quot; ;  
}
&lt;/script&gt;
&lt;body onload=&quot;longpoll(&#39;/poll&#39;, recv);&quot;&gt;
&lt;h1&gt; Long-Poll Chat Demo &lt;/h1&gt;
&lt;p id=&quot;counter&quot;&gt;&lt;/p&gt;
&lt;button onclick=&quot;send()&quot; id=&quot;test&quot;&gt;Test Button&lt;/button&gt;
&lt;/body&gt;
&lt;/html&gt;

The counter variable is not coming back from the server for some reason. I believe I am changing the state every time the button is clicked and so the longpolling function should get the newly updated counter variable. If you have any suggestions, please let me know!

答案1

得分: 1

我在你的程序中看到两个问题:

  1. 在服务器端:

    messages <- string(counter)

你应该使用 "strconv" 包

messages <- strconv.Itoa(counter)

string(0) 会返回类似 []byte{0} 的内容,而不是 "0"
2. 在你的客户端:

function recv(msg) {
var box = document.getElementById("counter");
box.value += msg + "\n";
}

应该改为:

function recv(msg) {
var box = document.getElementById("counter");
box.innerHTML += msg + "\n";
}

我认为 p 元素 没有 value 属性。

英文:

I see two issues in you program:

  1. In the server:

    messages <- string(counter)

You should use "strconv" package

messages &lt;- strconv.Itoa(counter)

string(0) will return something like []byte{0} not a "0"
2. In your client:

function recv(msg) {
var box = document.getElementById(&quot;counter&quot;);
box.value += msg + &quot;\n&quot;;
}

Should be:

function recv(msg) {
var box = document.getElementById(&quot;counter&quot;);
box.innerHTML += msg + &quot;\n&quot;;
}

I don't think the p element have value property

huangapple
  • 本文由 发表于 2013年11月4日 12:14:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/19761549.html
匿名

发表评论

匿名网友

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

确定