英文:
How can I send signal from the server to the client upon receiving os.Interrupt
问题
在我的代码中,我在关闭之前监听 os.Interrupt
的信号。
package main
import (
"net/http"
"os"
"os/signal"
"syscall"
)
var passer *DataPasser
const maxClients = 1
func init() {
passer = &DataPasser{
data: make(chan sseData),
logs: make(chan string),
connection: make(chan struct{}, maxClients),
}
}
func main() {
http.HandleFunc("/sse", passer.HandleSignal)
go http.ListenAndServe(":1234", nil)
// 监听 Ctrl+C 信号(你也可以做其他阻止程序退出的操作)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
<-c
if client.IsConnected() {
client.Disconnect()
}
}
passer.HandleSignal
是一个函数,用于向客户端发送 SSE(Server Sent Event):
package main
import (
"fmt"
"net/http"
)
type sseData struct {
event, message string
}
type DataPasser struct {
data chan sseData
connection chan struct{} // 控制最大允许的客户端连接数
}
func (p *DataPasser) HandleSignal(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/event-stream; charset=utf-8")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
fmt.Println("Client connected from IP:", r.RemoteAddr)
p.connection <- struct{}{}
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Internal error", 500)
return
}
fmt.Fprint(w, "event: notification\ndata: Connection to WhatsApp server ...\n\n")
flusher.Flush()
// 连接到 WhatsApp 客户端
go Connect()
for {
select {
case data := <-p.data:
fmt.Println("received")
switch {
case len(data.event) > 0:
fmt.Fprintf(w, "event: %v\ndata: %v\n\n", data.event, data.message)
case len(data.event) == 0:
fmt.Fprintf(w, "data: %v\n\n", data.message)
}
flusher.Flush()
case <-r.Context().Done():
<-p.connection
fmt.Println("Connection closed")
return
}
}
}
func Connect() {
// 进行数据操作,并将结果发送给 `parser`
passer.data <- sseData{
event: "notification",
message: "Reconnecting to WhatsApp server ...",
}
}
我的问题是,如果用户使用 Ctrl+C 中断应用程序,main
函数会对其做出响应,我希望它将数据发送给 parser
,以便处理程序向客户端发送服务器已关闭的通知。
英文:
In my code, I've the below that is listening to os.Interrupt
before closing
package main
import (
"net/http"
"os"
"os/signal"
"syscall"
)
var passer *DataPasser
const maxClients = 1
func init() {
passer = &DataPasser{
data: make(chan sseData),
logs: make(chan string),
connection: make(chan struct{}, maxClients),
}
}
func main() {
http.HandleFunc("/sse", passer.HandleSignal)
go http.ListenAndServe(":1234", nil)
// Listen to Ctrl+C (you can also do something else that prevents the program from exiting)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
<-c
if client.IsConnected() {
client.Disconnect()
}
}
The passer.HandleSignal
is a function that is sending SSE Server Sent Event
to the client, as:
package main
import (
"fmt"
"net/http"
)
type sseData struct {
event, message string
}
type DataPasser struct {
data chan sseData
connection chan struct{} // To control maximum allowed clients connections
}
func (p *DataPasser) HandleSignal(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/event-stream; charset=utf-8")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
fmt.Println("Client connected from IP:", r.RemoteAddr)
p.connection <- struct{}{}
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "Internal error", 500)
return
}
fmt.Fprint(w, "event: notification\ndata: Connection to WhatsApp server ...\n\n")
flusher.Flush()
// Connect to the WhatsApp client
go Connect()
for {
select {
case data := <-p.data:
fmt.Println("recieved")
switch {
case len(data.event) > 0:
fmt.Fprintf(w, "event: %v\ndata: %v\n\n", data.event, data.message)
case len(data.event) == 0:
fmt.Fprintf(w, "data: %v\n\n", data.message)
}
flusher.Flush()
case <-r.Context().Done():
<-p.connection
fmt.Println("Connection closed")
return
}
}
}
func Connect() {
// Doing data manipulation, and sending reselt to the `parser`
passer.data <- sseData{
event: "notification",
message: "Reconnecting to WhatsApp server ...",
}
}
My question is that, if the user interupted the application using Ctrl+C, the main
function is responding to it, I need it to send data to the parser
so that the handler send notification to the client that the server had been shut down
答案1
得分: -1
我找到了解决方案,它很简单,只需将日期传递给在os.interupt范围内定义为全局变量的parser
,如下所示:
<-c
if client.IsConnected() {
passer.data <- sseData{
event: "notification",
message: "服务器在主机上关闭...",
}
client.Disconnect()
}
英文:
I found the solution, it was trivial, just pass date to the parser
which is defined as global variable within the os.interupt scope, as:
<-c
if client.IsConnected() {
passer.data <- sseData{
event: "notification",
message: "Server is shut down at the host machine...",
}
client.Disconnect()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论