make loop

This commit is contained in:
chai2010
2015-12-26 20:05:30 +08:00
parent 82ec0c025d
commit e15e88dad7
74 changed files with 207 additions and 207 deletions

View File

@@ -22,7 +22,7 @@ func main() {
}
```
然後是broadcaster的goroutine。他的內部變量clients會記録當前建立連接的客戶端集合。其記録的內容是每一個客戶端的消息發channel的"資格"信息。
然後是broadcaster的goroutine。他的內部變量clients會記録當前建立連接的客戶端集合。其記録的內容是每一個客戶端的消息發channel的"資格"信息。
```go
@@ -55,9 +55,9 @@ func broadcaster() {
}
```
broadcaster監聽來自全局的entering和leaving的channel來穫知客戶端的到來和離開事件。當其接收到其中的一個事件時會更新clients集合當該事件是離開行爲時它會關閉客戶端的消息發channel。broadcaster也會監聽全局的消息channel所有的客戶端都會向這個channel中發送消息。當broadcaster接收到什麽消息時就會將其廣播至所有連接到服務端的客戶端。
broadcaster監聽來自全局的entering和leaving的channel來穫知客戶端的到來和離開事件。當其接收到其中的一個事件時會更新clients集合當該事件是離開行爲時它會關閉客戶端的消息發channel。broadcaster也會監聽全局的消息channel所有的客戶端都會向這個channel中發送消息。當broadcaster接收到什麽消息時就會將其廣播至所有連接到服務端的客戶端。
現在讓我們看看每一個客戶端的goroutine。handleConn函數會爲它的客戶端創建一個消息發channel併通過entering channel來通知客戶端的到來。然後它會讀取客戶端發來的每一行文本併通過全局的消息channel來將這些文本發送併爲每條消息帶上發送者的前綴來標明消息身份。當客戶端發送完畢後handleConn會通過leaving這個channel來通知客戶端的離開併關閉連接。
現在讓我們看看每一個客戶端的goroutine。handleConn函數會爲它的客戶端創建一個消息發channel併通過entering channel來通知客戶端的到來。然後它會讀取客戶端發來的每一行文本併通過全局的消息channel來將這些文本發送併爲每條消息帶上發送者的前綴來標明消息身份。當客戶端發送完畢後handleConn會通過leaving這個channel來通知客戶端的離開併關閉連接。
```go
func handleConn(conn net.Conn) {
@@ -87,7 +87,7 @@ func clientWriter(conn net.Conn, ch <-chan string) {
}
```
另外handleConn爲每一個客戶端創建了一個clientWriter的goroutine來接收向客戶端發消息channel中發送的廣播消息併將它們寫入到客戶端的網絡連接。客戶端的讀取方循環會在broadcaster接收到leaving通知併關閉了channel後終止。
另外handleConn爲每一個客戶端創建了一個clientWriter的goroutine來接收向客戶端發消息channel中發送的廣播消息併將它們寫入到客戶端的網絡連接。客戶端的讀取方循環會在broadcaster接收到leaving通知併關閉了channel後終止。
下面演示的是當服務器有兩個活動的客戶端連接併且在兩個窗口中運行的情況使用netcat來聊天
```
@@ -118,4 +118,4 @@ You are 127.0.0.1:64216 127.0.0.1:64216 has arrived
練習8.12: 使broadcaster能夠將arrival事件通知當前所有的客戶端。爲了達成這個目的你需要有一個客戶端的集合併且在entering和leaving的channel中記録客戶端的名字。
練習8.13: 使聊天服務器能夠斷開空閒的客戶端連接比如最近五分鐘之後沒有發送任何消息的那些客戶端。提示可以在其它goroutine中調用conn.Close()來解除Read調用就像input.Scanner()所做的那樣。
練習8.14: 脩改聊天服務器的網絡協議這樣每一個客戶端就可以在entering時可以提供它們的名字。將消息前綴由之前的網絡地址改爲這個名字。
練習8.15: 如果一個客戶端沒有及時地讀取數據可能會導致所有的客戶端被阻塞。脩改broadcaster來跳過一條消息而不是等待這個客戶端一直到其準備好寫。或者爲每一個客戶端的消息發channel建立緩衝區這樣大部分的消息便不會被丟掉broadcaster應該用一個非阻塞的send向這個channel中發消息。
練習8.15: 如果一個客戶端沒有及時地讀取數據可能會導致所有的客戶端被阻塞。脩改broadcaster來跳過一條消息而不是等待這個客戶端一直到其準備好寫。或者爲每一個客戶端的消息發channel建立緩衝區這樣大部分的消息便不會被丟掉broadcaster應該用一個非阻塞的send向這個channel中發消息。