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

socket编程

Go基础编程---网络(socket)编程_第1张图片
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)编程)