2014-09-10 6 views
0

Не знаете, как сформулировать вопрос, и если он действительно относится только к языку, но я пытаюсь сделать это с сервером и клиентом tcp, который будет обмениваться данными между ними, в основном клиент будет передавать большие объемы данных на более мелкие куски на сервер, сервер будет ждать, чтобы читать каждый кусок данных, а затем ответить кодом состояния, который будет считываться клиентом, и на основе этого он будет выполнять другую работу.Golang: разделитель данных клиент/сервер TCP

Я использую функцию ниже как тест прочитать данные от клиента и сервера (обратите внимание, я знаю, что не является совершенным, но это только тестирование):

func createBufferFromConn(conn net.Conn) *bytes.Buffer { 
    buffer := &bytes.Buffer{} 
    doBreak := false 
    for { 
     incoming := make([]byte, BUFFER_SIZE) 

     conn.SetReadDeadline(time.Now().Add(time.Second * 2)) 
     bytesRead, err := conn.Read(incoming) 
     conn.SetReadDeadline(time.Time{}) 

     if err != nil { 
      if err == io.EOF { 
       fmt.Println(err) 
      } else if neterr, ok := err.(net.Error); ok && neterr.Timeout() { 
       fmt.Println(err) 
      } 
      doBreak = true 
     } 

     if doBreak == false && bytesRead == 0 { 
      continue 
     } 

     if bytesRead > 0 { 
      buffer.Write(incoming[:bytesRead]) 
      if bytes.HasSuffix(buffer.Bytes(), []byte("|")) { 
       bb := bytes.Trim(buffer.Bytes(), "|") 
       buffer.Reset() 
       buffer.Write(bb) 
       doBreak = true 
      } 
     } 

     if doBreak { 
      break 
     } 
    } 
    return buffer 
} 

сейчас в моем случае, если я подключаюсь через telnet (код go также включает в себя код client() для подключения к server()), и я нахожу что-то вроде test 12345| достаточно справедливо, все работает отлично, и буфер содержит все байты, написанные с telnet (кроме трубы, которая удаляется вызовом Trim()).

Если я удалю блок if bytes.HasSuffix(buffer.Bytes(), []byte("|")) { из кода, то я получу таймаут через 2 секунды, опять же, как и ожидалось, потому что в этот промежуток времени не получено данных и сервер закрывает соединение, и если я не сделаю установите конечный срок чтения из соединения, он будет долго ждать чтения данных и никогда не узнает, когда остановиться.

Я предполагаю, что мой вопрос заключается в том, что если я отправляю несколько фрагментов данных, мне нужно указать собственный разделитель, чтобы я знал, когда прекратить чтение из соединения и не ждать навсегда или ждать, пока сервер не закроет тайм-аут связь ?

ответ

3

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

Да. TCP - это протокол потока, и нет способа определить, где сообщения в протоколе начинаются и останавливаются, не создавая их каким-либо образом.

Более распространенный метод кадрирования, используемый для отправки префикса размера, чтобы получатель знал, сколько нужно читать без, чтобы буферировать результаты и искать разделитель. Это может быть так же просто, как message_length:data.... (см. Также netstring и type-length-value).

+0

Спасибо, это действительно имеет смысл в связи с тем, что я получал от своих тестов. Я буду больше смотреть на методы кадрирования, которые вы разместили, и посмотреть, что я могу использовать, эта информация идеально подходит. – Twisted1919

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