Как построить сервер, который может получать и отправлять сообщения нескольким клиентам с помощью Go? - PullRequest
0 голосов
/ 04 октября 2018

Я новичок в 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 голосов
/ 04 октября 2018

Я изменил сторону клиента таким образом.Вызывается функция регулярного вызова «получать» в основной функции.

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()
}
0 голосов
/ 04 октября 2018

Я изменил ваш код, чтобы он выглядел следующим образом.Несмотря на то, что он работает, он немного примитивен и не имеет надлежащей обработки ошибок.

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()
}
...