V
V
Vladimir Grabko2016-04-22 16:09:55
go
Vladimir Grabko, 2016-04-22 16:09:55

How to send data to all routines?

Thanks to FireGM for helping me fix sending messages from the terminal to clients. In theory, the code should send data to all clients. Now I have connected two clients, I write the first message, it comes only to the first client, I write the second message, it comes only to the second client, I write the third SMS, it comes only to the first, etc.
52ece65a5177441b8f4a5c7f7c9c9521.png
Server Code

package main

import (
  "bufio"
  "fmt"
  "io"
  "log"
  "net"
  "os"
  "strconv"
  "strings"
)

var messages chan string

func main() {
  messages = make(chan string, 10)
  var port int = 3333
  listen, err := net.Listen("tcp4", ":"+strconv.Itoa(port))
  defer listen.Close()
  if err != nil {
    log.Fatalf("Прослушивание порта %d не удалось,\r\n\r\n %s", port, err)
    os.Exit(1)
  }

  go func() {

    log.Printf("Сервер слушает порт: %d", port)
    reader := bufio.NewReader(os.Stdin)
    for {
      fmt.Print("Enter text: ")
      text, _ := reader.ReadString('\n')
      log.Print(text)
      messages <- text
    }

  }()
  for {
    conn, err := listen.Accept()
    if err != nil {
      log.Fatalln(err)
      continue
    }
    go handler(conn)
  }
}
func handler(conn net.Conn) {
  defer conn.Close()
  var (
    buf = make([]byte, 1024)
    r   = bufio.NewReader(conn)
    w   = bufio.NewWriter(conn)
  )
ILOOP:
  for {
    n, err := r.Read(buf)
    data := string(buf[:n])
    switch err {
    case io.EOF:
      break ILOOP
    case nil:
      //log.Println("Получил:", data)
      if isTransportOver(data) {
        break ILOOP
      }
    default:
      log.Fatalf("Ошибка при получении:%s", err)
      return
    }
  }
  //данные из канала
  msg := <-messages
  w.Write([]byte(msg))
  w.Flush()

}
func isTransportOver(data string) (over bool) {
  over = strings.HasSuffix(data, "\r\n\r\n")
  return
}

Why is this happening? thanks in advance

Answer the question

In order to leave comments, you need to log in

1 answer(s)
I
Ilya, 2016-04-22
@lucifer-m

https://gist.github.com/drewolson/3950226 here is a good example of implementing a pool of clients. Just cut out the excess and you'll be fine.
remade that example, with the removal of dead connectors when sending. I cut out a little, it only works for sending to the client.

package main

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

type Client struct {
  writer *bufio.Writer
}

func (client *Client) Write(data string) error {
  fmt.Println("client write")
  _, err := client.writer.WriteString(data)
  err = client.writer.Flush()
  return err
}

func NewClient(connection net.Conn) *Client {
  writer := bufio.NewWriter(connection)
  client := &Client{
    writer: writer,
  }
  return client
}

type ChatRoom struct {
  clients []*Client
}

func (chatRoom *ChatRoom) Broadcast(data string) {
  deleted := 0
  for i := range chatRoom.clients {
    j := i - deleted
    if err := chatRoom.clients[j].Write(data); err != nil {
      fmt.Println(err, "deleted error")
      chatRoom.clients = chatRoom.clients[:j+copy(chatRoom.clients[j:], chatRoom.clients[j+1:])]
      deleted++
    }
  }
}

func (chatRoom *ChatRoom) Join(connection net.Conn) {
  client := NewClient(connection)
  chatRoom.clients = append(chatRoom.clients, client)
}

func NewChatRoom() *ChatRoom {
  chatRoom := &ChatRoom{
    clients: make([]*Client, 0),
  }

  return chatRoom
}

func main() {
  chatRoom := NewChatRoom()

  listener, _ := net.Listen("tcp4", ":3333")
  go readAndSend(chatRoom)

  for {
    conn, err := listener.Accept()
    if err != nil {
      continue
    }
    chatRoom.Join(conn)
  }
}

func readAndSend(chatRoom *ChatRoom) {

  reader := bufio.NewReader(os.Stdin)
  for {
    fmt.Print("Enter text: ")
    text, _ := reader.ReadString('\n')
    log.Print(text)
    chatRoom.Broadcast(text)
  }

}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question