[Go] socket programming

socket characteristics

  • Always come in pairs

  • Full-duplex (both send and receive) (tied to two channel)

Applications
- cs mode (client development)
- bs mode (web development)

net api package basis

The client is unsolicited data (client request)

There are three soket. 2 has a communication. Another for monitoring ip port

// 服务端

import (
    "net"
)

listener, err := net.Listen("tcp", "127.0.0.1:8000") //生成监听socket
defer listener.Close()

conn, err := listener.Accept() //[**阻塞] 生成读写socket
defer conn.Close()

buf := make([]byte, 4096)
n, err := conn.Read(buf) //[**阻塞]
                         //读客户端数据(client request)
conn.Write(buf[:n])      //写数据给客户端
//客户端

conn, err := net.Dial("tcp", "127.0.0.1:8000")
defer conn.Close()

conn.Write([]byte("Are you Ready?")) //写数据

buf := make([]byte, 4096) //读数据
n, err := conn.Read(buf)
fmt.Println("服务器回发:", string(buf[:n]))

Conn achieve multiplexing: read and write cycles

//server

func main() {
    listener, _ := net.Listen("tcp", ":3000")
    defer listener.Close()
    conn, _ := listener.Accept()
    defer conn.Close()
    buf := make([]byte, 1024)
    for {
        n, _ := conn.Read(buf)
        if n==0{ //客户端关闭时候server退出
            return
        }
        fmt.Println(string(buf[:n]))
        conn.Write([]byte("i am server"))
        time.Sleep(time.Second / 3)
    }
}
// client

func main() {
    conn, _ := net.Dial("tcp", ":3000")
    defer conn.Close()
    buf := make([]byte, 1024)
    for {
        conn.Write([]byte("hi server"))

        n, _ := conn.Read(buf)
        fmt.Println(string(buf[:n]))
        time.Sleep(time.Second/3)
    }
}

server support concurrent

// server

func main() {
    listener, _ := net.Listen("tcp", ":3000")
    defer listener.Close()
    for {
        conn, _ := listener.Accept()
        go func(conn net.Conn) {
            defer conn.Close()
            buf := make([]byte, 1024)
            for {
                n, _ := conn.Read(buf) //已关闭的chan中往出读数据会一直读出零值
                if n == 0 {
                    return
                }
                fmt.Println(string(buf[:n]))
                conn.Write([]byte("i am server"))
                time.Sleep(time.Second / 3)
            }
        }(conn)
    }

    time.Sleep(time.Second * 1000)
}
//client

func main() {
    conn, _ := net.Dial("tcp", ":3000")
    defer conn.Close()
    buf := make([]byte, 1024)
    for {
        conn.Write([]byte("hi server"))

        n, _ := conn.Read(buf)
        fmt.Println(string(buf[:n]))
        time.Sleep(time.Second/3)
    }
}

Concurrent server - the process exits and other issues.

// 并发版的server: 复用lisntner.Accept

listener, err := net.Listen("tcp", "localhost:3000")
defer listener.Close()

for {
    conn, err := listener.Accept() //阻塞,获取读写socket: conn
    if err != nil {
        fmt.Println("listener.Accept err:", err)
        return
    }
    go HandlerConnect(conn)
}


func HandlerConnect(conn net.Conn) {
    defer conn.Close()

    // 获取连接的客户端 Addr
    addr := conn.RemoteAddr()
    fmt.Println(addr, "客户端成功连接!")

    // 循环读取客户端发送数据
    buf := make([]byte, 4096)
    for {
        n, err := conn.Read(buf)
        if "exit\n" == string(buf[:n]) || "exit\r\n" == string(buf[:n]) {
            fmt.Println("服务器接收的客户端退出请求,服务器关闭")
            return
        }
        if n == 0 {
            fmt.Println("服务器检测到客户端已关闭,断开连接!!!")
            return
        }
        if err != nil {
            fmt.Println("conn.Read err:", err)
            return
        }
        fmt.Println("服务器读到数据:", string(buf[:n]))

        conn.Write([]byte(strings.ToUpper(string(buf[:n]))))
    }
}
//并发版的客户端

func main()  {
    conn, err := net.Dial("tcp", "192.168.15.78:8001")
    if err != nil {
        fmt.Println("net.Dial err:", err)
        return
    }
    defer conn.Close()
    // 获取用户键盘输入( stdin ),将输入数据发送给服务器
    go func() {
        str := make([]byte, 4096)
        for {
            n, err := os.Stdin.Read(str)
            if err != nil {
                fmt.Println("os.Stdin.Read err:", err)
                continue
            }
            //写给服务器, 读多少,写多少!
            conn.Write(str[:n])
        }
    }()

    // 回显服务器回发的大写数据
    buf := make([]byte, 4096)
    for {
        n, err := conn.Read(buf)
        if n == 0 {
            fmt.Println("检查到服务器关闭,客户端也关闭")
            return
        }
        if err != nil {
            fmt.Println("conn.Read err:", err)
            return
        }
        fmt.Println("客户端读到服务器回发:", string(buf[:n]))
    }
}

Guess you like

Origin www.cnblogs.com/iiiiiher/p/11962062.html