转自:http://stackoverflow.com/questions/2886719/unix-sockets-in-go
Server:
package main import "net" import "fmt" func echoServer(c net.Conn) { for { buf := make([]byte, 512) nr, err := c.Read(buf) if err != nil { return } data := buf[0:nr] fmt.Printf("Received: %v", string(data)) _, err = c.Write(data) if err != nil { panic("Write: " + err.String()) } } } func main() { l, err := net.Listen("unix", "/tmp/echo.sock") if err != nil { println("listen error", err.String()) return } for { fd, err := l.Accept() if err != nil { println("accept error", err.String()) return } go echoServer(fd) } }
Client
package main import ( "net" "time" "io" ) func reader(r io.Reader) { buf := make([]byte, 1024) for { n, err := r.Read(buf[:]) if err != nil { return } println("Client got:", string(buf[0:n])) } } func main() { c,err := net.Dial("unix","", "/tmp/echo.sock") if err != nil { panic(err.String()) } defer c.Close() go reader(c) for { _,err := c.Write([]byte("hi")) if err != nil { println(err.String()) break } time.Sleep(1e9) } }
转自:
Server:
package main import ( "fmt"; "net"; "log"; "os"; "container/list"; "strings"; "bytes"; "flag"; ) // flag for debuging info. or a simple log var debug = flag.Bool("d", false, "set the debug modus( print informations )") type ClientChat struct { Name string; // name of user IN chan string; // input channel for to send to user OUT chan string; // input channel from user to all Con *net.Conn; // connection of client Quit chan bool; // quit channel for all goroutines ListChain *list.List; // reference to list } // read from connection and return true if ok func (c *ClientChat) Read(buf []byte) bool{ nr, err := c.Con.Read(buf); if err!=nil { c.Close(); return false; } Log("Read(): ", nr, " bytes"); return true; } // close the connection and send quit to sender func (c *ClientChat) Close() { c.Quit<-true; c.Con.Close(); c.deleteFromList(); } // compare two clients: name and network connection func (c *ClientChat) Equal(cl *ClientChat) bool { if bytes.Equal(strings.Bytes(c.Name), strings.Bytes(cl.Name)) { if c.Con == cl.Con { return true; } } return false; } // delete the client from list func (c *ClientChat) deleteFromList() { for e := c.ListChain.Front(); e != nil; e = e.Next() { client := e.Value.(ClientChat); if c.Equal(&client) { Log("deleteFromList(): ", c.Name); c.ListChain.Remove(e); } } } // func Log(v ...): loging. give log information if debug is true func Log(v ...) { if *debug == true { ret := fmt.Sprint(v); log.Stdoutf("SERVER: %s", ret); } } // func test(): testing for error func test(err os.Error, mesg string) { if err!=nil { log.Stderr("SERVER: ERROR: ", mesg); os.Exit(-1); } else Log("Ok: ", mesg); } // handlingINOUT(): handle inputs from client, and send it to all other client via channels. func handlingINOUT(IN <-chan string, lst *list.List) { for { Log("handlingINOUT(): wait for input"); input := <-IN; // input, get from client // send to all client back Log("handlingINOUT(): handling input: ", input); for value := range lst.Iter() { client := value.(ClientChat); Log("handlingINOUT(): send to client: ", client.Name); client.IN<- input; } } } // clientreceiver wait for an input from network, after geting data it send to // handlingINOUT via a channel. func clientreceiver(client *ClientChat) { buf := make([]byte, 2048); Log("clientreceiver(): start for: ", client.Name); for client.Read(buf) { if bytes.Equal(buf, strings.Bytes("/quit")) { client.Close(); break; } Log("clientreceiver(): received from ",client.Name, " (", string(buf), ")"); send := client.Name+"> "+string(buf); client.OUT<- send; for i:=0; i<2048;i++ { buf[i]=0x00; } } client.OUT <- client.Name+" has left chat"; Log("clientreceiver(): stop for: ", client.Name); } // clientsender(): get the data from handlingINOUT via channel (or quit signal from // clientreceiver) and send it via network func clientsender(client *ClientChat) { Log("clientsender(): start for: ", client.Name); for { Log("clientsender(): wait for input to send"); select { case buf := <- client.IN: Log("clientsender(): send to \"", client.Name, "\": ", string(buf)); client.Con.Write(strings.Bytes(buf)); case <-client.Quit: Log("clientsender(): client want to quit"); client.Con.Close(); break; } } Log("clientsender(): stop for: ", client.Name); } // clientHandling(): get the username and create the clientsturct // start the clientsender/receiver, add client to list. func clientHandling(con *net.Conn, ch chan string, lst *list.List) { buf := make([]byte, 1024); con.Read(buf); name := string(buf); newclient := &ClientChat{name, make(chan string), ch, con, make(chan bool), lst}; Log("clientHandling(): for ", name); go clientsender(newclient); go clientreceiver(newclient); lst.PushBack(*newclient); ch<- name+" has joinet the chat"; } func main() { flag.Parse(); Log("main(): start"); // create the list of clients clientlist := list.New(); in := make(chan string); Log("main(): start handlingINOUT()"); go handlingINOUT(in, clientlist); // create the connection netlisten, err := net.Listen("tcp", "127.0.0.1:9988"); test(err, "main Listen"); defer netlisten.Close(); for { // wait for clients Log("main(): wait for client ..."); conn, err := netlisten.Accept(); test(err, "main: Accept for client"); go clientHandling(&conn, in, clientlist); } }
Server has three part which are running as goroutines and communicate via channels.
1) handlingINOUT() simple wait for input of clientreceiver() and send to all clientsender() which are in the list.
2) clientreceiver() wait for his data from client via networkconnection and send it to a inputchannel to handlingINOUT
3) clientsender() wait for data from channel and send it to client
every client connection get a his own clientreceiver/sender and a list entry. on disconnection the list entry will be deleted.
Client:
package main import ( "fmt"; "net"; "log"; "os"; "bytes"; "bufio"; "strings"; "time"; "flag"; ) var running bool; // global variable if client is running var debug = flag.Bool("d", false, "set the debug modus( print informations )") // func Log(v ...): loging. give log information if debug is true func Log(v ...) { if *debug == true { ret := fmt.Sprint(v); log.Stdoutf("CLIENT: %s", ret); } } // func test(): testing for error func test(err os.Error, mesg string) { if err!=nil { log.Stderr("CLIENT: ERROR: ", mesg); os.Exit(-1); } else Log("Ok: ", mesg); } // read from connection and return true if ok func Read(con *net.Conn) string{ var buf [4048]byte; _, err := con.Read(&buf); if err!=nil { con.Close(); running=false; return "Error in reading!"; } str := string(&buf); fmt.Println(); return string(str); } // clientsender(): read from stdin and send it via network func clientsender(cn *net.Conn) { reader := bufio.NewReader(os.Stdin); for { fmt.Print("you> "); input, _ := reader.ReadBytes('\n'); if bytes.Equal(input, strings.Bytes("/quit\n")) { cn.Write(strings.Bytes("/quit")); running = false; break; } Log("clientsender(): send: ", string(input[0:len(input)-1])); cn.Write(input[0:len(input)-1]); } } // clientreceiver(): wait for input from network and print it out func clientreceiver(cn *net.Conn) { for running { fmt.Println(Read(cn)); fmt.Print("you> "); } } func main() { flag.Parse(); running = true; Log("main(): start "); // connect destination := "127.0.0.1:9988"; Log("main(): connecto to ", destination); cn, err := net.Dial("tcp", "", destination); test(err, "dialing"); defer cn.Close(); Log("main(): connected "); // get the user name fmt.Print("Please give you name: "); reader := bufio.NewReader(os.Stdin); name, _ := reader.ReadBytes('\n'); //cn.Write(strings.Bytes("User: ")); cn.Write(name[0:len(name)-1]); // start receiver and sender Log("main(): start receiver"); go clientreceiver(&cn); Log("main(): start sender"); go clientsender(&cn); // wait for quiting (/quit). run until running is true for ;running; { time.Sleep(1*1e9); } Log("main(): stoped"); }