温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

使用go语言怎么实现一个聊天服务器

发布时间:2021-04-09 17:56:09 来源:亿速云 阅读:209 作者:Leah 栏目:编程语言

这篇文章将为大家详细讲解有关使用go语言怎么实现一个聊天服务器,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

server 端:

监听 TCP 连接;支持自定义客户端命令;支持消息分发;理论上支持广播;...

package main import (   "fmt"   "net"   "io"   "strconv"   "time"   "strings" ) const (   NORMAL_MESSAGE = iota   LIST_MESSAGE ) var clientSenders = make(map[string] chan string) func send (addr string, conn *net.Conn){   senderChan := clientSenders[addr]   for s := range senderChan{     (*conn).Write([]byte(s))   } } func sendUsersInfo(addr string){   senderChan := clientSenders[addr]   if nil != senderChan{     ls := strconv.Itoa(LIST_MESSAGE)     cs := strconv.Itoa(NORMAL_MESSAGE) + "已登录客户端列表:\n"     i := 1     for k := range clientSenders{       a := ""       if k == addr {         a = "(我)"       }       cs = cs + strconv.Itoa(i) + ")" + k + a + "\n"       ls += k + "\n"       i ++     }     cs += "发送消息,可使用 1<-这是给1号客户端的消息\n(请使用英文以获取最佳体验)\n"     senderChan <- cs     time.Sleep(time.Millisecond * 300)     senderChan <- ls     // 发送格式化的列表     fmt.Println("已发送“登录用户信息”", addr)   } else{     fmt.Println("客户端接受通道不存在", addr)   } } func serve (conn *net.Conn){   connect := *conn   addr := connect.RemoteAddr().String()   fmt.Println(addr, "接入服务")   senderChan := make(chan string, 3)   clientSenders[addr] = senderChan   // 启动发送   go send(addr, conn)   // 发送当前用户信息   go sendUsersInfo(addr)   buff := make([]byte, 10240)   for {     n, err := connect.Read(buff)     if err != nil {       if err == io.EOF {         fmt.Println("客户端断开链接,", addr)         delete(clientSenders, addr)         return       } else{         fmt.Println(err)       }     }     msg := string(buff[:n])     // 刷新客户端列表     if msg == "ls\n" {       go sendUsersInfo(addr)       continue     }     // 提取数据     msgs := strings.Split(msg, "<-")     if len(msg) < 2{       senderChan <- string("数据格式不正确,请联系开发者")       continue     }     aimAddr := msgs[0]     aimSender := clientSenders[aimAddr]     if aimSender == nil {       senderChan <- string("客户端已下线,使用 ls 命令获取最新的客户端列表")       continue     }     aimSender <- strconv.Itoa(NORMAL_MESSAGE) + "[from:" + addr + "]:" + strings.Join(msgs[1:], "<-")   } } func main(){   addr := ":8080"   listener, err := net.Listen("tcp", addr)   if err != nil{     fmt.Println(err)     return   }   // 启动消息调度器   defer listener.Close()   // 启动连接监听   for {     conn, err := listener.Accept()     if err != nil {       fmt.Println(err)       continue     }     go serve(&conn)   } }

客户端:

支持断线重连;支持给特定其他客户端发信息

package main import (   "net"   "fmt"   "io"   "os"   "bufio"   "sync"   "time"   "strings"   "strconv" ) var conn *net.Conn var addrs []string const (   NORMAL_MESSAGE = iota   LIST_MESSAGE ) func read(conn2 *net.Conn){   defer func() {     fmt.Println("尝试重连")     go connectServer()   }()   connect := *conn2   buff := make([]byte, 20140)   for {     n, err := connect.Read(buff)     if err != nil {       if err == io.EOF{         fmt.Println("结束")         (*conn2).Close()         conn = nil         return       } else{         fmt.Println(err)       }     }     msg := string(buff[:n])     t, err := strconv.Atoi(string(msg[0]))     msg = msg[1:]     switch t {     case NORMAL_MESSAGE:       fmt.Print(msg)       break     case LIST_MESSAGE:       // 解析客户端列表数据       addrs = strings.Split(msg, "\n")       fmt.Println("已接收客户端列表。\n")       break     default:       fmt.Print(msg)       break     }   } } func connectServer(){   addr := "192.168.99.236:8080"   fmt.Println("等待服务器开启中")   conn2, err := net.Dial("tcp", addr)   if err != nil {     fmt.Print(err)     fmt.Println("连接失败,10s后尝试")     time.Sleep(10 * time.Second)     go connectServer()     return   }   fmt.Println("已连接")   conn = &conn2   go read(&conn2) } func send (){   inputReader := bufio.NewReader(os.Stdout)   for {     input, err := inputReader.ReadString('\n')     if err != nil {       if err == io.EOF{         return       } else{         fmt.Println(err)       }     }     if input == "ls\n" {       (*conn).Write([]byte(input))       continue     }     msgs := strings.Split(input, "<-")     if len(msgs) < 2 {       fmt.Println("发送的姿势不正确,应该像这样 1<-给1号发送消息\n")       continue     }     index, err := strconv.Atoi(msgs[0])     if err != nil {       fmt.Println("发送的姿势不正确,应该像这样 1<-给1号发送消息\n")       continue     }     if len(addrs) <= index {       fmt.Println("不存在第" + strconv.Itoa(index) + "个客户端\n")       continue     }     addr := addrs[index-1]     input = addr + "<-" + strings.Join(msgs[1:], "<-")     if nil != conn {       (*conn).Write([]byte(input))     }   } } func main (){   var wg sync.WaitGroup   wg.Add(2)   go connectServer()   go send()   wg.Wait()   defer func() {     if nil != conn {       (*conn).Close()     }   }() }

关于使用go语言怎么实现一个聊天服务器就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI