2,190
社区成员
发帖
与我相关
我的任务
分享
package main
import (
"fmt"
"net"
"os"
"time"
"unicode/utf8"
)
func main() {
if len(os.Args) != 3 {
fmt.Print("参数不正确,无法启动!")
//os.Exit(0)
}
if os.Args[1] == "server" {
Server(os.Args[2])
}
if os.Args[1] == "client" {
Client(os.Args[2])
}
time.Sleep(5 * time.Second)
}
//错误检查
func checkError(err error, message string) (res bool) {
if err != nil {
fmt.Println(message + " " + err.Error())
return false
}
return true
}
func Server(port string) {
service := ":" + port
l, err := net.Listen("tcp", service)
checkError(err, "Listen")
conns := make(map[string]net.Conn) //创建连接池 ip=>conn
msgs := make(chan string, 100) //创建消息池 就是chan;
//启动广播线程
go Broadcast(&conns, msgs) // ['brɔdkæst] 广播
fmt.Println("服务端已经启动,正在监听......")
for {
//接受连接
conn, err := l.Accept()
checkError(err, "接受连接异常")
//增加字典 IP-> Conn
conns[conn.RemoteAddr().String()] = conn
//启动一个线程 用于该连接的消息读取到信道;
go Getmsg(conn, msgs)
}
}
//获取消息
func Getmsg(conn net.Conn, msgs chan string) {
msg := make([]byte, 1024)
for {
//读取消息
length, err := conn.Read(msg)
if checkError(err, "Getmsg") == false {
conn.Close()
break
}
//将消息存放到信道
msgs <- string(msg[0:length])
}
}
//广播消息
func Broadcast(conns *map[string]net.Conn, msgs chan string) {
for {
// 阻塞读取信道内容
msg := <-msgs
fmt.Println(msg)
for key, conn := range *conns {
//向客户端发送消息
_, err := conn.Write([]byte(msg))
if err != nil {
fmt.Println(err.Error())
//若写入失败,说明断开,删除该连接
delete(*conns, key)
}
}
}
}
//客户端;
func Client(address string) {
fmt.Print(100)
//创建拨号器
conn, err := net.Dial("tcp4", address)
checkError(err, "Dial")
//启动客户端发送线程
go ClientSend(conn)
//轮询接受消息
for {
msg := make([]byte, 1024) //存放接受到消息,固定byte一次到位,省的底层数组可能变动;
length, err := conn.Read(msg)
if checkError(err, "Connection") == false {
conn.Close()
fmt.Println("与服务器断开")
os.Exit(0)
}
fmt.Println(string(msg[0:length]))
}
}
//发送消息
func ClientSend(conn net.Conn) {
//用户名
username := conn.LocalAddr().String()
var input string
for {
//获取命令
fmt.Scanln(&input)
//退出客户端
if input == "/quit" {
fmt.Println("1秒后关闭客户端..")
//os.Sleep(1)
conn.Close()
os.Exit(0)
}
//发送消息
_, err := conn.Write([]byte(username + " Say:: " + input))
if err != nil {
fmt.Println(err.Error())
conn.Close()
break
}
}
}