• Golang socket


    1.本例子实现了一个简单的TCP echo。客户端发送Hello,服务端回应World。

    参考:《Socket编程》

     

    2.服务端代码

    package main
    
    import (
        "net"
        "fmt"
        "os"
        "time"
    )
    
    //错误处理函数
    func checkErr(err error, extra string) bool {
        if err != nil {
            formatStr := " Err : %s
    ";
            if extra != "" {
                formatStr = extra + formatStr;
            }
    
            fmt.Fprintf(os.Stderr, formatStr, err.Error());
            return true;
        }
    
        return false;
    }
    
    //连接处理函数
    func svrConnHandler(conn net.Conn) {
        fmt.Println("Client connect success :", conn.RemoteAddr().String());
        conn.SetReadDeadline(time.Now().Add(2 * time.Minute))
        request := make([]byte, 128);
        defer conn.Close();
        for {
            readLen, err := conn.Read(request)
            if checkErr(err, "Read") {
                break;
            }
    
            //socket被关闭了
            if readLen == 0 {
                fmt.Println("Client connection close!");
                break;
            } else {
                //输出接收到的信息
                fmt.Println(string(request[:readLen]))
    
                time.Sleep(time.Second);
                //发送
                conn.Write([]byte("World !"));
            }
    
            request = make([]byte, 128);
        }
    }
    
    func main() {
        //解析地址
        tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:6666");
        if checkErr(err, "ResolveTCPAddr") {
            return;
        }
    
        //设置监听地址
        listener, err := net.ListenTCP("tcp", tcpAddr);
        if checkErr(err, "ListenTCP") {
            return;
        }
    
        for {
            //监听
            fmt.Println("Start wait for client.")
            conn, err := listener.Accept();
            if checkErr(err, "Accept") {
                continue;
            }
    
            //消息处理函数
            go svrConnHandler(conn);
        }
    }

     

    3.客户端代码

     

    package main
    
    import (
        "fmt"
        "os"
        "net"
        "sync"
    )
    
    var gLocker sync.Mutex; //全局锁
    var gCondition *sync.Cond; //全局条件变量
    
    //错误处理函数
    func checkErr(err error, extra string) bool {
        if err != nil {
            formatStr := " Err : %s
    ";
            if extra != "" {
                formatStr = extra + formatStr;
            }
    
            fmt.Fprintf(os.Stderr, formatStr, err.Error());
            return true;
        }
    
        return false;
    }
    
    //连接处理函数
    func clientConnHandler(conn net.Conn) {
        gLocker.Lock();
        defer gLocker.Unlock();
    
        defer conn.Close();
    
        request := make([]byte, 128);
        for {
            readLen, err := conn.Read(request)
            if checkErr(err, "Read") {
                gCondition.Signal();
                break;
            }
    
            //socket被关闭了
            if readLen == 0 {
                fmt.Println("Server connection close!");
    
                //条件变量同步通知
                gCondition.Signal();
                break;
            } else {
                //输出接收到的信息
                fmt.Println(string(request[:readLen]))
    
                //发送
                conn.Write([]byte("Hello !"));
            }
    
            request = make([]byte, 128);
        }
    }
    
    func main() {
        //解析地址
        tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:6666");
        if checkErr(err, "ResolveTCPAddr") {
            return;
        }
    
        conn, err := net.DialTCP("tcp", nil, tcpAddr);
        if checkErr(err, "DialTCP") {
            return;
        }
    
        fmt.Println("Connect server success.")
    
        gLocker.Lock();
        gCondition = sync.NewCond(&gLocker);
    
        //发送数据给服务器
        conn.Write([]byte("Hello !"));
    
        //处理连接(lock在上面调用了,所以clientConnHandler函数必须等wait函数调用后才能lock,这样就能保证调用的先后顺序)
        go clientConnHandler(conn);
    
        //主线程阻塞,等待Singal结束
        for {
            //条件变量同步等待
            gCondition.Wait();
            break;
        }
        gLocker.Unlock();
        fmt.Println("Client finish.")
    }

     PS:关于sync.Cond可以参考下一篇文章:《Golang sync》

     

     

    4.结果截图

     

    以上。

     

  • 相关阅读:
    Apache Beam入门及Java SDK开发初体验
    fetch的请求
    Spring Cache 带你飞(一)
    存储技术发展过程
    Redis 高阶数据类型重温
    Redis 基础数据类型重温
    [源码解析] PyTorch 分布式(1)------历史和概述
    [源码解析] PyTorch 如何实现后向传播 (4)---- 具体算法
    [源码解析] Pytorch 如何实现后向传播 (3)---- 引擎动态逻辑
    [源码解析] Pytorch 如何实现后向传播 (2)---- 引擎静态结构
  • 原文地址:https://www.cnblogs.com/chevin/p/8082224.html
Copyright © 2020-2023  润新知