码农Golang语言社区

Golang聊天室

2017-01-08  本文已影响194人  丶沙工
 type TCPAddr struct {
      IP IP
      Port int
  }
  service="www.google.com:80"
  tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
  conn, err := net.DialTCP("tcp", nil, tcpAddr)
  _, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))
  _, err = conn.Read(b) / result, err := ioutil.ReadAll(conn)
  service:=":9090"
  tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
  l,err := net.ListenTCP("tcp",tcpAddr)
  conn,err := l.Accept()
  go Handler(conn) //此处使用go关键字新建线程处理连接,实现并发
  1. 代码中包括了服务器和客户端的内容,如果是服务器,直接输入./chat server 9090即可,客户端也很简单,输入./chat client :9090就好;

  2. 如果是客户端,其实就包括了两部分内容,一部分是 chatSend 函数,接受用户的输入;另一部分是connect 到 server,接受相关信息;

  3. 如果是 server,稍微复杂一点,有三个部分组成。第一部分就是不停地 accept 各个客户端;第二个就是为每一个客户端创立 Handler 函数,接受客户端发来的信息;第三个就是 echoHandler 函数,它的作用就是将从某一用户接受过来的信息广播给其他所有的客户端,就是这么简单。
    [实现]
    package main

        import (
            "fmt"
            "net"
            "os"
        )
    
        ////////////////////////////////////////////////////////
        //
        //错误检查
        //
        ////////////////////////////////////////////////////////
        func checkError(err error, info string) (res bool) {
    
            if err != nil {
                fmt.Println(info + "  " + err.Error())
                return false
            }
            return true
        }
    
        ////////////////////////////////////////////////////////
        //
        //服务器端接收数据线程
        //参数:
        //      数据连接 conn
        //      通讯通道 messages
        //
        ////////////////////////////////////////////////////////
        func Handler(conn net.Conn, messages chan string) {
    
            fmt.Println("connection is connected from ...", conn.RemoteAddr().String())
    
            buf := make([]byte, 1024)
            for {
                lenght, err := conn.Read(buf)
                if checkError(err, "Connection") == false {
                    conn.Close()
                    break
                }
                if lenght > 0 {
                    buf[lenght] = 0
                }
                //fmt.Println("Rec[",conn.RemoteAddr().String(),"] Say :" ,string(buf[0:lenght]))
                reciveStr := string(buf[0:lenght])
                messages <- reciveStr
    
            }
    
        }
    
        ////////////////////////////////////////////////////////
        //
        //服务器发送数据的线程
        //
        //参数
        //      连接字典 conns
        //      数据通道 messages
        //
        ////////////////////////////////////////////////////////
        func echoHandler(conns *map[string]net.Conn, messages chan string) {
    
            for {
                msg := <-messages
                fmt.Println(msg)
    
                for key, value := range *conns {
    
                    fmt.Println("connection is connected from ...", key)
                    _, err := value.Write([]byte(msg))
                    if err != nil {
                        fmt.Println(err.Error())
                        delete(*conns, key)
                    }
    
                }
            }
    
        }
    
        ////////////////////////////////////////////////////////
        //
        //启动服务器
        //参数
        //  端口 port
        //
        ////////////////////////////////////////////////////////
        func StartServer(port string) {
            service := ":" + port //strconv.Itoa(port);
            tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
            checkError(err, "ResolveTCPAddr")
            l, err := net.ListenTCP("tcp", tcpAddr)
            checkError(err, "ListenTCP")
            conns := make(map[string]net.Conn)
            messages := make(chan string, 10)
            //启动服务器广播线程
            go echoHandler(&conns, messages)
    
            for {
                fmt.Println("Listening ...")
                conn, err := l.Accept()
                checkError(err, "Accept")
                fmt.Println("Accepting ...")
                conns[conn.RemoteAddr().String()] = conn
                //启动一个新线程
                go Handler(conn, messages)
    
            }
    
        }
    
        ////////////////////////////////////////////////////////
        //
        //客户端发送线程
        //参数
        //      发送连接 conn
        //
        ////////////////////////////////////////////////////////
        func chatSend(conn net.Conn) {
    
            var input string
            username := conn.LocalAddr().String()
            for {
    
                fmt.Scanln(&input)
                if input == "/quit" {
                    fmt.Println("ByeBye..")
                    conn.Close()
                    os.Exit(0)
                }
    
                lens, err := conn.Write([]byte(username + " Say :::" + input))
                fmt.Println(lens)
                if err != nil {
                    fmt.Println(err.Error())
                    conn.Close()
                    break
                }
    
            }
    
        }
    
        ////////////////////////////////////////////////////////
        //
        //客户端启动函数
        //参数
        //      远程ip地址和端口 tcpaddr
        //
        ////////////////////////////////////////////////////////
        func StartClient(tcpaddr string) {
    
            tcpAddr, err := net.ResolveTCPAddr("tcp4", tcpaddr)
            checkError(err, "ResolveTCPAddr")
            conn, err := net.DialTCP("tcp", nil, tcpAddr)
            checkError(err, "DialTCP")
            //启动客户端发送线程
            go chatSend(conn)
    
            //开始客户端轮训
            buf := make([]byte, 1024)
            for {
    
                lenght, err := conn.Read(buf)
                if checkError(err, "Connection") == false {
                    conn.Close()
                    fmt.Println("Server is dead ...ByeBye")
                    os.Exit(0)
                }
                fmt.Println(string(buf[0:lenght]))
    
            }
        }
    
        ////////////////////////////////////////////////////////
        //
        //主程序
        //
        //参数说明:
        //  启动服务器端:  Chat server [port]             eg: Chat server 9090
        //  启动客户端:    Chat client [Server Ip Addr]:[Server Port]    eg: Chat client 192.168.0.74:9090
        //
        ////////////////////////////////////////////////////////
        func main() {
    
            if len(os.Args) != 3 {
                fmt.Println("Wrong pare")
                os.Exit(0)
            }
    
            if os.Args[1] == "server" && len(os.Args) == 3 {
    
                StartServer(os.Args[2])
            }
    
            if os.Args[1] == "client" && len(os.Args) == 3 {
    
                StartClient(os.Args[2])
            }
    
        }
上一篇 下一篇

猜你喜欢

热点阅读