美文网首页
Go基础编程---网络(socket)编程

Go基础编程---网络(socket)编程

作者: addin_gao | 来源:发表于2018-04-13 09:16 被阅读21次

    socket编程

    cs架构-socket编程.jpg

    服务器编码---多协程和服务器通信

    // 服务器代码
    package main
    import (
        "fmt"
        "io"
        "log"
        "net"
        "runtime"
        "strings"
    )
    
    func main() {
        listener, err := net.Listen("tcp", "10.0.154.199:8899")
        if err != nil {
            return
        }
        defer listener.Close()
        // 循环等待客户端接入
        for {
            conn, err := listener.Accept() // 阻塞等待客户端接入
            if err != nil {
                continue
            }
            go handle(conn) // 将连接传入执行 函数
        }
    }
    func handle(conn net.Conn) {
        defer conn.Close()                             // 执行完关闭资源
        defer fmt.Println(conn.RemoteAddr(), "已经退出连接") // 执行完关闭资源
        fmt.Println(conn.RemoteAddr(), "已经连接") // 10.0.154.199:11307 已经连接
        buf := make([]byte, 1024) // 创建一个byte的切片容器
    
        for {
            n, err1 := conn.Read(buf) // n为读到的内容长度
            if err1 != nil && err1 != io.EOF {
                fmt.Println("xxxxxxxxxxxxx")
                log.Print(err1)
                return
            }
            str := string(buf[:n])
            if str == "exit" {
                fmt.Println("------------------")
                runtime.Goexit()
            } else {
                str = strings.ToUpper(str)
            }
            conn.Write([]byte(str))
        }
    }
    
    // 客户端代码
    func main() {
        conn, err := net.Dial("tcp", "10.0.154.199:8899")
        defer conn.Close()
        if err != nil {
            return
        }
        dealWith(conn)
    }
    func dealWith(conn net.Conn) {
        buf := make([]byte, 1024)
        for {
            fmt.Scan(&buf)
            conn.Write(buf)
            n, err1 := conn.Read(buf)
            if err1 != nil {
                return
            }
            fmt.Printf("服务器返回:%s\n", string(buf[:n]))
        }
    }
    
    

    文件传输程序

    接收方代码:
    package main
    import (
        "fmt"
        "io"
        "net"
        "os"
    )
    func main() {
        listener, err := net.Listen("tcp", "10.0.154.199:8899")
        defer listener.Close()
        if err != nil {
            return
        }
        conn, err1 := listener.Accept()
        defer conn.Close()
        if err1 != nil {
            return
        }
        // 接收文件名
        fileBuf := make([]byte, 1024)
        n, err2 := conn.Read(fileBuf)
        if err2 != nil {
            return
        }
        fileName := string(fileBuf[:n])
        fmt.Println(fileName)
        // 回复ok
        conn.Write([]byte("ok"))
        // 接收文件内容
        receiveFile(fileName, conn)
    }
    func receiveFile(fileName string, conn net.Conn) {
        buf := make([]byte, 1024*4)
        f, err := os.Create(fileName)
        if err != nil {
            return
        }
        for {
            n, err := conn.Read(buf)
            if err != nil {
                if err == io.EOF {
                    fmt.Printf("文件传送完成")
                    break
                }
                return
            }
            if n == 0 {
                fmt.Printf("文件传送完成")
                break
            }
            f.Write(buf[:n])
        }
    }
    
    // 发送方代码
    package main
    
    import (
        "fmt"
        "io"
        "net"
        "os"
    )
    func main() {
        fmt.Println("请输入要传输的文件路径")
        var path string
        fmt.Scan(&path)
        fileInfo, err0 := os.Stat(path)
        if err0 != nil {
            return
        }
        //传递 文件名给 文件服务器
        conn, err := net.Dial("tcp", "10.0.154.199:8899")
        if err != nil {
            return
        }
        defer conn.Close()
        conn.Write([]byte(fileInfo.Name()))
        buf := make([]byte, 1024)
        n, err1 := conn.Read(buf)
        if err1 != nil {
            return
        }
        if string(buf[:n]) == "ok" {
            // 开始传输文件
            fmt.Println("接收到ok")
            sendFile(path, conn)
        }
    }
    func sendFile(path string, conn net.Conn) {
        //读取文件
        f, err := os.Open(path)
        if err != nil {
            return
        }
        buf := make([]byte, 1024*4)
        for {
            n, err1 := f.Read(buf)
            if err1 != nil {
                if err1 == io.EOF {
                    fmt.Println("传送成功")
                    return
                }
                fmt.Println("传送失败")
            }
            conn.Write(buf[:n])
        }
    }
    
    

    go实现--聊天室---代码

    服务器代码实现
    package main
    import (
        "fmt"
        "log"
        "net"
    )
    
    type Client struct {
        C    chan string
        Addr string
        Name string
    }
    
    // var onLineMap map[string]Client  这样没有分配内存,因为map是引用类型
    var onLineMap = make(map[string]Client)
    var message = make(chan string)
    
    func addToOnline(conn net.Conn) {
        defer conn.Close()
        // 获取ip地址
        str := conn.RemoteAddr().String() // 将*net.TCPAddr指针类型的变为string类型
        // 创建一个结构实列,然后添加到在线map中
        client := Client{make(chan string), str, str}
        onLineMap[str] = client
    
        go WriteToClient(client, conn)
    
        // 发送已经上线
        message <- makeMessage(str, "login")
        // 是否主动退出
        quit := make(chan bool)
        // 遍历map存在多少人
        // 新建一个协程,监听客户端发送的消息
        go func(addr string, conn net.Conn) {
            buf := make([]byte, 1024)
            for {
                n, err := conn.Read(buf)
                if err != nil {
                    return
                }
                str := string(buf[:n])
                if str == "who" {
                    for _, v := range onLineMap {
                        // fmt.Println(v.Name)
                        message <- makeMessage(v.Addr, "在线\n")
                    }
                    message <- string(len(onLineMap)) + "在线\n"
                } else if str == "exit" {
                    quit <- true
                } else {
                    message <- makeMessage(addr, str)
                }
            }
        }(str, conn)
        fmt.Println("---------------")
        for _, v := range onLineMap {
            fmt.Println(v.Name)
        }
        for {
            select {
            case <-quit:
                message <- makeMessage(str, "logout")
                delete(onLineMap, str) // 删除map
            }
        }
    }
    func reciveMessage() {
        for {
            msg := <-message // 没有消息时这个协程 会阻塞
            // 遍历map 给每个人发送
            for _, v := range onLineMap {
                v.C <- msg
            }
        }
    }
    func WriteToClient(cli Client, conn net.Conn) {
        for msg := range cli.C {
            // 给当前客户端发送信息
            conn.Write([]byte(msg))
        }
    }
    func makeMessage(addr string, meg string) (result string) {
        result = "[" + addr + "] : " + meg
        return
    }
    func main() {
        //监听服务
        listener, err := net.Listen("tcp", "10.0.154.199:8899")
        defer listener.Close()
        if err != nil {
            return
        }
        // 接收消息
        go reciveMessage()
        // 循环接收连接请求
        for {
            conn, err := listener.Accept()
            if err != nil {
                log.Print(err)
                continue
            }
            go addToOnline(conn)
        }
    }
    
    

    相关文章

      网友评论

          本文标题:Go基础编程---网络(socket)编程

          本文链接:https://www.haomeiwen.com/subject/dmlvcftx.html