第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

Golang - API Server 和 Socket 同時(shí)進(jìn)行

Golang - API Server 和 Socket 同時(shí)進(jìn)行

Go
qq_笑_17 2022-01-10 19:12:26
我嘗試制作套接字以與我的客戶(hù)進(jìn)行通信。在對(duì)我的 API 發(fā)出一些請(qǐng)求后,將創(chuàng)建一個(gè)套接字。這意味著,客戶(hù)端連接自己(僅通過(guò)請(qǐng)求),但隨后,他加入了聊天,因此創(chuàng)建了一個(gè)套接字并將其鏈接到良好的頻道。我已經(jīng)使用過(guò)套接字,所以我了解它是如何工作的(C、C++、C#、Java),但是我想做的,我在網(wǎng)上看到的,我認(rèn)為這是可能的,但我不明白如何處理它與golang。我創(chuàng)建了第一臺(tái)服務(wù)器:func main() {    r := mux.NewRouter()    r.HandleFunc("/", HomeHandler)    r.HandleFunc("/products", ProductsHandler)    r.HandleFunc("/articles", ArticlesHandler)    http.Handle("/", r)}但是對(duì)于套接字,我需要另一個(gè)嗎?package mainimport "net"import "fmt"import "bufio"import "strings" // only needed below for sample processingfunc main() {    fmt.Println("Launching server...")    // listen on all interfaces    ln, _ := net.Listen("tcp", ":8081")    // accept connection on port    conn, _ := ln.Accept()       // run loop forever (or until ctrl-c)    for {             // will listen for message to process ending in newline (\n)        message, _ := bufio.NewReader(conn).ReadString('\n')        // output message received             fmt.Print("Message Received:", string(message))        // sample process for string received             newmessage := strings.ToUpper(message)        // send new string back to client             conn.Write([]byte(newmessage + "\n"))       } }感謝您的幫助!
查看完整描述

2 回答

?
鳳凰求蠱

TA貢獻(xiàn)1825條經(jīng)驗(yàn) 獲得超4個(gè)贊

默認(rèn) http 服務(wù)器僅接受一個(gè)“主機(jī):端口”上的連接


答案取決于您將使用什么協(xié)議通過(guò)套接字進(jìn)行通信。


我建議這樣做:(非常簡(jiǎn)化)


讓 http.Server 單獨(dú)為您的 API 提供服務(wù)(它實(shí)現(xiàn)了 HTTP 1.*/2 協(xié)議,因此您無(wú)需擔(dān)心)


實(shí)現(xiàn)你自己的“MultiSocketServer”,這樣做:


2.1 實(shí)現(xiàn) GracefulListener(必須實(shí)現(xiàn) net.Listener)(當(dāng)你不再需要它們時(shí),你需要關(guān)閉你的套接字,對(duì)吧?)


2.2 實(shí)現(xiàn) MultiSocketServer.Serve(l GracefulListener) (hello http.Server.Serve() ) 來(lái)服務(wù)單個(gè)連接(你通過(guò)套接字與客戶(hù)端通信的協(xié)議在這里。像 net.textproto 這樣的東西很容易實(shí)現(xiàn),因?yàn)槟?GracefulListener.Accept () 將返回 net.Conn)


2.3 添加方法MultiSocketServer.ListenAndServe(addr), MultiSocketServer.StopServe(l GracefulListener) 到你的MultiSocketServer


type MultiSocketServer struct {

    listeners GracefulListener[] //or map?


    // lots of other stuff

}



// looks familiar? (http.Server.ListenAndServe) 

func (s *MultiSocketServer) ListenAndServe(addr string) {

    ln, err := net.Listen("tcp", addr)

    graceful_listner = &GracefulListener(ln)


    s.listeners = append(s.listeners, graceful_listner)


    go s.Serve(graceful_listner)

    return graceful_listner

}


func (s *MultiSocketServer) StopServe(graceful_listner  GracefulListener) {

    graceful_listner.Stop()

    //pseudocode

    remove_listener_from_slice(s.listeners, graceful_listner)

}

當(dāng)然,您需要添加錯(cuò)誤檢查和互斥鎖(可能)來(lái)保護(hù) MultiSocketServer.listeners 以使其線(xiàn)程安全。


