Advertisement
Guest User

Untitled

a guest
Mar 31st, 2015
228
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.43 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4. "bufio"
  5. "errors"
  6. "fmt"
  7. "net"
  8. "strings"
  9. "time"
  10. )
  11.  
  12. type Client struct {
  13. name string
  14. incoming chan string
  15. outgoing chan string
  16. leave chan bool
  17. reader *bufio.Reader
  18. writer *bufio.Writer
  19. conn net.Conn
  20. }
  21.  
  22. func (client *Client) Read() {
  23. for {
  24. line, err := client.reader.ReadString('\n')
  25. if err != nil {
  26. // fmt.Println("\nsocket read err: ", err)
  27. break
  28. }
  29. fmt.Print("r")
  30. client.incoming <- line
  31. }
  32. fmt.Print("R")
  33. client.leave <- true
  34. }
  35.  
  36. func (client *Client) Write() {
  37. for data := range client.outgoing {
  38. _, err := client.writer.WriteString(data)
  39. if err != nil {
  40. // fmt.Println("\nsocket write err: ", err)
  41. break
  42. }
  43. fmt.Print("w")
  44. client.writer.Flush()
  45. }
  46. fmt.Print("W")
  47. client.leave <- true
  48. }
  49.  
  50. func (client *Client) ReadName() (string, error) {
  51. // Get client's name
  52. _, err := client.writer.WriteString("please enter you nickname\r\n")
  53. if err != nil {
  54. return "", errors.New("write error")
  55. }
  56. client.writer.Flush()
  57.  
  58. name, err := client.reader.ReadString('\n')
  59. if err != nil {
  60. return "", errors.New("read error")
  61. }
  62.  
  63. name = strings.TrimSpace(name)
  64. client.name = name
  65. return name, nil
  66. }
  67.  
  68. func (client *Client) Listen() {
  69. go client.Read()
  70. go client.Write()
  71. }
  72.  
  73. func (client *Client) String() string {
  74. return fmt.Sprintf("%p", client.conn)
  75. }
  76.  
  77. func NewClient(conn net.Conn) *Client {
  78. writer := bufio.NewWriter(conn)
  79. reader := bufio.NewReader(conn)
  80.  
  81. client := &Client{
  82. incoming: make(chan string),
  83. outgoing: make(chan string),
  84. leave: make(chan bool),
  85. reader: reader,
  86. writer: writer,
  87. conn: conn,
  88. }
  89.  
  90. return client
  91. }
  92.  
  93. type ChatRoom struct {
  94. clients []*Client
  95. joins chan net.Conn
  96. leaves chan *Client
  97. incoming chan string
  98. outgoing chan string
  99. }
  100.  
  101. func (chatRoom *ChatRoom) Broadcast(data string) {
  102. fmt.Print(len(chatRoom.clients))
  103. for _, client := range chatRoom.clients {
  104. client.outgoing <- data
  105. }
  106. }
  107.  
  108. func (chatRoom *ChatRoom) Join(conn net.Conn) {
  109. client := NewClient(conn)
  110. chatRoom.clients = append(chatRoom.clients, client)
  111. go func() {
  112. name, err := client.ReadName()
  113. if err != nil {
  114. chatRoom.leaves <- client
  115. fmt.Printf("Client %v quit.\n", conn.RemoteAddr())
  116. return
  117. }
  118. comeStr := name + " entered the room.\r\n"
  119. chatRoom.incoming <- comeStr
  120.  
  121. // 开始正常的聊天读写流程
  122. client.Listen()
  123.  
  124. for {
  125. select {
  126. case data := <-client.incoming:
  127. if strings.Contains(data, "stat") {
  128. count := len(chatRoom.clients)
  129. stat := fmt.Sprintf("conn count: %d detail:%s \r\n", count, chatRoom.clients)
  130. client.outgoing <- stat
  131. } else {
  132. // client.outgoing <- data
  133. chatRoom.incoming <- client.name + ": " + data
  134. }
  135. case <-client.leave:
  136. chatRoom.leaves <- client
  137. return
  138. }
  139. }
  140. }()
  141. }
  142.  
  143. // 退出要求:
  144. // 1. 结束读、写循环
  145. // 2. 从列表中移除
  146. // 3. 关闭conn
  147. // 4. 读、写均可能调用destory,需要判断去重
  148. func (chatRoom *ChatRoom) Leaves(client *Client) (success bool) {
  149. // 查找
  150. index := -1
  151. s := chatRoom.clients
  152. for i, _v := range s {
  153. if _v == client {
  154. index = i
  155. break
  156. }
  157. }
  158. if index == -1 {
  159. return false
  160. }
  161.  
  162. // 从列表中移除
  163. i := index
  164. s[i], s[len(s)-1], s = s[len(s)-1], nil, s[:len(s)-1]
  165. chatRoom.clients = s
  166.  
  167. // 宣告退出,这里必须go,否则会死锁
  168. go func() {
  169. chatRoom.incoming <- client.name + " quit.\r\n"
  170. }()
  171.  
  172. // 关闭资源
  173. close(client.outgoing)
  174. client.conn.Close()
  175. // client.conn = nil
  176.  
  177. return true
  178. }
  179.  
  180. func (chatRoom *ChatRoom) Listen() {
  181. go func() {
  182. for {
  183. select {
  184. case data := <-chatRoom.incoming:
  185. chatRoom.Broadcast(data)
  186. case conn := <-chatRoom.joins:
  187. chatRoom.Join(conn)
  188. fmt.Print("-")
  189. case client := <-chatRoom.leaves:
  190. chatRoom.Leaves(client)
  191. fmt.Print("x")
  192. }
  193. }
  194. }()
  195. }
  196.  
  197. func NewChatRoom() *ChatRoom {
  198. chatRoom := &ChatRoom{
  199. clients: make([]*Client, 0),
  200. joins: make(chan net.Conn),
  201. leaves: make(chan *Client),
  202. incoming: make(chan string),
  203. outgoing: make(chan string),
  204. }
  205.  
  206. chatRoom.Listen()
  207.  
  208. return chatRoom
  209. }
  210.  
  211. func main() {
  212. chatRoom := NewChatRoom()
  213.  
  214. l, err := net.Listen("tcp", ":6666")
  215. if err != nil {
  216. fmt.Println("\nfailed to listen on port 6666")
  217. return
  218. }
  219. defer l.Close()
  220.  
  221. for {
  222. conn, _ := l.Accept()
  223. // conn.SetReadDeadline(time.Now().Add(20 * time.Second)) // set 20 seconds timeout
  224. // conn.SetWriteDeadline(time.Now().Add(20 * time.Second)) // set 20 seconds timeout
  225. chatRoom.joins <- conn
  226. }
  227.  
  228. // debug:
  229. time.Sleep(2 * time.Second)
  230. <-time.After(5 * time.Second)
  231. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement