奇妙的go语言(聊天室的开发)
【 声明:版权全部,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
这是一篇关于聊天室开发的博客,原来文章的地址来自于此。这篇文章非常具有代表性,对于代码中的函数部分内容,不想多说什么,仅仅是对它的实现进行一些必要的解说。关于代码,大家既能够在这里阅读,也能够跳转到那篇博客,继续阅读。
package main import( "fmt" "os" "net" ) //////////////////////////////////////////////////////// // //错误检查 // //////////////////////////////////////////////////////// func checkError(err error,info string) (res bool) { if(err != nil){ fmt.Println(info+" " + err.Error()) return false } return true } //////////////////////////////////////////////////////// // //server端接收数据线程 //參数: // 数据连接 conn // 通讯通道 messages // //////////////////////////////////////////////////////// func Handler(conn net.Conn,messages chan string){ fmt.Println("connection is connected from ...",conn.RemoteAddr().String()) buf := make([]byte,1024) for{ lenght, err := conn.Read(buf) if(checkError(err,"Connection")==false){ conn.Close() break } if lenght > 0{ buf[lenght]=0 } //fmt.Println("Rec[",conn.RemoteAddr().String(),"] Say :" ,string(buf[0:lenght])) reciveStr :=string(buf[0:lenght]) messages <- reciveStr } } //////////////////////////////////////////////////////// // //server发送数据的线程 // //參数 // 连接字典 conns // 数据通道 messages // //////////////////////////////////////////////////////// func echoHandler(conns *map[string]net.Conn,messages chan string){ for{ msg:= <- messages fmt.Println(msg) for key,value := range *conns { fmt.Println("connection is connected from ...",key) _,err :=value.Write([]byte(msg)) if(err != nil){ fmt.Println(err.Error()) delete(*conns,key) } } } } //////////////////////////////////////////////////////// // //启动server //參数 // 端口 port // //////////////////////////////////////////////////////// func StartServer(port string){ service:=":"+port //strconv.Itoa(port); tcpAddr, err := net.ResolveTCPAddr("tcp4", service) checkError(err,"ResolveTCPAddr") l,err := net.ListenTCP("tcp",tcpAddr) checkError(err,"ListenTCP") conns:=make(map[string]net.Conn) messages := make(chan string,10) //启动server广播线程 go echoHandler(&conns,messages) for { fmt.Println("Listening ...") conn,err := l.Accept() checkError(err,"Accept") fmt.Println("Accepting ...") conns[conn.RemoteAddr().String()]=conn //启动一个新线程 go Handler(conn,messages) } } //////////////////////////////////////////////////////// // //client发送线程 //參数 // 发送连接 conn // //////////////////////////////////////////////////////// func chatSend(conn net.Conn){ var input string username := conn.LocalAddr().String() for { fmt.Scanln(&input) if input == "/quit"{ fmt.Println("ByeBye..") conn.Close() os.Exit(0); } lens,err :=conn.Write([]byte(username + " Say :::" + input)) fmt.Println(lens) if(err != nil){ fmt.Println(err.Error()) conn.Close() break } } } //////////////////////////////////////////////////////// // //client启动函数 //參数 // 远程ip地址和端口 tcpaddr // //////////////////////////////////////////////////////// func StartClient(tcpaddr string){ tcpAddr, err := net.ResolveTCPAddr("tcp4", tcpaddr) checkError(err,"ResolveTCPAddr") conn, err := net.DialTCP("tcp", nil, tcpAddr) checkError(err,"DialTCP") //启动client发送线程 go chatSend(conn) //開始client轮训 buf := make([]byte,1024) for{ lenght, err := conn.Read(buf) if(checkError(err,"Connection")==false){ conn.Close() fmt.Println("Server is dead ...ByeBye") os.Exit(0) } fmt.Println(string(buf[0:lenght])) } } //////////////////////////////////////////////////////// // //主程序 // //參数说明: // 启动server端: Chat server [port] eg: Chat server 9090 // 启动client: Chat client [Server Ip Addr]:[Server Port] eg: Chat client 192.168.0.74:9090 // //////////////////////////////////////////////////////// func main(){ if len(os.Args)!=3 { fmt.Println("Wrong pare") os.Exit(0) } if os.Args[1]=="server" && len(os.Args)==3 { StartServer(os.Args[2]) } if os.Args[1]=="client" && len(os.Args)==3 { StartClient(os.Args[2]) } }
主要知识点例如以下:
(1)代码中包含了server和client的内容,假设是server,直接输入./chat server 9090就可以,client也非常easy,输入./chat client :9090就好;
(2)假设是client,事实上就包含了两部分内容,一部分是chatSend函数,接受用户的输入;还有一部分是connect到server,接受相关信息;
(3)假设是server,略微复杂一点,有三个部分组成。第一部分就是不停地accept各个client;第二个就是为每个client创立Handler函数,接受client发来的信息;第三个就是echoHandler函数,它的作用就是将从某一用户接受过来的信息广播给其它全部的client,就是这么简单。