0
点赞
收藏
分享

微信扫一扫

线性代数(二) 矩阵及其运算

一、用户业务层的封装:

重点关注,user的结构体中继承server中的信息,同时具备了server中所有方法

 二、代码内容:

2.1main.go

package main

func main() {
server := NewServer("127.0.0.1", 8000)
server.Start()
}

 2.2server.go

package main

import (
"fmt"
"io"
"net"
"sync"
)

type Server struct {
Ip string
Port int

//在线用户的列表
OnlineMap map[string]*User
mapLock sync.RWMutex

//消息广播的channel
Message chan string
}

// 创建一个server的接口
func NewServer(ip string, port int) *Server {
server := &Server{
Ip: ip,
Port: port,
OnlineMap: make(map[string]*User),
Message: make(chan string),
}

return server
}

// 监听Message广播消息channel的goroutine,一旦有消息就发送给全部的在线User
func (this *Server) ListenMessager() {
for {
msg := <-this.Message

//将msg发送给全部的在线User
this.mapLock.Lock()
for _, cli := range this.OnlineMap {
cli.C <- msg
}
this.mapLock.Unlock()
}
}

// 广播消息的方法
func (this *Server) BroadCast(user *User, msg string) {
sendMsg := "[" + user.Addr + "]" + user.Name + ":" + msg

this.Message <- sendMsg
}

func (this *Server) Handler(conn net.Conn) {
//...当前链接的业务
//fmt.Println("链接建立成功")

user := NewUser(conn, this)

user.Online()

//接受客户端发送的消息
go func() {
buf := make([]byte, 4096)
for {
n, err := conn.Read(buf)
if n == 0 {
user.Offline()
return
}

if err != nil & io.EOF {
fmt.Println("Conn Read err:", err)
return
}

//提取用户的消息(去除'\n')
msg := string(buf[:n-1])

//用户针对msg进行消息处理
user.DoMessage(msg)
}
}()

//当前handler阻塞
select {}
}

// 启动服务器的接口
func (this *Server) Start() {
//socket listen
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", this.Ip, this.Port))
if err != nil {
fmt.Println("net.Listen err:", err)
return
}
//close listen socket
defer listener.Close()

//启动监听Message的goroutine
go this.ListenMessager()

for {
//accept
conn, err := listener.Accept()
if err != nil {
fmt.Println("listener accept err:", err)
continue
}

//do handler
go this.Handler(conn)
}
}

2.3user.go

package main

import "net"

type User struct {
Name string
Addr string
C chan string
conn net.Conn

server *Server
}

// 创建一个用户的API
func NewUser(conn net.Conn, server *Server) *User {
userAddr := conn.RemoteAddr().String()

user := &User{
Name: userAddr,
Addr: userAddr,
C: make(chan string),
conn: conn,

server: server,
}

//启动监听当前user channel消息的goroutine
go user.ListenMessage()

return user
}

// 用户的上线业务
func (this *User) Online() {

//用户上线,将用户加入到onlineMap中
this.server.mapLock.Lock()
this.server.OnlineMap[this.Name] = this
this.server.mapLock.Unlock()

//广播当前用户上线消息
this.server.BroadCast(this, "已上线")
}

// 用户的下线业务
func (this *User) Offline() {

//用户下线,将用户从onlineMap中删除
this.server.mapLock.Lock()
delete(this.server.OnlineMap, this.Name)
this.server.mapLock.Unlock()

//广播当前用户上线消息
this.server.BroadCast(this, "下线")

}

// 用户处理消息的业务
func (this *User) DoMessage(msg string) {
this.server.BroadCast(this, msg)
}

// 监听当前User channel的 方法,一旦有消息,就直接发送给对端客户端
func (this *User) ListenMessage() {
for {
msg := <-this.C

this.conn.Write([]byte(msg + "\n"))
}
}

三、客户登录测试

3.1服务端登录【运行代码】

3.2客户端登录测试

举报

相关推荐

0 条评论