我需要一个写缓冲区吗?

时间:2015-01-28 08:17:13

标签: sockets tcp go

假设我在linux中有一个Tcp服务器,它会为新的连接创建一个新的goroutine。当我想将数据写入tcp连接时,我应该像这样做

conn.Write(data)

或者在goroutine中进行,尤其是写作,就像这样

func writeRoutine(sendChan chan []byte){
      for {
       select {
       case  msg := <- sendChan :
          conn.Write(msg)
       }
      }
}

以防网络繁忙。

简而言之,在写入套接字时,我是否需要使用c / c ++中的写缓冲区?

PS也许我没有清楚地解决这个问题。

1我谈到了服务器,这意味着在Linux中运行的tcp服务器。它将为新的连接创造一个新的goroutine。像这样

   listener, err := net.ListenTCP("tcp", tcpAddr)
    if err != nil {
        log.Error(err.Error())
        os.Exit(-1)
    }
    for {
        conn, err := listener.AcceptTCP()
        if err != nil {
            continue
        }
        log.Debug("Accept a new connection ", conn.RemoteAddr())
        go handleClient(conn)
    }

2我认为我的问题并不太关心代码。我们知道,当我们使用size_t write(int fd, const void *buf, size_t count);在c / c ++中编写套接字fd时,对于tcp服务器,我们需要为代码中的套接字写一个缓冲区,或者可能只有部分数据写成功。我的意思是,我必须这样做吗?

2 个答案:

答案 0 :(得分:2)

你实际上在这里问了两个不同的问题:

1)您应该在我的TCP服务器中使用每个接受的客户端连接goroutine吗? 2)给定一个[]字节,我应该如何写入连接?

对于1),答案是肯定的。这是最适合的模式类型。如果您查看net/http的源代码,您会看到它为每个连接生成一个goroutine。

对于2),你应该做与在c / c ++服务器中做同样的事情:写,检查写了多少并继续写,直到你完成,总是检查错误。以下是有关如何执行此操作的代码段:

func writeConn(data []byte) error {
    var start,c int
    var err error
    for {
      if c, err = conn.Write(data[start:]); err != nil {
          return err
      }
      start += c
      if c == 0 || start == len(data) {
          break
      }
    }
    return nil
}

答案 1 :(得分:1)

  

服务器[...]为新连接创建一个新的goroutine

这是有道理的,因为处理程序goroutines可以在不延迟服务器接受循环的情况下阻塞。

如果您按顺序处理每个请求,那么任何阻塞系统调用都会为所有客户端锁定服务器。

  

goroutine特别是写作

这只适用于您正在编写大量数据或非常慢的连接的用例,例如,您需要处理程序继续解除阻塞。

请注意,这不是通常被理解为&#34;写入缓冲区&#34;。