即时通讯系统
1.基础server构建
- 创建一个Server的结构体,结构体应该包含服务端的IP和端口
- 写一个创建Server的方法
- 创建一个启动Server函数
- 创建一个业务链接函数
server.go
package main
import (
"fmt"
"net"
)
type Server struct{
Ip string
Port int
}
//创建Server对象
func NewServer(ip string,port int)*Server{
server:=&Server{
Ip:ip,
Port:port,
}
return server
}
//启动Server服务函数
func(this *Server)Start(){
listener,err:=net.Listen("tcp",fmt.Sprintf("%s:%d",this.Ip,this.Port))
if err!=nil{
fmt.Plrintln("Accept Error:",err)
return
}
for{
conn,err:=listener.Accept()
if err!=nil{
fmt.Println("Listener Accept err:",err)
continue
}
go this.Handler(conn)
}
//Handler函数 业务函数
func (this *Server)Handler(conn net.Conn){
fmt.Println("业务链接成功!")
}
}
main.go
package main
func main(){
server:=NewServer("127.0.0.1",8888)
server.Start()
}
2.用户上线及广播功能
- user.go
- 创建User结构体
- 创建User对象
- 监听User对应channel消息
- server.go
- Server结构体新增在线用户表和Message管道属性
- 在处理客户端上线的Handler函数中根据端口创建用户并添加到在线用户表中
- Handler函数中添加广播消息函数,广播用户上线的消息
- 添加广播消息的函数
- 添加广播消息channel方法
- 用一个goroutine单独监听Message管道
user.go
package main
import "net"
type User struct{
Name string
Addr string
C chan string
conn net.Conn
}
//创建User对象
func NewUser(conn net.Conn)*User{
userAddr:=conn.RemoteAddr().String()
user:=&User{
Name:userAddr,
Addr:userAddr,
C :make(chan string),
conn:conn
}
//监听当前user的channel消息
go user.ListenMessage()
return user
}
//监听当前用户channel管道消息函数,一旦有消息,就直接发送给对端客户端
func (this *User)ListenMessage(){
for {
msg:=<-this.C
this.conn.Write([]byte(msg+"\n"))
}
}
server.go
package main
type Server struct {
Ip string
Port int
Message chan string
OnlineMap map[string]*User
mapLock sync.RWMutex
}
//创建一个Server对象
func NewServer(ip string ,port int)*Server{
server:=&Server{
Ip:ip,
Port:port,
Message:make(chan string),
OnlineMap:make(map[string]*User)
}
return server
}
//创建启动函数
func (this *Server)Start(){
listener,err:=net.Listen("tcp",fmt.Sprintf("%s:%d",this.IP,this.Port))
if err!=nil{
fmt.Println("net.Listen err:",err)
return
}
defer listener.Close()
go this.ListenMessager()
for {
conn,err:=listener.Accept()
if err!=nil{
fmt.Println("Listenner accept err:",err)
continue
}
go this.Handler(conn)
}
}
//创建Handler函数
func (this *Server)Handler(conn net.Conn){
user:=NewUser(conn)
this.mapLock.Lock()
this.OnlineMap[user.Name]=user
this.mapLock.Unlock()
//广播当前用户上线的消息
this.BroadCast(user,"已上线")
//阻塞当前handler
select{}
}
//监听Message广播消息channel的goroutine,一旦有消息就发送给全部的在线User
func (this *Server)ListenMessager(){
msg:=<-this.Message
this.mapLock.Lock()
for _,cli:=range OnlineMap{
cli.C<-msg
}
this.mapLock.Unlock()
}
//广播函数
func (this *Server)BroadCast(user *User,msg string){
sendMsg:="["+user.Addr+"]"+user.name+":"+msg
this.Message<-sendMsg
}
标签:string,err,系统,即时通讯,Server,golang,User,go,conn
From: https://www.cnblogs.com/Weber-security/p/17254960.html