WebSocket을 사용하여 사격 기능을 구현하는 모든 사람을 위한 컬럼, 필요한 친구들에게 도움이 되길 바랍니다!
websocket 프로토콜을 사용하여 클라이언트는 메시지를 보내고 서버는 이를 모든 유효한 연결에 브로드캐스트합니다.기본 아이디어: 1. *websocket.conn을 캡슐화하고 클라이언트 구조를 사용하여 클라이언트를 나타냅니다.
3. 웹소켓 연결을 처리하는 것 외에도 클라이언트 연결, 연결 해제 및 게시를 모니터링하기 위해 브로드캐스트 코루틴도 열어야 합니다. 이벤트.
추천: "
go 언어 튜토리얼
"
type Client struct{ wsConnect *websocket.Conn inChan chan []byte outChan chan []byte closeChan chan byte Name string //客户的名称 Id string //客户id,唯一 mutex sync.Mutex // 对closeChan关闭上锁 IsClosed bool // 防止closeChan被关闭多次 } type Message struct { EventType byte `json:"type"` // 0表示用户发布消息;1表示用户进入;2表示用户退出 Name string `json:"name"` // 用户名称 Message string `json:"message"` // 消息内容 } clients = make(map [*util.Client] bool) // 用户组映射 join = make(chan *util.Client, 10) // 用户加入通道 leave = make(chan *util.Client, 10) // 用户退出通道 message = make(chan Message, 10) // 消息通道
서버 측 코드package main
import (
"encoding/json"
"fmt"
"github.com/gorilla/websocket"
"goGin/server/util"
"net/http"
)
var(
upgrader = websocket.Upgrader{
// 允许跨域
CheckOrigin:func(r *http.Request) bool{
return true
},
}
clients = make(map [*util.Client] bool) // 用户组映射
join = make(chan *util.Client, 10) // 用户加入通道
leave = make(chan *util.Client, 10) // 用户退出通道
message = make(chan Message, 10) // 消息通道
)
type Message struct {
EventType byte `json:"type"` // 0表示用户发布消息;1表示用户进入;2表示用户退出
Name string `json:"name"` // 用户名称
Message string `json:"message"` // 消息内容
}
func wsHandler(w http.ResponseWriter , r *http.Request){
var(
wsConn *websocket.Conn
err error
client *util.Client
data []byte
)
r.ParseForm() //返回一个map,并且赋值给r.Form
name := r.Form["name"][0]
id := r.Form["id"][0]
if wsConn , err = upgrader.Upgrade(w,r,nil); err != nil{
return
}
if client , err = util.InitConnection(wsConn); err != nil{
goto ERR
}
client.Id = id
client.Name = name
// 如果用户列表中没有该用户
if !clients[client] {
join <- client
}
for {
if data , err = client.ReadMessage();err != nil{ //一直读消息,没有消息就阻塞
goto ERR
}
var msg Message
msg.EventType = 0
msg.Name = client.Name
msg.Message = string(data)
message <- msg
}
ERR:
leave<-client//这个客户断开
client.Close()
}
func broadcaster() {
for {
select {
// 消息通道中有消息则执行,否则堵塞
case msg := <-message:
// 将数据编码成json形式,data是[]byte类型
// json.Marshal()只会编码结构体中公开的属性(即大写字母开头的属性)
data, err := json.Marshal(msg)
if err != nil {
return
}
for client := range clients {
if client.IsClosed == true {
leave<-client//这个客户断开
continue
}
// fmt.Println("=======the json message is", string(data)) // 转换成字符串类型便于查看
if client.WriteMessage(data) != nil {
continue //发送失败就跳过
}
}
// 有用户加入
case client := <-join:
clients[client] = true // 将用户加入映射
// 将用户加入消息放入消息通道
var msg Message
msg.Name = client.Name
msg.EventType = 1
msg.Message = fmt.Sprintf("%s join in, there are %d preson in room", client.Name, len(clients))
message <- msg
// 有用户退出
case client := <-leave:
// 如果该用户已经被删除
if !clients[client] {
break
}
delete(clients, client) // 将用户从映射中删除
// 将用户退出消息放入消息通道
var msg Message
msg.Name = client.Name
msg.EventType = 2
msg.Message = fmt.Sprintf("%s leave, there are %d preson in room", client.Name, len(clients))
message <- msg
}
}
}
func main(){
go broadcaster()
http.HandleFunc("/ws",wsHandler)
http.ListenAndServe("0.0.0.0:7777",nil)
}
캡슐화된 클라이언트
package util import ( "github.com/gorilla/websocket" "sync" "errors" ) type Client struct{ wsConnect *websocket.Conn inChan chan []byte outChan chan []byte closeChan chan byte Name string //客户的名称 Id string //客户id,唯一 mutex sync.Mutex // 对closeChan关闭上锁 IsClosed bool // 防止closeChan被关闭多次 } func InitConnection(wsConn *websocket.Conn)(conn *Client ,err error){ conn = &Client{ wsConnect:wsConn, inChan: make(chan []byte,1000), outChan: make(chan []byte,1000), closeChan: make(chan byte,1), IsClosed:false, } // 启动读协程 go conn.readLoop(); // 启动写协程 go conn.writeLoop(); return } func (conn *Client)ReadMessage()(data []byte , err error){ select{ case data = <- conn.inChan: case <- conn.closeChan: err = errors.New("connection is closeed") } return } func (conn *Client)WriteMessage(data []byte)(err error){ select{ case conn.outChan <- data: case <- conn.closeChan: err = errors.New("connection is closeed") } return } func (conn *Client)Close(){ // 线程安全,可多次调用 conn.wsConnect.Close() // 利用标记,让closeChan只关闭一次 conn.mutex.Lock() if !conn.IsClosed { close(conn.closeChan) conn.IsClosed = true } conn.mutex.Unlock() } func (conn *Client)readLoop(){ var( data []byte err error ) for{ if _, data , err = conn.wsConnect.ReadMessage(); err != nil{ goto ERR } //阻塞在这里,等待inChan有空闲位置 select{ case conn.inChan <- data: case <- conn.closeChan: // closeChan 感知 conn断开 goto ERR } } ERR: conn.Close() } func (conn *Client)writeLoop(){ var( data []byte err error ) for{ select{ case data= <- conn.outChan: case <- conn.closeChan: goto ERR } if err = conn.wsConnect.WriteMessage(websocket.TextMessage , data); err != nil{ goto ERR } } ERR: conn.Close() }
클라이언트 측 코드
<!DOCTYPE html> <html> <head> <title>go websocket</title> <meta charset="utf-8" /> </head> <body> <script type="text/javascript"> var wsUri ="ws://127.0.0.1:7777/ws?name=aaa&id=112"; var output; function init() { output = document.getElementById("output"); testWebSocket(); } function testWebSocket() { websocket = new WebSocket(wsUri); websocket.onopen = function(evt) { onOpen(evt) }; websocket.onclose = function(evt) { onClose(evt) }; websocket.onmessage = function(evt) { onMessage(evt) }; websocket.onerror = function(evt) { onError(evt) }; } function onOpen(evt) { writeToScreen("CONNECTED"); // doSend("WebSocket rocks"); } function onClose(evt) { writeToScreen("DISCONNECTED"); } function onMessage(evt) { writeToScreen('<span style="color: blue;">RESPONSE: '+ evt.data+'</span>'); // websocket.close(); } function onError(evt) { writeToScreen('<span style="color: red;">ERROR:</span> '+ evt.data); } function doSend(message) { // writeToScreen("SENT: " + message); websocket.send(message); } function writeToScreen(message) { var pre = document.createElement("p"); pre.style.wordWrap = "break-word"; pre.innerHTML = message; output.appendChild(pre); } window.addEventListener("load", init, false); function sendBtnClick(){ var msg = document.getElementById("input").value; doSend(msg); document.getElementById("input").value = ''; } function closeBtnClick(){ websocket.close(); } </script> <h2 id="WebSocket-nbsp-Test">WebSocket Test</h2> <input type="text" id="input"></input> <button onclick="sendBtnClick()" >send</button> <button onclick="closeBtnClick()" >close</button> <div id="output"></div> </body> </html>
위 내용은 Go가 websocket을 사용하여 사격 기능을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

C는 하드웨어 리소스 및 고성능 최적화가 직접 제어되는 시나리오에 더 적합하지만 Golang은 빠른 개발 및 높은 동시성 처리가 필요한 시나리오에 더 적합합니다. 1.C의 장점은 게임 개발과 같은 고성능 요구에 적합한 하드웨어 특성 및 높은 최적화 기능에 가깝습니다. 2. Golang의 장점은 간결한 구문 및 자연 동시성 지원에 있으며, 이는 동시성 서비스 개발에 적합합니다.

Golang은 실제 응용 분야에서 탁월하며 단순성, 효율성 및 동시성으로 유명합니다. 1) 동시 프로그래밍은 Goroutines 및 채널을 통해 구현됩니다. 2) Flexible Code는 인터페이스 및 다형성을 사용하여 작성됩니다. 3) NET/HTTP 패키지로 네트워크 프로그래밍 단순화, 4) 효율적인 동시 크롤러 구축, 5) 도구 및 모범 사례를 통해 디버깅 및 최적화.

