2015-07-18 6 views
0

Я работаю над сетевыми функциями Cloud Server, используя язык программирования Go. И я столкнулся с проблемой с с одинаковым TCPconn в то же время от разных Goroutines.Go - Чтение данных из TCP-соединения из нескольких считывателей

Вот простой пример

package main 

import (
    "fmt" 
    "net" 
) 

func main() { 
    addr, _ := net.ResolveTCPAddr("tcp", ":8888") 
    listener, _ := net.ListenTCP("tcp", addr) 

    for { 
     conn, err := listener.AcceptTCP() 
     if err != nil { 
      fmt.Println(err) 
      return 
     } 
     go Handle(conn) // output always coming from here 
     go Handle(conn) 
    } 
} 

func Handle(conn *net.TCPConn) { 
    data := make([]byte, 1024) 
    fmt.Println("Ok") 
    for { 
     len_data, err := conn.Read(data) 
     fmt.Println(err) 
     fmt.Println(len_data) 
    } 
} 

В этом примере выход консоли всегда наступающем от 1-го goroutine go Handle(conn) ...

Как сделать функциональные возможности чтения из 2 Goroutines в то же время?

Благодаря

ответ

0

Запуск однопользовательского идут обычные для выполнения conn.Read (данных) и поместить результат в канал.

Затем (одновременно, не дожидаясь завершения первой процедуры go), запустите несколько программ для чтения с этого канала.

Вы не хотите напрямую читать из conn одновременно из процедуры множественного доступа, так как он не является потокобезопасным (тот факт, что он работает, и работает только на одной рутине, вероятно, потому, что ваш MAXGOPROCS == 1).

+0

Это означает, что он должен был бы держать все данные в памяти. – OneOfOne

+0

Нет, если он установил правильный размер буфера для канала. – Cooy

+0

нет? он должен будет создать канал для каждого запроса, прочитать все данные в буфер, отправить его по каналу. – OneOfOne

1

Один из способов сделать это является использование io.MultiWriter и io.Pipe:

func main() { 
    var wg sync.WaitGroup 
    r := strings.NewReader(hello) 
    pr1, pw1 := io.Pipe() 
    pr2, pw2 := io.Pipe() 
    pr3, pw3 := io.Pipe() 
    mw := io.MultiWriter(pw1, pw2, pw3) 

    wg.Add(4) 
    go process(&wg, 0, pr1) 
    go process(&wg, 1, pr2) 
    go process(&wg, 2, pr3) 
    go func() { 
     io.Copy(mw, r) 
     pw1.Close() 
     pw2.Close() 
     pw3.Close() 
     wg.Done() 
    }() 

    wg.Wait() 
} 

playground

+1

Или, [используя разрезы произвольного размера] (https://play.golang.org/p/IYZ-Jnq4g3), а не из жесткого кодированного вентилятора из трех (и это также пропускает любую ошибку чтения для каждого процессора). –

-1

ИТАК в первую очередь. Вы делаете это неправильно друг.

Что нужно сделать, это создать рабочих (создать), создать канал и объединить этот канал с входящими соединениями. Чем вы должны брать ту же связь внутри рабочего и обрабатывать ее. Таким образом, вы получите X одновременных работников, которые работают против ваших соединений.

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

http://play.golang.org/p/YkQVmBEWly

Надеется, что это помогает,

Смежные вопросы