在您的 main() 中啟動(dòng)您的 API http.Server,并初始化您的 MultiSocketServer?,F(xiàn)在,從 http.Server 的 http.Handler/http.HandlerFunc 中,您應(yīng)該能夠調(diào)用 MultiSocketServer.ListenAndServe(addr) 來(lái)監(jiān)聽(tīng)和服務(wù)您的套接字連接。


根據(jù)問(wèn)題更新


但是,我不確定是否理解“在您的 main() 中”部分。如果我理解得很好,你說(shuō)我有我的API,啟動(dòng)它后,我初始化MultiSocketServer。但是哪里?在我的 API 啟動(dòng)之后?或者您的意思是我將您的代碼邏輯用作 API 會(huì)更好?每個(gè)請(qǐng)求都通過(guò)一個(gè)套接字


順便說(shuō)一句:更新 MultiSocketServer.ListenAndServe 以啟動(dòng) Listen 并返回 graceful_listner


func main() {

    //init MultiSocketServer

    multi_socket_server = &MultiSocketServer{} //nil for GracefulListener[] is fine for now, complex initialization will be added later

    // no listners yet, serves nothing


    // create new Handeler for your "socket requests"

    SocketRequestHandler := function(w http.ResponseWriter, r *http.Request) {

       // identify client, assign him an address to connect

       addr_to_listen := parse_request(r) //pseudocode


       listener := multi_socket_server.ListenAndServe(addr_to_listen)

       // TODO: handle errors

       // now your multi_socket_server listen to addr_to_listen and serves it with multi_socket_server.Serve method in its own goroutine

       // as i said MultiSocketServer.Serve method must implement your protocol (plaintext Reader/Writer on listener for now?)


       save_listener_in_context_or_whatever_you_like_to_track_it(listener) //pseudo

   }  


    SocketDisconnectHandler := function(w http.ResponseWriter, r *http.Request) {

      // identify client 

      some_client := parse_request(r) //pseudocode

      // get listener based on info

      listener := get_listener_from_context_or_whatever(some_client) //pseudo


      multi_socket_server.StopServe(listener)

      // TODO: handle errors

    }


    //initialize your API http.Server

    r := mux.NewRouter()

    r.HandleFunc("/", HomeHandler)

    r.HandleFunc("/products", ProductsHandler)

    r.HandleFunc("/articles", ArticlesHandler)

    r.HandleFunc("/socket_request", SocketRequestHandler) // added

    r.HandleFunc("/socket_disconnect", SocketDisconnectHandler) //added

    http.Handle("/", r)


    // it creates new http.Server with DefaultServeMux as Handler (which is configured with your http.Handle("/", r) call)

   http.ListenAndServe(":8080") // start serving API via HTTP proto

}

實(shí)際上,您可以調(diào)用multi_socket_server.ListenAndServe(addr_to_listen)和multi_socket_server.StopServe(listener)從您的 API 服務(wù)器中的任何處理程序。


每次調(diào)用multi_socket_server.ListenAndServe(addr_to_listen)它都會(huì)創(chuàng)建新的偵聽(tīng)器并為其提供服務(wù),您必須控制它(不要在同一個(gè)地址上偵聽(tīng)一次以上(我認(rèn)為它無(wú)論如何都會(huì)出錯(cuò)))


您的 MultiSocketServer.Serve 可能如下所示:


func (s *MultiSocketServer) Serve(l net.Listener) {

    defer l.Close()


    for {     

        // will listen for message to process ending in newline (\n)

        message, _ := bufio.NewReader(conn).ReadString('\n')

        // output message received     

        fmt.Print("Message Received:", string(message))

        // sample process for string received     

        newmessage := strings.ToUpper(message)

        // send new string back to client     

        conn.Write([]byte(newmessage + "\n"))   

    } 

}

可能的 GracefulListener實(shí)現(xiàn) github


還是您想實(shí)現(xiàn)完全不同的目標(biāo)?=)


查看完整回答
反對(duì) 回復(fù) 2022-01-10
?
繁花如伊