GO의 핵심 기능에는 쓰레기 수집, 정적 연결 및 동시성 지원이 포함됩니다. 1. Go Language의 동시성 모델은 고루틴 및 채널을 통한 효율적인 동시 프로그래밍을 실현합니다. 2. 인터페이스 및 다형성은 인터페이스 방법을 통해 구현되므로 서로 다른 유형을 통일 된 방식으로 처리 할 수 있습니다. 3. 기본 사용법은 기능 정의 및 호출의 효율성을 보여줍니다. 4. 고급 사용에서 슬라이스는 동적 크기 조정의 강력한 기능을 제공합니다. 5. 레이스 조건과 같은 일반적인 오류는 Getest-race를 통해 감지 및 해결할 수 있습니다. 6. 성능 최적화는 sync.pool을 통해 개체를 재사용하여 쓰레기 수집 압력을 줄입니다.

Go Language는 효율적이고 확장 가능한 시스템을 구축하는 데 잘 작동합니다. 장점은 다음과 같습니다. 1. 고성능 : 기계 코드로 컴파일, 빠른 달리기 속도; 2. 동시 프로그래밍 : 고어 라틴 및 채널을 통한 멀티 태스킹 단순화; 3. 단순성 : 간결한 구문, 학습 및 유지 보수 비용 절감; 4. 크로스 플랫폼 : 크로스 플랫폼 컴파일, 쉬운 배포를 지원합니다.

SQL 쿼리 결과의 정렬에 대해 혼란스러워합니다. SQL을 학습하는 과정에서 종종 혼란스러운 문제가 발생합니다. 최근 저자는 "Mick-SQL 기본 사항"을 읽고 있습니다.

기술 스택 컨버전스와 기술 선택의 관계, 소프트웨어 개발에서 기술 스택의 선택 및 관리는 매우 중요한 문제입니다. 최근에 일부 독자들은 ...

골란 ...

GO 언어로 세 가지 구조를 비교하고 처리하는 방법. GO 프로그래밍에서는 때때로 두 구조의 차이점을 비교하고 이러한 차이점을 ...에 적용해야합니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

WebStorm Mac 버전
유용한 JavaScript 개발 도구

VSCode Windows 64비트 다운로드
Microsoft에서 출시한 강력한 무료 IDE 편집기
