duan3019 2018-10-04 04:04 采纳率: 100%
浏览 98

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

I am new in Go and I am trying to create a server which can receive a message from a client and send it to other client or any other specific client. I have tried many chat examples but what I wanted to do is to create two files where one is for server and another is for the client. This is the code I tried so far.

server.go

package main

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

func send(c net.Conn){
    netData, err := bufio.NewReader(c).ReadString('
')
            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('
')
    fmt.Println(message)
}

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

    text, _ := reader.ReadString('
')
    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()
}

When I try to run that my computer crashed. I understand I am making some mistake for handling the send & received message but couldn't able to figure it out. I will appreciate any kind of help. Thanks.

  • 写回答

2条回答 默认 最新

  • dongxinjun3944 2018-10-04 11:57
    关注

    I've modified your code to look like this. Although it seems to be working it is a bit primitive and lacks proper error handling.

    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('
    ')
            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
    ", 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('
    ')" method on the server side.
            // Otherwise, the program would stuck at the "readstring"
            // method.
            b := []byte(txt + "
    ")
            _, err := conn.Write(b)
            if err != nil {
                fmt.Println("Failed to send data to the server!")
                break
            }
        }
    
        conn.Close()
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog