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

 PS:關於sync.Cond可以參考下一篇文章:《Golang sync》

 

 

4.結果截圖

 

以上。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM