go示例3:模拟简单游戏服务器

来源:互联网 发布:关键字排名优化软件 编辑:程序博客网 时间:2024/06/06 03:33

server.go

package ipcimport ("encoding/json""fmt")type Request struct {Method string `json:"method"`Params string `json:"params"`}type Response struct {Code string `json:"code"`Body string `json:"body"`}type Server interface {Name() stringHandle(method, params string) *Response}type IpcServer struct {Server}func NewIpcServer(server Server) *IpcServer {return &IpcServer{server}}func (server *IpcServer) Connect() chan string {session := make(chan string, 0)go func(c chan string) {for {request := <-cif request == "CLOSE" {break}var req Requesterr := json.Unmarshal([]byte(request), &req)if err != nil {fmt.Println("Invalid request format:", request)return}resp := server.Handle(req.Method, req.Params)b, err := json.Marshal(resp)c <- string(b)}fmt.Println("Session closed.")}(session)fmt.Println("A new session has been created successfully.")return session}
client.go

package ipcimport ("encoding/json")type IpcClient struct {conn chan string}func NewIpcClient(server *IpcServer) *IpcClient {c := server.Connect()return &IpcClient{c}}func (client *IpcClient) Call(method, params string) (resp *Response, err error) {req := &Request{method, params}var b []byteb, err = json.Marshal(req)if err != nil {return}client.conn <- string(b)str := <-client.connvar resp1 Responseerr = json.Unmarshal([]byte(str), &resp1)resp = &resp1return}func (client *IpcClient) Close() {client.conn <- "CLOSE"}
ipc_test.go
package ipcimport ("testing")type EchoServer struct {}func (server *EchoServer) Handle(method, params string) *Response {return &Response{"OK", "ECHO: " + method + " ~ " + params}}func (server *EchoServer) Name() string {return "EchoServer"}func TestIpc(t *testing.T) {server := NewIpcServer(&EchoServer{})client1 := NewIpcClient(server)client2 := NewIpcClient(server)resp1, _ := client1.Call("foo", "From Client1")resp2, _ := client1.Call("foo", "From Client2")if resp1.Body != "ECHO: foo ~ From Client1" ||resp2.Body != "ECHO: foo ~ From Client2" {t.Error("IpcClient.Call failed. resp1:", resp1, "resp2:", resp2)}client1.Close()client2.Close()}
player.go

package cgimport "fmt"type Player struct {Name  stringLevel intExp   intRoom  intmq chan *Message}func NewPlayer() *Player {m := make(chan *Message, 1024)player := &Player{"", 0, 0, 0, m}go func(p *Player) {for {msg := <-p.mqfmt.Println(p.Name, "received message:", msg.Content)}}(player)return player}
center.go

package cgimport ("encoding/json""errors""sync""ipc")var _ ipc.Server = &CenterServer{}type Message struct {From    string `json:"from"`To      string `json:"to"`Content string `json:"content"`}type CenterServer struct {servers map[string]ipc.Serverplayers []*Playerrooms   []*intmutex   sync.RWMutex}func NewCenterServer() *CenterServer {servers := make(map[string]ipc.Server)players := make([]*Player, 0)return &CenterServer{servers: servers, players: players}}func (server *CenterServer) addPlayer(params string) error {player := NewPlayer()err := json.Unmarshal([]byte(params), &player)if err != nil {return err}server.mutex.Lock()defer server.mutex.Unlock()server.players = append(server.players, player)return nil}func (server *CenterServer) removePlayer(params string) error {server.mutex.Lock()defer server.mutex.Unlock()for i, v := range server.players {if v.Name == params {if len(server.players) == 1 {server.players = make([]*Player, 0)} else if i == len(server.players)-1 {server.players = server.players[:i]} else if i == 0 {server.players = server.players[1:]} else {server.players = append(server.players[:i-1], server.players[:i+1]...)}return nil}}return errors.New("Player not found.")}func (server *CenterServer) listPlayer(params string) (players string, err error) {server.mutex.RLock()defer server.mutex.RUnlock()if len(server.players) > 0 {b, _ := json.Marshal(server.players)players = string(b)} else {err = errors.New("No player online")}return}func (server *CenterServer) broadcast(params string) error {var message Messageerr := json.Unmarshal([]byte(params), &message)if err != nil {return err}server.mutex.Lock()defer server.mutex.Unlock()if len(server.players) > 0 {for _, player := range server.players {p := &messageplayer.mq <- p}} else {err = errors.New("No player online.")}return err}func (server *CenterServer) Handle(method, params string) *ipc.Response {switch method {case "addplayer":err := server.addPlayer(params)if err != nil {return &ipc.Response{Code: err.Error()}}case "removeplayer":err := server.removePlayer(params)if err != nil {return &ipc.Response{Code: err.Error()}}case "listplayer":players, err := server.listPlayer(params)if err != nil {return &ipc.Response{Code: err.Error()}}return &ipc.Response{"200", players}case "broadcast":err := server.broadcast(params)if err != nil {return &ipc.Response{Code: "200"}}default:return &ipc.Response{Code: "404", Body: method + ":" + params}}return &ipc.Response{Code: "200"}}func (server *CenterServer) Name() string {return "CenterServer"}
centerclient.go

