zoukankan      html  css  js  c++  java
  • Unix Sockets in Go

    转自: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");
    }
  • 相关阅读:
    SpringMVC视图解析器
    JavaEE PO VO BO DTO POJO DAO 整理总结
    Android Studio JNI开发入门教程
    javah的使用
    右键“在此处打开命令行窗口”的一个小秘密
    URL和URI的区别
    自学使用
    Ribbon使用
    Eureka集群搭建
    ssm常见面试题
  • 原文地址:https://www.cnblogs.com/sevenyuan/p/2966044.html
Copyright © 2011-2022 走看看