如何构建一个可以使用Go接收消息并将消息发送到多个客户端的服务器?

时间:2018-10-04 04:04:21

标签: go server client

我是Go语言的新手,我正在尝试创建一个服务器,该服务器可以接收来自客户端的消息并将其发送给其他客户端或任何其他特定客户端。我已经尝试了许多聊天示例,但是我想做的是创建两个文件,其中一个用于服务器,另一个用于客户端。这是我到目前为止尝试过的代码。

server.go

package main

import "net"
import "fmt"
import "bufio"
import "strings" 

func send(c net.Conn){
    netData, err := bufio.NewReader(c).ReadString('\n')
            if err != nil {
                    fmt.Println(err)
                    return
            }

    temp := strings.TrimSpace(string(netData))
    fmt.Printf(temp)        

}

func main() {

    fmt.Println("Launching server...")

    // listen on all interfaces
    ln, _ := net.Listen("tcp", ":8081")

    for {
        // Listen for an incoming connection.
        conn, err := ln.Accept()

        if err != nil {
            fmt.Println("Error accepting: ", err.Error())
            continue
        }

        go send(conn)

    } 

client.go

package main

import "net"
import "fmt"
import "bufio"
import "os"

func recieve(conn net.Conn){
    message, _ := bufio.NewReader(conn).ReadString('\n')
    fmt.Println(message)
}

func send(conn net.Conn){
    reader := bufio.NewReader(os.Stdin)

    text, _ := reader.ReadString('\n')
    fmt.Fprintf(conn, text)
}


func main(){

    // connect to this socket
    conn, err := net.Dial("tcp", "127.0.0.1:8081")
    if err != nil {
        fmt.Println("Error accepting: ", err.Error())

    }

    for {
        go recieve(conn)
        go send(conn)  
    }
    conn.Close()
}

当我尝试运行时,我的计算机崩溃了。我了解我在处理发送和接收的消息时遇到了一些错误,但是无法弄清楚。我将不胜感激。谢谢。

2 个答案:

答案 0 :(得分:1)

我已经修改了您的代码,使其看起来像这样。虽然似乎可行 它有点原始,缺乏适当的错误处理。

server.go

package main

import (
    "bufio"
    "fmt"
    "io"
    "net"
    "strings"
)

func (s *server) recvAndEcho(c io.ReadCloser) {
    defer c.Close()

    for {
        netData, err := bufio.NewReader(c).ReadString('\n')
        if err != nil {
            fmt.Println(err)
            return
        }

        temp := strings.TrimSpace(string(netData))
        fmt.Println(temp)
        s.broadcastMsg(netData)
    }
}

type server struct {
    clients []io.Writer
}

func (s *server) addClient(c net.Conn) {
    s.clients = append(s.clients, c)
}

func (s *server) broadcastMsg(msg string) {
    for _, cl := range s.clients {
        // Send the original msg back to the client
        _, err := cl.Write([]byte(fmt.Sprintf("server replied: %s\n", msg)))
        if err != nil {
            fmt.Println("server: failed to write!")
        }
    }
}

func main() {
    fmt.Println("Launching server...")
    srv := &server{}

    // listen on all interfaces
    ln, _ := net.Listen("tcp", ":8081")

    for {
        // Listen for an incoming connection.
        conn, err := ln.Accept()

        if err != nil {
            fmt.Println("Error accepting: ", err.Error())
            continue
        }
        srv.addClient(conn)
        go srv.recvAndEcho(conn)
    }
}

client.go

package main

import (
    "bufio"
    "fmt"
    "io"
    "net"
    "os"
)

func recvLoop(r io.Reader) {
    var inbuf [64]byte
    for {
        n, err := r.Read(inbuf[:])
        if err != nil {
            fmt.Println("Failed to receive msg from the server!")
            break
        }
        fmt.Print(string(inbuf[:n]))
    }
}

func main() {
    // connect to this socket
    conn, err := net.Dial("tcp", "127.0.0.1:8081")
    if err != nil {
        fmt.Println("Error accepting: ", err.Error())
        return

    }

    sc := bufio.NewScanner(os.Stdin)
    rd := bufio.NewReader(conn)
    go recvLoop(rd)

    for sc.Scan() {
        if sc.Err() != nil {
            fmt.Println("scanner error!")
        }
        txt := sc.Text()
        // It is important to append "newline" here because you are
        // using the "ReadString('\n')" method on the server side.
        // Otherwise, the program would stuck at the "readstring"
        // method.
        b := []byte(txt + "\n")
        _, err := conn.Write(b)
        if err != nil {
            fmt.Println("Failed to send data to the server!")
            break
        }
    }

    conn.Close()
}

答案 1 :(得分:0)

我已经以这种方式修改了客户端。在主函数中将goroutine函数称为“接收”。

package main

import (
"bufio"
"fmt"
"net"
"os"
)

func main() {
// connect to this socket
conn, err := net.Dial("tcp", "127.0.0.1:8081")
if err != nil {
    fmt.Println("Error accepting: ", err.Error())

}
go receive(conn)
sc := bufio.NewScanner(os.Stdin)


for sc.Scan() {
    if sc.Err() != nil {
        fmt.Println("scanner error!")
    }
    txt := sc.Text()
    // It is important to append "newline" here because you are
    // using the "ReadString('\n')" method on the server side.
    // Otherwise, the program would stuck at the "readstring"
    // method.
    b := []byte(txt + "\n")
    _, err := conn.Write(b)
    if err != nil {
        fmt.Println("Failed to send data to the server!")
        break
    }


}

conn.Close()
}

func receive(c net.Conn){
    rd := bufio.NewReader(c)
    var inbuf [64]byte
for{
 n, err := rd.Read(inbuf[:])

if err != nil {
        fmt.Println("Failed to receive msg from the server!")
        break
    }
    fmt.Print(string(inbuf[:n]))

}
c.Close()
}