服务器
服务器就是有一个持续获取连接的动作,for循环实现,for循环开启处理消息的协程,处理消息的函数,接收消息并将消息写入缓冲信道。还有一个广播函数,用来将收到的消息发给所有与服务器连接的地址。
package main
import (
"net"
"os"
)
func main() {
port := ":8080" //端口
Start(port)
}
func Start(p string) {
tcpAddr, err := net.ResolveTCPAddr("tcp", p)
if err != nil {
os.Exit(0)
return
}
listener,err:= net.ListenTCP("tcp",tcpAddr) //布置监听
if err != nil {
os.Exit(0)
return
}
conns := make(map[string]net.Conn) //连接池,用来保存所有人的数据
message := make(chan string,10) //缓冲消息信道
//时刻监听
for{
conn,err:= listener.AcceptTCP() //返回网络连接
if err!=nil{
os.Exit(0)
fmt.Println("Acception failed!")
continue
}
conns[conn.RemoteAddr().String()] = conn //将新连接存进map,键是他的远程地址
go HandlerMessage(conn,message) //启动接收信息协程
}
}
//广播到所有conn 除了发出消息的
func BroadCast(conns map[string]net.Conn,mess chan int) {
for {
mess := <-messages //读取信道信息
for k, v := range conns {
_, err := v.Write([]byte(mess))
if err != nil {
delete(conns, k)
v.Close()
continue
}
v.Write([]byte("BroadCast"))
}
}
}
//处理收的的消息
func HandlerMessage(conn net.Conn,mess chan string) {
//for循环持续接收conn连接发来的信息
for{
buf := make([]byte,1024)
length,err:=conn.Read(&buf) //读取消息
if err != nil {
conn.Close()
delete(cns, conn.RemoteAddr().String())
break
}
mess<-string(buf[0:length]) //接收到的信息写入信道
fmt.Println(string(buf[0:length]))
}
}
客户端
客户端有一个开始的函数,用来连接服务器,开启协程,读取服务器发来的消息。发送消息的函数,接收输入消息后用conn.Write()发送消息。
package main
import (
"fmt"
"log"
"net"
"os"
)
func main() {
Start(os.Args[1]) //os.Args是存储命令行的
}
func Start(addr string) {
Tcpaddr, err := net.ResolveTCPAddr("tcp4", addr) //获取tcp
if err != nil {
log.Printf("Address error: %v\n", err)
return
}
conn, err := net.DialTCP("tcp", nil, Tcpaddr) //连接服务器
if err != nil {
log.Printf("Dial to Server failed! %v\n", err)
return
}
//启动发送消息协程
go SendMessage(conn)
buf := make([]byte, 1024)
for {
length, err := conn.Read(buf) //读取服务器发来的消息
if err != nil {
log.Printf("receive server's message failed! %v\n", err)
conn.Close() //关闭
os.Exit(0)
}
fmt.Println(string(buf[0:length]))
}
}
func SendMessage(conn net.Conn) {
username := conn.LocalAddr().String()
for {
var in string
fmt.Scanln(&in) //接收输入的消息到in变量
if len(in) > 0 {
msg := username + "say:" + in
_, err := conn.Write([]byte(msg)) //发送消息
if err != nil {
conn.Close()
break
}
}
}
}