一、目的
使用Go语言实现一个服务器端与客户端的聊天室。
软件:Goland,Go1.9
二、思路
1,首先启动服务器端,使用listen_socket函数监听IP地址上的客户端连接;
2,启动客户端,并向服务器端发送数据,发送结束后端口阻塞,等待服务器端的消息;
3,服务器端接收到由客户端发送来的消息;
4,服务器端向客户端发送数据,发送结束后;
5,客户端接收到由服务器端发送来的消息,发送结束后端口阻塞,等待客户端的消息;
6,重复步骤2-5;
7,如果服务器端接收到由客户端发送来的“close"消息后,服务器端关闭与客户端的连接,继续等待下一个客户端的连接;
8,客户端关闭,聊天结束。
三、Go代码实现
Sever端
// One-to-one ChatRoom Severpackage mainimport ( "fmt" "net")//var ConnMap map[string]*net.TCPConnfunc main() { listen_socket, err := net.Listen("tcp", "127.0.0.1:8000") //打开监听接口 if err != nil { //如果有错误 fmt.Println("sever error") } defer listen_socket.Close() //延迟服务器端关闭 fmt.Println("sever is wating ....") for { conn, err := listen_socket.Accept() //监听客户端的端口 if err != nil { fmt.Println("conn fail ...") } fmt.Println("connect client successed") //显示服务器端连接成功 var msg string //声明msg为字符串变量 for { //开始接收客户端发过来的消息 msg = "" //字符串msg初始为空 data := make([]byte, 255) //创建并声明数据变量,为255位 msg_read, err := conn.Read(data) //接收由客户端发来的消息,字节赋值给msg_read,err为错误 if msg_read == 0 || err != nil { //如果读取的消息为0字节或者有错误 fmt.Println("err") } msg_read_str := string(data[0:msg_read]) //将msg_read_str的字节格式转化成字符串形式 if msg_read_str == "close" { //如果接收到的客户端消息为close conn.Write([]byte("close")) break } //fmt.Println(string(data[0:msg_read])) fmt.Println("client say: ", msg_read_str) //接收客户端发来的信息 fmt.Printf("say to client: ") //提示向客户端要说的话 fmt.Scan(&msg) //输入服务器端要对客户端说的话 //conn.Write([]byte("hello client\n")) //msg_write := []byte(msg) conn.Write([]byte(msg)) //把消息发送给客户端 //此处造成服务器端的端口堵塞 } fmt.Println("client Close\n") conn.Close() //关闭连接 }}
Client端
// One-to-one ChatRoom Clientpackage mainimport ( "fmt" "net")func main() { conn, err := net.Dial("tcp", "127.0.0.1:8000") if err != nil { fmt.Println("conn fail...") } defer conn.Close() fmt.Println("connect sever successed") var msg string //声明msg为字符串变量 for { msg = "" //初始化msg为空值 fmt.Printf("say to sever: ") fmt.Scan(&msg) //输入客户端向服务器端要发送的消息 //fmt.Println(msg) //msg_write := []byte(msg) //conn.Write(msg_write) conn.Write([]byte(msg)) //信息转化成字节流形式并向服务器端发送 //此处造成客户端程序端口堵塞 //fmt.Println([]byte(msg)) //等待服务器端发送信息回来 data := make([]byte, 255) msg_read, err := conn.Read(data) if msg_read == 0 || err != nil { fmt.Println("err") } msg_read_str := string(data[0:msg_read]) if msg_read_str == "close" { conn.Write([]byte("close")) break } fmt.Println("sever say:", msg_read_str) } conn.Close()}
四、小结
- Write、Read、conn、Scan函数可造成程序的堵塞;
- 网络中一般是用字节进行数据的传输,所以需要进行格式转换:发送时由字符串转字节;接收时由字节转字符串。