// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // $G $F.go && $L $F.$A && GOMAXPROCS=3 ./$A.out // # TODO(rsc): GOMAXPROCS will go away eventually. // # 3 is one for Echo, one for Serve, one for Connect. package main import ( "os"; "io"; "net"; "syscall" ) func StringToBuf(s string) *[]byte { l := len(s); b := new([]byte, l); for i := 0; i < l; i++ { b[i] = s[i]; } return b; } func Echo(fd io.ReadWrite, done *chan<- int) { var buf [1024]byte; for { n, err := fd.Read(&buf); if err != nil || n == 0 { break; } fd.Write((&buf)[0:n]) } done <- 1 } func Serve(network, addr string, listening, done *chan<- int) { l, err := net.Listen(network, addr); if err != nil { panic("listen: "+err.String()); } listening <- 1; for { fd, addr, err := l.Accept(); if err != nil { break; } echodone := new(chan int) go Echo(fd, echodone); <-echodone; // make sure Echo stops l.Close(); } done <- 1 } func Connect(network, addr string) { fd, err := net.Dial(network, "", addr); if err != nil { panic("connect: "+err.String()); } b := StringToBuf("hello, world\n"); var b1 [100]byte; n, errno := fd.Write(b); if n != len(b) { panic("syscall.write in connect"); } n, errno = fd.Read(&b1); if n != len(b) { panic("syscall.read in connect"); } // os.Stdout.Write((&b1)[0:n]); fd.Close(); } func Test(network, listenaddr, dialaddr string) { // print("Test ", network, " ", listenaddr, " ", dialaddr, "\n"); listening := new(chan int); done := new(chan int); go Serve(network, listenaddr, listening, done); <-listening; // wait for server to start Connect(network, dialaddr); <-done; // make sure server stopped } func main() { Test("tcp", "0.0.0.0:9999", "127.0.0.1:9999"); Test("tcp", "[::]:9999", "[::ffff:127.0.0.1]:9999"); Test("tcp", "[::]:9999", "127.0.0.1:9999"); Test("tcp", "0.0.0.0:9999", "[::ffff:127.0.0.1]:9999"); sys.exit(0); // supposed to happen on return, doesn't }