package main import ( "encoding/binary" "fmt" "github.com/pborman/getopt/v2" "io" "io/ioutil" "net" "os" "strings" "time" ) const HeadSize int = 4 func initServer(network,addr string) net.Listener { listener,err := net.Listen(network,addr) if err != nil { fmt.Println("Listener for",addr) } return listener } func testServer(listener net.Listener) { defer listener.Close() for { unixConn, err := listener.Accept() if err != nil { continue //return } fmt.Println("A client connected : " + unixConn.RemoteAddr().String()) unixPipe(unixConn) } } func unixPipe(conn io.ReadWriteCloser) { defer conn.Close() buf := make([]byte,1024*1024*10) for { conn.Read(buf[:HeadSize]) payloadLength := binary.LittleEndian.Uint32(buf) length,err := conn.Read(buf[HeadSize : HeadSize+int(payloadLength)]) if err != nil { if err == io.EOF { fmt.Println("read from client error=", err, "need to read len=", payloadLength) } else { fmt.Println("client disconnected=", err, "need to read len=", payloadLength) } return } buf[0] = '@' buf[1] = '#' conn.Write(buf[:HeadSize+length]) fmt.Println(time.Now(),"received len=",length) } } func initClient(network,addr string) io.ReadWriteCloser{ conn, err := net.Dial(network, addr) if err != nil { fmt.Println("dialUnix err=", err) } fmt.Println("connected!") return conn } func testClient(conn io.ReadWriteCloser,content []byte,count int) { data := make([]byte, HeadSize+len(content)) dataLength := uint32(len(content)) binary.LittleEndian.PutUint32(data,dataLength) copy(data[HeadSize:], content) fmt.Println("client will send",data) buf := make([]byte,1024*1024*10) var max,sum time.Duration var min = time.Second * 100 for i := 0; i < count;i++ { begin := time.Now() conn.Write(data) length, err := conn.Read(buf[:len(data)]) if err != nil { fmt.Println("read from server, error=",err) return } elapsed := time.Since(begin) if max < elapsed { max = elapsed } if min > elapsed { min = elapsed } sum += elapsed fmt.Println("read use ",elapsed,"length=",length,buf[0],buf[1]) time.Sleep(time.Millisecond *100) } ave := time.Duration(int64(sum) / 1000) fmt.Println("total use ","max=",max,"min=",min,"ave=",ave) } func main() { // Declare the flags to be used helpFlag := getopt.Bool('h', "display help") serverFlag := getopt.BoolLong("server", 's', "", "the command") addrString := getopt.StringLong("address", 'a', "/tmp/unix_sock", "address") countFlag := getopt.IntLong("count", 'c',1,"test count of loop") textFlag := getopt.StringLong("text", 't',"00112233445566778899","text to send") fileFlag := getopt.StringLong("file", 'f',"","read data from file to send") //repeatFlag := getopt.StringLong("retransmit", 'r',"","address for retransmit data to next node") //:= getopt.BoolLong("server", 's', "", "the command") // Parse the program arguments getopt.Parse() // Get the remaining positional parameters //args := getopt.Args() if *helpFlag { getopt.PrintUsage(os.Stdout) return } var network string isUnixDomain := strings.ContainsRune(*addrString,'/') if !isUnixDomain { network = "tcp" } else { network = "unix" if *serverFlag { os.Remove(*addrString) } } sendContent := []byte(*textFlag) fmt.Println("It will use :",network,*addrString) if len(*fileFlag) > 0 { f , err := os.Open(*fileFlag) if err != nil { fmt.Println("open file",*fileFlag,err) return } sendContent,err = ioutil.ReadAll(f) if err != nil { fmt.Println("read file",*fileFlag,err) return } } if *serverFlag { listener := initServer(network,*addrString) defer listener.Close() testServer(listener) } else { conn := initClient(network,*addrString) defer conn.Close() testClient(conn,sendContent,*countFlag) } }