golang实现qq聊天之客户端与服务器

Mr丶易客 · · 930 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

一、用到的net方法
1 、客户端:

    var buf [512]byte
    tcpAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:9090")
    //向服务器拨号
    conn, _ := net.DialTCP("tcp", nil, tcpAddr)
    //获取远程服务器地址
    rAddr := conn.RemoteAddr()
    //发送数据
    n, _ := conn.Write([]byte(""))
    //接收数据
    n, _ = conn.Read(buf[0:])

2、服务器

func ResolveTCPAddr(network, address string) (*TCPAddr, error)
ResolveTCPAddr返回TCP端点的地址。
网络必须是TCP网络名。
如果地址参数中的主机不是字面IP地址或者端口不是字面端口号,那么ResolveTCPAddr将地址解析为TCP端点的地址。
否则,它将地址解析为一对文字IP地址和端口号。
address参数可以使用主机名,但不建议这样做,因为它将最多返回一个主机名的IP地址。
有关网络和地址的描述,请参阅func Dial参数。

network : Tcp Tcp4 Tcp6         address : :9090  应该是访问地址
返回值:*TCPAddr 地址   第二个返回值:err 
 
监听:func ListenTCP(network string, laddr *TCPAddr) (*TCPListener, error)
ListenTCP在本地TCP地址laddr上声明并返回一个*TCPListener,net参数必须是"tcp"、"tcp4"、"tcp6",如果laddr的端口字段为0,函数将选择一个当前可用的端口,可以用Listener的Addr方法获得该端口

第一个参数:TCP   第二个参数 *TCPAddr 地址   返回值 :

具体代码实现
net.go

package main

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

func main() {
tcpAddr, _ := net.ResolveTCPAddr("tcp", ":9090")
    //向服务器拨号
    conn, _ := net.DialTCP("tcp", nil, tcpAddr)
    go HandlerMessage(conn)
    //接受来自服务器的消息
    buf := make([]byte, 1024)
    for {
        length, err := conn.Read(buf)
        fmt.Println(length)
        if err != nil {
            log.Printf("recv server msg failed :%v\n", err)
            conn.Close()
            os.Exit(0)
            break
        }
        fmt.Println(string(buf[0:length]))
    }

}
func HandlerMessage(conn net.Conn) {
    //获取用户的地址
    username := conn.LocalAddr().String()
    for {
        var input string
        //获取用户发送的消息
        fmt.Scanln(&input)
        if len(input) > 0 {
            msg := username + " say " + input
            //
            _, err := conn.Write([]byte(msg))
            if err != nil {
                conn.Close()
                break
            }
        }
    }
}

server.go

package main

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

func main() {
    port := "9090"
    StartServer(port)
}
func StartServer(p string) {
    port := ":" + p
    //返回tcp地址
    tcpAddr, err := net.ResolveTCPAddr("tcp", port)
    fmt.Println(tcpAddr)
    if err != nil {
        os.Exit(0)
        return
    }
    //监听tcp地址
    listener, err := net.ListenTCP("tcp", tcpAddr)
    if err != nil {
        os.Exit(0)
        return
    }
    buf := make([]byte, 1024)
    conns := make(map[string]net.Conn)  //用户池
    messages := make(chan string, 10)  //消息的通道
    go BroadCastMessage(conns, messages)  //
    //每有一个客户进来就将其放入用户池
    for {
        conn, err := listener.AcceptTCP()
        if err != nil {
            fmt.Println("Accept failed")
            continue
        }
        conns[conn.RemoteAddr().String()] = conn  //将新进来的用户放进用户池
        go HandlerMessage(conn, buf, conns, messages)  //开一个协程监听用户是否发送消息
    }

}
//将收到的信息发送到每一个客户端
func BroadCastMessage(cns map[string]net.Conn, messages chan string) {
    for {
        messtr := <-messages    //接受通道里的消息
        //将接收到的消息发送给用户池里的每一个用户
        for k, v := range cns {
            _, err := v.Write([]byte(messtr))  //发送消息
            if err != nil {
                delete(cns, k)  //如果出现错误 删除用户 结束本次循环
                v.Close()
                continue
            }
        }
    }
}
//接受用户发送的消息
func HandlerMessage(conn net.Conn, buf []byte, cns map[string]net.Conn, messages chan string) {
    for {
        length, err := conn.Read(buf)
        if err != nil {
            conn.Close()
            delete(cns, conn.RemoteAddr().String())
            break
        }
        messages <- string(buf[0:length])  //将用户的信息放到通道里
        // fmt.Println(string(buf[0:length]))
    }
}

OK!


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:Mr丶易客

查看原文:golang实现qq聊天之客户端与服务器

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

930 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传