1. 程式人生 > >Golang socket

Golang socket

== pack else import github lob echo dial listener

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\n";
        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\n";
        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.")
}

4.結果截圖

技術分享圖片

以上。

Golang socket