gpt4 book ai didi

api - Golang - API Server 和 Socket 同时存在

转载 作者:IT王子 更新时间:2023-10-29 01:42:08 26 4
gpt4 key购买 nike

我尝试制作套接字来与我的客户通信。

在对我的 API 发出一些请求后,将创建一个套接字。这意味着,客户端连接自己(仅通过请求),但随后他加入了聊天,因此创建了一个套接字并将其链接到良好的 channel 。

我已经使用过套接字,所以我了解它是如何工作的(C、C++、C#、Java),但是我想做的,根据我在网上看到的,我认为这是可能的,但我不明白如何用 golang 处理它。

我创建第一个服务器:

func main() {
r := mux.NewRouter()
r.HandleFunc("/", HomeHandler)
r.HandleFunc("/products", ProductsHandler)
r.HandleFunc("/articles", ArticlesHandler)
http.Handle("/", r)
}

但是对于套接字,我需要另一个吗?

package main

import "net"
import "fmt"
import "bufio"
import "strings" // only needed below for sample processing

func 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"))
}
}

感谢帮助!

最佳答案

基于我们的聊天讨论。

OVER带有大量伪代码的简化示例

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)
}

调用 ConnectUsersHandler(user1, user2) 让他们相互通信。

known_users_with_tokens[token] = user 允许用户连接到服务器

您需要为与您的服务器的连接实现异步读取器/写入器。保持良好用户的有用结构。保护服务器结构成员并提供线程安全访问以更新它。

UDP

看起来像 json.NewEncoder(connection).Encode(&message)json.NewDecoder(connection).Decode(&message) 是异步和线程安全的。所以你可以同时从不同的 goroutines 编写。无需手动同步,耶!

关于api - Golang - API Server 和 Socket 同时存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37408252/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com