<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 4.14\. Multiplexing 基于管道,我們可以很容易實現一個支持多路客戶端的服務器程序。采用的技巧是將每個客戶端私有的通信管道 作為消息的一部分發送給服務器,然后服務器通過這些管道和客戶端獨立通信。現實中的服務器實現都很復雜, 我們這里只給出一個服務器的簡單實現來展現前面描述的技巧。首先定義一個"request"類型,里面包含一個 客戶端的通信管道。 ``` 09 type request struct { 10 a, b int 11 replyc chan int 12 } ``` 服務器對客戶端發送過來的兩個整數進行運算。下面是具體的函數,函數在運算完之后將結構通過結構中的 管道返回給客戶端。 ``` 14 type binOp func(a, b int) int 16 func run(op binOp, req *request) { 17 reply := op(req.a, req.b) 18 req.replyc <- reply 19 } ``` 第14行現定義一個"binOp"函數類型,用于對兩個整數進行運算。 服務器routine線程是一個無限循環,它接受客戶端請求。然后為每個客戶端啟動一個獨立的routine線程, 用于處理客戶數據(不會被某個客戶端阻塞)。 ``` 21 func server(op binOp, service chan *request) { 22 for { 23 req := <-service 24 go run(op, req) // don't wait for it 25 } 26 } ``` 啟動服務器的方法也是一個類似的routine線程,然后返回服務器的請求管道。 ``` 28 func startServer(op binOp) chan *request { 29 req := make(chan *request) 30 go server(op, req) 31 return req 32 } ``` 這里是一個簡單的測試。首先啟動服務器,處理函數為計算兩個整數的和。接著向服務器發送"N"個請求(無阻塞)。 當所有請求都發送完了之后,再進行驗證返回結果。 ``` 34 func main() { 35 adder := startServer(func(a, b int) int { return a + b }) 36 const N = 100 37 var reqs [N]request 38 for i := 0; i < N; i++ { 39 req := &reqs[i] 40 req.a = i 41 req.b = i + N 42 req.replyc = make(chan int) 43 adder <- req 44 } 45 for i := N-1; i >= 0; i-- { // doesn't matter what order 46 if <-reqs[i].replyc != N + 2*i { 47 fmt.Println("fail at", i) 48 } 49 } 50 fmt.Println("done") 51 } ``` 前面的服務器程序有個小問題:當main函數退出之后,服務器沒有關閉,而且可能有一些客戶端被阻塞在 管道通信中。為了處理這個問題,我們可給服務器增加一個控制管道,用于退出服務器。 ``` 32 func startServer(op binOp) (service chan *request, quit chan bool) { 33 service = make(chan *request) 34 quit = make(chan bool) 35 go server(op, service, quit) 36 return service, quit 37 } ``` 首先給"server"函數增加一個控制管道參數,然后這樣使用: ``` 21 func server(op binOp, service chan *request, quit chan bool) { 22 for { 23 select { 24 case req := <-service: 25 go run(op, req) // don't wait for it 26 case <-quit: 27 return 28 } 29 } 30 } ``` 在服務器函數中,"select"操作服用于從多個通訊管道中選擇一個就緒的管道。如果所有的管道都沒有數據, 那么將等待知道有任意一個管道有數據。如果有多個管道就緒,則隨即選擇一個。服務器處理客戶端請求,如果 有退出消息則退出。 最后是在main函數中保存"quit"管道,然后在退出的時候向服務線程發送停止命令。 ``` 40 adder, quit := startServer(func(a, b int) int { return a + b }) ... 55 quit <- true ``` 當然,Go語言及并行編程要討論的問題很多。這個入門只是給出一些簡單的例子。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看