GO语言实现多人聊天室

运用go里面的net包中的相关方法来实现一个基于tcp的简单多人聊天室,用一个服务器来管理,主要反馈客户端是否连接成功并显示客户端输入的内容,并且发送给每一个在服务器上连接的客服端

服务器代码

// server
package main


import (
	"fmt"
	"net"
)


var ConnMap map[string]*net.TCPConn


func checkErr(err error) int {
	if err != nil {
		if err.Error() == "EOF" {
			fmt.Println("用户退出")
			return 0
		}
		fmt.Println("发生错误")
		return -1
	}
	return 1
}
func say(tcpConn *net.TCPConn) {
	for {
		data := make([]byte, 256)
		total, err := tcpConn.Read(data)
		if err != nil {
			fmt.Println(string(data[:total]), err)
		} else {
			fmt.Println(string(data[:total]))
		}


		flag := checkErr(err)
		if flag == 0 {
			break
		}
		for _, conn := range ConnMap {
			if conn.RemoteAddr().String() == tcpConn.RemoteAddr().String() {
				continue
			}
			conn.Write(data[:total])
		}
	}
}
func main() {
	//var conn net.TCPConn
	//localAddr :=conn.LocalAddr().String()
	//fmt.Println(localAddr)
	//tcpAddr, _ := net.ResolveTCPAddr("tcp",localAddr)
	tcpAddr, _ := net.ResolveTCPAddr("tcp", "192.168.128.216:8080")
	tcpListen, _ := net.ListenTCP("tcp", tcpAddr)
	ConnMap = make(map[string]*net.TCPConn)
	for {
		tcpConn, _ := tcpListen.AcceptTCP()
		defer tcpConn.Close()
		ConnMap[tcpConn.RemoteAddr().String()] = tcpConn
		fmt.Println("连接客户端信息:", tcpConn.RemoteAddr().String())


		go say(tcpConn)
	}
}

本来打算用系统的LocalAddr()函数来直接调用本地网络地址,但是这里调用一直报格式的错误,所以这里用本地地址直接输在里面,端口是8080//192.168.247.128:8080,也可以改成和客户端相似的代码来进行调用,但鉴于服务器唯一,所以就不做更改了

客户端代码

// client
package main


import (
	"fmt"
	"net"
	"os"
)


var ch chan int = make(chan int)
var nickname string


func reader(conn *net.TCPConn) {
	buff := make([]byte, 256)
	for {
		j, err := conn.Read(buff)
		if err != nil {
			ch <- 1
			break
		}
		fmt.Printf("%s\n", buff[0:j])
	}
}
func main() {
	if len(os.Args) != 2 {
		fmt.Fprintf(os.Stderr, "Usage:%s  host:port", os.Args[0])
		os.Exit(1)
	}
	service := os.Args[1]
	TcpAdd, _ := net.ResolveTCPAddr("tcp", service)
	//TcpAdd, _ := net.ResolveTCPAddr("tcp", "localhost:8080")
	conn, err := net.DialTCP("tcp", nil, TcpAdd)
	if err != nil {
		fmt.Println("服务没打开")
		os.Exit(1)
	}
	defer conn.Close()
	go reader(conn)
	fmt.Println("请输入昵称")
	fmt.Scanln(&nickname)
	fmt.Println("你的昵称是:", nickname)
	//var str string
	for {
		var msg string
		fmt.Scan(&msg)
		fmt.Print("<" + nickname + ">" + "说:")
		//for i, _ := range msg {
		//	fmt.Printf("%c", msg[i])
		//}
		fmt.Println(msg)
		b := []byte("<" + nickname + ">" + "说:" + msg)
		conn.Write(b)
		select {
		case <-ch:
			fmt.Println("server发生错误,请重新连接")
			os.Exit(2)
		default:
		}
	}
}

客户端主要就是向服务器发起连接,然后发送和接收数据,原计划定义一个字符切片来存储读来的数据,但是出现了调用fmt.Println()来输出是时候显示ASCII码的错误,所以改成直接往一个空字符串里面读写,然后再来调用fmt.Println(),显示出正确的字符串

运行服务器

go build server.go

./server

或  go run server.go

运行客户端

go build client.go

./client 服务器地址:端口(上面例子是192.168.247.128:8080)

GO语言实现多人聊天室_第1张图片


你可能感兴趣的:(go,计算机网络)