dongqiyang3711 2018-04-11 20:35 采纳率: 100%
浏览 58
已采纳

golang聊天服务器/选择语句

I have the following piece of code that implements a simple tcp chat server written in go. I have trouble understanding where in the code the connection is sent through the "partner channel". I see that when the first user connects, the select statement just waits until the next user joins. But when the second user joins, how does the code send information through the channel and know to select which case?

package main

import (
    "io"
  "net"
  "log"
  "fmt"
)
const listnAddr = "localhost:4000"

func main(){
  l , err := net.Listen("tcp",listnAddr)
  if err != nil {
    log.Fatal(err)
  }
  for {
    c , err := l.Accept()
    if c!= nil{
      fmt.Printf("ok")
    }
    if err != nil {
      log.Fatal(err)
    }
    go match(c)
  }
}
var partner = make(chan io.ReadWriteCloser)

func match(c io.ReadWriteCloser){
  fmt.Fprint(c,"waiting for a partner...")
  select{
    case partner <- c:
      //now handled by the other goroutine
    case p := <-partner:
      chat(p,c)
  }
  fmt.Printf("waiting")

}

func chat(a, b io.ReadWriteCloser) {
    fmt.Fprintln(a, "Found one! Say hi.")
    fmt.Fprintln(b, "Found one! Say hi.")
    go io.Copy(a, b)
    io.Copy(b, a)
}

</div>
  • 写回答

1条回答 默认 最新

  • duanlang0025 2018-04-11 21:09
    关注
    var partner = make(chan io.ReadWriteCloser)
    
    func match(c io.ReadWriteCloser) {
        fmt.Fprint(c, "waiting for a partner...")
        select {
        case partner <- c:
            //now handled by the other goroutine
        case p := <-partner:
            chat(p, c)
        }
        fmt.Printf("waiting")
    }
    

    The match function is called once, every time a client connects. I believe that much is clear.

    The first case of the select statement wants to sends the TCP connection down the partner channel. The second case wants to receive a TCP connection from the partner channel.

    If multiple cases of a select statements are ready to proceed, the runtime picks one at random.

    When match is called for the first time (let's call this M1), neither case can proceed because the channel is unbuffered; M1 blocks and waits. When match is called for the second time (M2), it is actually unpredictable what exactly happens next, but the effect is the same.

    Let's assume that M2 tries to proceed with the first case, sending the second connection to partner. This will work, because M1 is ready to receive it. So M2 proceeds with the first case, and M1 proceeds with the second case and calls chat.

    Let's now go back and assume that M2 tries to proceed with the second case, receiving another connection from partner. This also works, because M1 is ready to send the first connection. So in this case M1 proceeds with the first case, and M2 proceeds with the second case and calls chat.

    So chat is called in both cases, but the order of the arguments is not deterministic. In this case it works either way, because the communication is bi-directional and we don't care who came first.

    And then it just starts all over again.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 ansys fluent计算闪退
  • ¥15 有关wireshark抓包的问题
  • ¥15 需要写计算过程,不要写代码,求解答,数据都在图上
  • ¥15 向数据表用newid方式插入GUID问题
  • ¥15 multisim电路设计
  • ¥20 用keil,写代码解决两个问题,用库函数
  • ¥50 ID中开关量采样信号通道、以及程序流程的设计
  • ¥15 U-Mamba/nnunetv2固定随机数种子
  • ¥15 vba使用jmail发送邮件正文里面怎么加图片
  • ¥15 vb6.0如何向数据库中添加自动生成的字段数据。