Golang socket
阿新 • • 發佈:2017-12-21
== 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