├── README.md ├── client.go └── server.go /README.md: -------------------------------------------------------------------------------- 1 | golang-udp-chat 2 | =============== 3 | 4 | 用golang写的小的基于udp协议的聊天室程序 5 | 6 | /////////////////////////////////////////// 7 | 非常简单 8 | blog:http://0x55aa.sinaapp.com 9 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | "net" 6 | "os" 7 | "time" 8 | "strings" 9 | ) 10 | 11 | type Client struct{ 12 | conn *net.UDPConn 13 | gkey bool //用来判断用户退出 14 | userID int 15 | userName string 16 | sendMessages chan string 17 | receiveMessages chan string 18 | 19 | } 20 | 21 | 22 | 23 | //突然加上一个函数,不加就需要去掉for或者多设一个变量, 24 | func (c *Client) func_sendMessage(sid int,msg string){ 25 | str := fmt.Sprintf("###%d##%d##%s##%s###", sid, c.userID,c.userName,msg) 26 | _,err := c.conn.Write([]byte(str)) 27 | checkError(err,"func_sendMessage") 28 | } 29 | 30 | //send 31 | func (c *Client) sendMessage() { 32 | for c.gkey { 33 | msg := <- c.sendMessages 34 | //str := fmt.Sprintf("(%s) \n %s: %s", nowTime(), c.userName,msg) 35 | str := fmt.Sprintf("###2##%d##%s##%s###", c.userID,c.userName,msg) 36 | _,err := c.conn.Write([]byte(str)) 37 | checkError(err,"sendMessage") 38 | } 39 | 40 | } 41 | 42 | //接收 43 | func (c *Client) receiveMessage() { 44 | var buf [512]byte 45 | for c.gkey { 46 | n,err := c.conn.Read(buf[0:]) 47 | checkError(err, "receiveMessage") 48 | c.receiveMessages <- string(buf[0:n]) 49 | } 50 | 51 | } 52 | //获得输入并处理之,这里有Println 53 | func (c *Client) getMessage() { 54 | var msg string 55 | for c.gkey { 56 | fmt.Println("msg: ") 57 | _,err := fmt.Scanln(&msg) 58 | checkError(err, "getMessage") 59 | if msg == ":quit" { 60 | c.gkey = false 61 | }else{ 62 | c.sendMessages <- encodeMessage(msg) 63 | } 64 | } 65 | } 66 | //打印,这里有Println 67 | func (c *Client) printMessage() { 68 | //var msg string 69 | for c.gkey { 70 | msg := <- c.receiveMessages 71 | fmt.Println(msg) 72 | } 73 | } 74 | //转换需要发送的字符串 75 | func encodeMessage(msg string) (string) { 76 | return strings.Join(strings.Split(strings.Join(strings.Split(msg,"\\"),"\\\\"),"#"),"\\#") 77 | 78 | } 79 | func nowTime() string { 80 | return time.Now().String() 81 | } 82 | func checkError(err error, funcName string){ 83 | if err != nil{ 84 | fmt.Fprintf(os.Stderr,"Fatal error:%s-----in func:%s",err.Error(), funcName) 85 | os.Exit(1) 86 | } 87 | } 88 | func main(){ 89 | if len(os.Args) != 2{ 90 | fmt.Fprintf(os.Stderr, "Usage:%s host:port", os.Args[0]) 91 | os.Exit(1) 92 | } 93 | service := os.Args[1] 94 | udpAddr, err := net.ResolveUDPAddr("udp4",service) 95 | checkError(err,"main") 96 | 97 | var c Client 98 | c.gkey = true 99 | c.sendMessages = make(chan string) 100 | c.receiveMessages = make(chan string) 101 | 102 | fmt.Println("input id: ") 103 | _,err = fmt.Scanln(&c.userID) 104 | checkError(err,"main") 105 | fmt.Println("input name: ") 106 | _,err = fmt.Scanln(&c.userName) 107 | checkError(err,"main") 108 | 109 | c.conn,err = net.DialUDP("udp",nil,udpAddr) 110 | checkError(err,"main") 111 | //fmt.Println(c) 112 | defer c.conn.Close() 113 | 114 | 115 | //发送进入聊天室消息,类型1,###1##uid##uName##进入聊天室### 116 | //messagestr := fmt.Sprintf("###1##%d##%s###", c.userID, c.userName) 117 | //_,err = c.conn.Write([]byte(messagestr)) 118 | //checkError(err) 119 | c.func_sendMessage(1,c.userName + "进入聊天室") 120 | 121 | //go c.getMessage() 122 | go c.printMessage() 123 | go c.receiveMessage() 124 | 125 | go c.sendMessage() 126 | c.getMessage() 127 | 128 | c.func_sendMessage(3,c.userName + "离开聊天室") 129 | fmt.Println("退出成功!") 130 | 131 | 132 | os.Exit(0) 133 | } 134 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | "net" 6 | "os" 7 | "time" 8 | "strings" 9 | "strconv" 10 | ) 11 | 12 | const( 13 | port string = ":1200" 14 | ) 15 | 16 | type Server struct{ 17 | conn *net.UDPConn // 18 | messages chan string //接受到的消息 19 | clients map [int]Client 20 | } 21 | 22 | type Client struct{ 23 | userID int 24 | userName string 25 | userAddr *net.UDPAddr 26 | 27 | } 28 | type Message struct{ 29 | status int 30 | userID int 31 | userName string 32 | content string 33 | } 34 | 35 | func (s *Server) handleMessage(){ 36 | var buf [512]byte 37 | 38 | fmt.Println("1\n") 39 | n, addr, err := s.conn.ReadFromUDP(buf[0:]) 40 | if err != nil{ 41 | return 42 | } 43 | fmt.Println("2\n") 44 | //分析消息 45 | msg := string(buf[0:n]) 46 | fmt.Println(msg) 47 | m := s.analyzeMessage(msg) 48 | switch m.status{ 49 | //进入聊天室消息 50 | case 1: 51 | var c Client 52 | c.userAddr = addr 53 | c.userID = m.userID 54 | c.userName = m.userName 55 | s.clients[c.userID] = c //添加用户 56 | s.messages <- msg 57 | fmt.Println("3") 58 | //用户发送消息 59 | case 2: 60 | s.messages <- msg 61 | //client发来的退出消息 62 | case 3: 63 | delete(s.clients, m.userID) 64 | s.messages <- msg 65 | default: 66 | fmt.Println("未识别消息", msg) 67 | } 68 | 69 | //fmt.Println(n,addr,string(buf[0:n])) 70 | 71 | 72 | } 73 | //这里还要判断一下数组的长度, 74 | func (s *Server) analyzeMessage(msg string) (m Message) { 75 | //var m Message 76 | s1 := strings.Split(msg,"###") 77 | 78 | s2 := strings.Split(s1[1],"##") 79 | //fmt.Println(s2) 80 | switch s2[0]{ 81 | case "1": 82 | m.status,_ = strconv.Atoi(s2[0]) 83 | fmt.Println("44") 84 | m.userID,_ = strconv.Atoi(s2[1]) 85 | m.userName = s2[2] 86 | fmt.Println(m) 87 | return 88 | case "2": 89 | m.status,_ = strconv.Atoi(s2[0]) 90 | m.userID,_ = strconv.Atoi(s2[1]) 91 | m.content = s2[2] 92 | return 93 | case "3": 94 | m.status,_ = strconv.Atoi(s2[0]) 95 | m.userID,_ = strconv.Atoi(s2[1]) 96 | return 97 | default: 98 | fmt.Println("未识别消息", msg) 99 | return 100 | } 101 | return 102 | } 103 | func (s *Server) sendMessage() { 104 | for{ 105 | msg := <- s.messages 106 | daytime := time.Now().String() 107 | sendstr := msg + daytime 108 | fmt.Println(00,sendstr) 109 | for _,c := range s.clients { 110 | fmt.Println(c) 111 | n,err := s.conn.WriteToUDP([]byte(sendstr),c.userAddr) 112 | fmt.Println(n,err) 113 | } 114 | } 115 | 116 | } 117 | 118 | func checkError(err error){ 119 | if err != nil{ 120 | fmt.Fprintf(os.Stderr,"Fatal error:%s",err.Error()) 121 | os.Exit(1) 122 | } 123 | } 124 | 125 | func main(){ 126 | udpAddr, err := net.ResolveUDPAddr("udp4",port) 127 | checkError(err) 128 | 129 | var s Server 130 | s.messages = make(chan string,20) 131 | s.clients =make(map[int]Client,0) 132 | 133 | s.conn,err = net.ListenUDP("udp",udpAddr) 134 | checkError(err) 135 | 136 | go s.sendMessage() 137 | 138 | for{ 139 | s.handleMessage() 140 | } 141 | } 142 | --------------------------------------------------------------------------------