TA貢獻(xiàn)2012條經(jīng)驗(yàn) 獲得超12個(gè)贊

基于我們的聊天討論。


OVER帶有大量偽代碼的簡(jiǎn)化示例


import (

    "net"

    "encoding/json"

    "errors"

)


type User struct {

    name string

}


type Message {

    Action string

    Params map[string]string

}


type Server struct {

    connected_users map[*User]net.Conn

    users_connected_with_each_other map[*User][]*User

    good_users map[string]*User

}


func (srv *Server) ListenAndServe(addr string) error {

    ln, err := net.Listen("tcp", addr)

    if err != nil {

        return err

    }

    return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})

}


func (srv *Server) Serve(l net.Listener) error {

    defer l.Close()


    for {

        rw, e := l.Accept()

        if e != nil {

            return e

        }


        // you want to create server_conn here with buffers, channels and stuff

        // to use async thread safe read/write from it

        go srv.serve_conn(rw)

    }

}


func (srv *Server) serve_conn(rw net.Conn) error {  

    dec := json.NewDecoder(rw)


    var message Message


    //read 1st message he sent, should be token to connect

    dec.Decode(&message)


    token := get_token(Message)


    user, ok := srv.good_users[token]


    if !ok {

        return errors.New("BAD USER!")

    }

    // store connected user

    srv.connected_users[user] = rw


    for {

        // async reader will be nice

        dec.Decode(&message)


        switch message.Action {

            case "Message":

                // find users to send message to

                if chats_with, err := users_connected_with_each_other[user]; err == nil {                   

                    for user_to_send_message_to := range chats_with {

                        // find connections to send message to

                        if conn, err := srv.connected_users[user_to_send_message_to]; err == nil {

                            // send json encoded message

                            err := json.NewEncoder(conn).Encode(message)

                            //if write failed store message for later

                        }

                    }

                }


            //other cases


            default:

                // log?

        }       

    }

}


func main() {

    known_users_with_tokens := make(map[string]*User)



    srv := &Server{

        connected_users: make(map[*User]net.Conn),

        users_connected_with_each_other: make(map[*User][]*User),

        good_users: known_users_with_tokens, // map is reference type, so treat it like pointer

    }

    // start our server

    go srv.ListenAndServe(":54321")



    ConnRequestHandler := function(w http.ResponseWriter, r *http.Request) {

        user := create_user_based_on_request(r)

        token := create_token(user)


        // now user will be able to connect to server with token

        known_users_with_tokens[token] = user

    }


    ConnectUsersHandler := function(user1,user2) {

        // you should guard your srv.* members to avoid concurrent read/writes to map

        srv.users_connected_with_each_other[user1] = append(srv.users_connected_with_each_other[user1], user2)

        srv.users_connected_with_each_other[user2] = append(srv.users_connected_with_each_other[user2], user1)

    }


    //initialize your API http.Server

    r := mux.NewRouter()

    r.HandleFunc("/", HomeHandler)

    r.HandleFunc("/products", ProductsHandler)

    r.HandleFunc("/articles", ArticlesHandler)

    r.HandleFunc("/connection_request", ConnRequestHandler) // added

    http.Handle("/", r)

}

打電話(huà)ConnectUsersHandler(user1, user2)讓他們互相交流。


known_users_with_tokens[token] = user 允許用戶(hù)連接到服務(wù)器


您需要實(shí)現(xiàn)異步讀取器/寫(xiě)入器以連接到您的服務(wù)器。保持良好用戶(hù)的有用結(jié)構(gòu)。保護(hù)服務(wù)器結(jié)構(gòu)成員并提供線(xiàn)程安全訪(fǎng)問(wèn)來(lái)更新它。


UDP


看起來(lái)像json.NewEncoder(connection).Encode(&message)并且json.NewDecoder(connection).Decode(&message)是異步和線(xiàn)程安全的。因此,您可以從不同的 goroutine 同時(shí)編寫(xiě)代碼。無(wú)需手動(dòng)同步,耶!


查看完整回答
反對(duì) 回復(fù) 2022-01-10
  • 2 回答
  • 0 關(guān)注
  • 525 瀏覽
慕課專(zhuān)欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢(xún)優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)