package cgimport ("encoding/json""errors""ipc")type CenterClient struct {*ipc.IpcClient}func (client *CenterClient) AddPlayer(player *Player) error {b, err := json.Marshal(*player)if err != nil {return err}resp, err := client.Call("addplayer", string(b))if err == nil && resp.Code == "200" {return nil}return err}func (client *CenterClient) RemovePlayer(name string) error {ret, _ := client.Call("removeplayer", name)if ret.Code == "200" {return nil}return errors.New(ret.Code)}func (client *CenterClient) ListPlayer(params string) (ps []*Player, err error) {resp, _ := client.Call("listplayer", params)if resp.Code != "200" {err = errors.New(resp.Code)return}err = json.Unmarshal([]byte(resp.Body), &ps)return}func (client *CenterClient) Broadcast(message string) error {m := &Message{Content: message}b, err := json.Marshal(m)if err != nil {return err}resp, _ := client.Call("broadcast", string(b))if resp.Code == "200" {return nil}return errors.New(resp.Code)}
cgss.go

package mainimport ("bufio""fmt""os""strconv""strings""cg""ipc")var centerClient *cg.CenterClientfunc startCenterService() error {server := ipc.NewIpcServer(&cg.CenterServer{})client := ipc.NewIpcClient(server)centerClient = &cg.CenterClient{client}return nil}func Help(args []string) int {fmt.Println(`Commands:login <username><level><exp>logout <username>send <message>listplayerquit(q)help(h)`)return 0}func Quit(args []string) int {return 1}func Logout(args []string) int {if len(args) != 2 {fmt.Println("USAGE: logout <username>")return 0}centerClient.RemovePlayer(args[1])return 0}func Login(args []string) int {if len(args) != 4 {fmt.Println("USAGE: login <username><level><>exp")return 0}level, err := strconv.Atoi(args[2])if err != nil {fmt.Println("Invalid Parameter: <level> should be an integer.")return 0}exp, err := strconv.Atoi(args[3])if err != nil {fmt.Println("Invalid Parameter: <exp> should be an integer.")return 0}player := cg.NewPlayer()player.Name = args[1]player.Level = levelplayer.Exp = experr = centerClient.AddPlayer(player)if err != nil {fmt.Println("Failed adding player", err)}return 0}func ListPlayer(args []string) int {ps, err := centerClient.ListPlayer("")if err != nil {fmt.Println("Failed. ", err)} else {for i, v := range ps {fmt.Println(i+1, ":", v)}}return 0}func Send(args []string) int {message := strings.Join(args[1:], " ")err := centerClient.Broadcast(message)if err != nil {fmt.Println("Failed.", err)}return 0}func GetCommandHandlers() map[string]func(args []string) int {return map[string]func([]string) int{"help":       Help,"h":          Help,"quit":       Quit,"q":          Quit,"login":      Login,"logout":     Logout,"listplayer": ListPlayer,"send":       Send,}}func main() {fmt.Println("Casual Game Server Solution")startCenterService()Help(nil)r := bufio.NewReader(os.Stdin)handlers := GetCommandHandlers()for {fmt.Print("Comand> ")b, _, _ := r.ReadLine()line := string(b)tokens := strings.Split(line, " ")if handler, ok := handlers[tokens[0]]; ok {ret := handler(tokens)if ret != 0 {break}} else {fmt.Println("Unknown command:", tokens[0])}}}








0 0
原创粉丝点击