您现在的位置是:首页 >技术交流 >go服务器网站首页技术交流
go服务器
简介go服务器
实现一个复杂的服务器需要考虑多个方面,包括网络通信、并发处理、安全性、持久化存储、服务监控等。以下是一个用 Go 语言实现的复杂服务器的示例代码,包含详细的注释说明。这个服务器支持 HTTP 和 WebSocket 通信,具备用户认证、日志记录、并发处理和简单的数据存储功能。
Go 代码示例
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"sync"
"time"
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
)
// User 数据结构,用于存储用户信息
type User struct {
Username string `json:"username"`
Password string `json:"password"`
}
// Message 数据结构,用于 WebSocket 消息传递
type Message struct {
From string `json:"from"`
Content string `json:"content"`
}
// ServerState 用于存储服务器状态信息
type ServerState struct {
Users map[string]User
Online map[*websocket.Conn]string
mu sync.RWMutex
Message chan Message
}
// NewServerState 创建一个新的服务器状态
func NewServerState() *ServerState {
return &ServerState{
Users: make(map[string]User),
Online: make(map[*websocket.Conn]string),
Message: make(chan Message, 10),
}
}
// RegisterUser 注册用户
func (s *ServerState) RegisterUser(username, password string) bool {
s.mu.Lock()
defer s.mu.Unlock()
if _, exists := s.Users[username]; exists {
return false
}
s.Users[username] = User{Username: username, Password: password}
return true
}
// AuthenticateUser 用户认证
func (s *ServerState) AuthenticateUser(username, password string) bool {
s.mu.RLock()
defer s.mu.RUnlock()
user, exists := s.Users[username]
return exists && user.Password == password
}
// BroadcastMessage 广播消息给所有在线用户
func (s *ServerState) BroadcastMessage(msg Message) {
s.mu.RLock()
defer s.mu.RUnlock()
for conn := range s.Online {
err := conn.WriteJSON(msg)
if err != nil {
log.Printf("Error sending message to %s: %v", s.Online[conn], err)
conn.Close()
delete(s.Online, conn)
}
}
}
// WebSocketHandler WebSocket 连接处理器
func (s *ServerState) WebSocketHandler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println(err)
return
}
defer conn.Close()
// 用户登录
var loginData struct {
Username string `json:"username"`
Password string `json:"password"`
}
if err := conn.ReadJSON(&loginData); err != nil {
log.Println("Error reading login data:", err)
return
}
if !s.AuthenticateUser(loginData.Username, loginData.Password) {
log.Println("Authentication failed")
return
}
// 将用户添加到在线列表
s.mu.Lock()
s.Online[conn] = loginData.Username
s.mu.Unlock()
// 广播用户上线消息
s.BroadcastMessage(Message{From: loginData.Username, Content: "has joined the chat"})
// 处理接收到的消息
for {
var msg Message
if err := conn.ReadJSON(&msg); err != nil {
log.Printf("Error reading message from %s: %v", loginData.Username, err)
break
}
msg.From = loginData.Username
s.BroadcastMessage(msg)
}
// 用户下线
s.mu.Lock()
delete(s.Online, conn)
s.mu.Unlock()
s.BroadcastMessage(Message{From: loginData.Username, Content: "has left the chat"})
}
// HTTPHandler HTTP 请求处理器
func (s *ServerState) HTTPHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.Method {
case http.MethodGet:
// 返回在线用户列表
s.mu.RLock()
onlineUsers := make([]string, 0, len(s.Online))
for _, username := range s.Online {
onlineUsers = append(onlineUsers, username)
}
s.mu.RUnlock()
json.NewEncoder(w).Encode(onlineUsers)
case http.MethodPost:
// 注册用户
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, "Invalid request", http.StatusBadRequest)
return
}
if s.RegisterUser(user.Username, user.Password) {
w.WriteHeader(http.StatusCreated)
} else {
http.Error(w, "User already exists", http.StatusConflict)
}
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
// MessageHandler 消息处理协程
func (s *ServerState) MessageHandler() {
for msg := range s.Message {
s.BroadcastMessage(msg)
}
}
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func main() {
// 创建服务器状态
serverState := NewServerState()
// 注册 HTTP 和 WebSocket 路由
r := mux.NewRouter()
r.HandleFunc("/ws", serverState.WebSocketHandler).Methods(http.MethodGet)
r.HandleFunc("/users", serverState.HTTPHandler).Methods(http.MethodGet, http.MethodPost)
// 启动消息处理协程
go serverState.MessageHandler()
// 启动 HTTP 服务器
log.Println("Starting server on :8080")
if err := http.ListenAndServe(":8080", r); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
}
代码说明
用户管理:
支持用户注册和登录,用户信息存储在内存中。
使用简单的用户名和密码进行认证。
WebSocket 通信:
支持 WebSocket 连接,用户可以通过 WebSocket 发送和接收消息。
广播消息给所有在线用户。
HTTP 接口:
提供 HTTP 接口用于注册用户和获取在线用户列表。
并发处理:
使用 sync.RWMutex 保护共享数据,确保线程安全。
使用通道和协程处理消息广播。
日志记录:
使用 log 包记录服务器运行日志。
这个服务器是一个较为复杂的示例,涵盖了基本的网络通信、用户认证和并发处理功能。你可以根据实际需求进一步扩展,例如添加数据库支持、更复杂的用户权限管理等。
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。