聊天伺服器玩具

elvin5發表於2017-03-31

Server

檔案:main.go
package main

import (
    "log"
)

func init() {
    log.SetFlags(log.Lshortfile)
}

var (
    addr = ":7001"
)

func main() {
    log.Println("running on:", addr)
    err := NewServer(addr).Listen()
    if nil != err {
        log.Fatal(err)
    }
}

檔案:server.go
package main

import (
    "bufio"
    "log"
    "net"
    "strings"
)

type Server struct {
    addr string
}

func NewServer(addr string) *Server {
    return &Server{addr}
}

func (s *Server) Listen() error {
    l, err := net.Listen("tcp", s.addr)
    if nil != err {
        log.Fatalln(err)
    }

    for {
        conn, err := l.Accept()
        if nil != err {
            log.Println(err)
            return err
        }
        log.Println("one client came")

        session, err := s.handleLogin(conn)
        if nil != err {
            log.Println(err)
            return err
        }
        session.Start()
    }

    return nil
}

func (s *Server) handleLogin(conn net.Conn) (*Session, error) {
    userName, err := bufio.NewReader(conn).ReadString('\n')
    if nil != err {
        log.Println(err)
        return nil, err
    }

    _, err = conn.Write([]byte("hi " + userName))
    if nil != err {
        log.Println(err)
        return nil, err
    }

    session := &Session{
        UserName: strings.TrimRight(userName, "\n"),
        Conn:     conn,
    }

    defaultSessionManager.AddSession(session)

    return session, nil
}

檔案:session_manager.go
package main

var (
    defaultSessionManager = &SessionManager{
        Sessions: map[string]*Session{},
    }
)

type SessionManager struct {
    Sessions map[string]*Session
}

func (sm *SessionManager) AddSession(s *Session) {
    sm.Sessions[s.UserName] = s
}

func (sm *SessionManager) GetSession(userName string) *Session {
    return sm.Sessions[userName]
}

檔案:session.go
package main

import (
    "bufio"
    "log"
    "net"
    "strings"
)

type Session struct {
    Conn     net.Conn
    UserName string
}

func NewSession(name string, conn net.Conn) *Session {
    return &Session{
        Conn:     conn,
        UserName: name,
    }
}

func (s *Session) Start() {
    go s.readloop()
}

func (s *Session) Send(b []byte) (int, error) {
    return s.Conn.Write(b)
}

func (s *Session) Read(b []byte) (int, error) {
    return s.Conn.Read(b)
}

func (s *Session) readloop() {
    reader := bufio.NewReader(s.Conn)
    for {
        rec, err := reader.ReadString('\n')
        if nil != err {
            log.Println(err)
            return
        }
        baz := strings.Split(rec, "#")
        if 2 != len(baz) {
            log.Println("wrong msg format")
            return
        }

        userName := baz[0]
        msg := baz[1]

        _, err = defaultSessionManager.GetSession(userName).Send([]byte(s.UserName + ": " + msg))
        if nil != err {
            log.Println(err)
            return
        }
    }
}

Client

檔案:client.go

package main

import (
    "bufio"
    "fmt"
    "log"
    "net"
    "os"
)

func init() {
    log.SetFlags(log.Lshortfile)
}

type Client struct {
    addr string
    Conn net.Conn
}

func NewClient(addr string) *Client {
    return &Client{addr: addr}
}

func (s *Client) Run() {
    conn, err := net.Dial("tcp", s.addr)
    if nil != err {
        log.Fatalln(err)
    }
    s.Conn = conn

    err = s.login()
    if nil != err {
        log.Fatal(err)
    }

    go s.writeloop()
    s.readloop()
}

func (s *Client) login() error {
    _, err := s.Conn.Write([]byte(*userName + "\n"))
    if nil != err {
        log.Println(err)
        return err
    }

    return nil
}
func (s *Client) readloop() error {
    for {
        bin := make([]byte, 10, 10)
        n, err := s.Conn.Read(bin)
        if nil != err {
            log.Println(err)

            err = s.Conn.Close()
            if nil != err {
                log.Println(err)
                return err
            }

            return err
        }
        fmt.Print(string(bin[:n]))
    }

    return nil
}
func (s *Client) writeloop() error {
    reader := bufio.NewReader(os.Stdin)
    for {
        input, err := reader.ReadString('\n')
        if nil != err {
            log.Println(err)
            return err
        }

        _, err = s.Conn.Write([]byte(input))
        if nil != err {
            log.Println(err)
            err = s.Conn.Close()
            if nil != err {
                log.Println(err)
                return err
            }

            return err
        }
    }

    return nil
}

檔案:main.go

package main

import (
    "flag"
    "log"
)

var (
    addr = ":7001"
)

var (
    userName = flag.String("name", "", "user name")
)

func init() {
    flag.Parse()
}

func main() {
    if "" == *userName {
        log.Fatal("input your name")
    }
    NewClient(addr).Run()
}

https://github.com/elvin-du/dim

相關文章