tcp编程

  • 服务端
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "net"
  6. )
  7. func main() {
  8. listen, err := net.Listen("tcp", "127.0.0.1:20000") //监听端口
  9. if err != nil {
  10. fmt.Println("listen failed, err:", err)
  11. return
  12. }
  13. for {
  14. conn, err := listen.Accept() //建立连接
  15. if err != nil {
  16. fmt.Println("accept failed, err:", err)
  17. continue
  18. }
  19. go process(conn) //启动一个goroutine处理连接
  20. }
  21. }
  22. func process(conn net.Conn) {
  23. defer conn.Close() //关闭连接
  24. for {
  25. reader := bufio.NewReader(conn)
  26. var buf [128]byte
  27. n, err := reader.Read(buf[:]) //读取数据
  28. if err != nil {
  29. fmt.Println("read from client failed, err:", err)
  30. break
  31. }
  32. recvStr := string(buf[:n])
  33. fmt.Println("接收到客户端发来的数据:", recvStr)
  34. conn.Write([]byte(recvStr)) //发送数据
  35. }
  36. }
  • 客户端
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "net"
  6. "os"
  7. "strings"
  8. )
  9. func main() {
  10. conn, err := net.Dial("tcp", "127.0.0.1:20000") //建立与服务端的连接
  11. if err != nil {
  12. fmt.Println("err :", err)
  13. return
  14. }
  15. defer conn.Close() //关闭连接
  16. inputReader := bufio.NewReader(os.Stdin)
  17. for {
  18. input, _ := inputReader.ReadString('\n')
  19. inputInfo := strings.Trim(input, "\r\n")
  20. if strings.ToUpper(inputInfo) == "Q" {
  21. return
  22. }
  23. _, err := conn.Write([]byte(inputInfo)) //发送数据
  24. if err != nil {
  25. return
  26. }
  27. buf := [512]byte{}
  28. n, err := conn.Read(buf[:])
  29. if err != nil {
  30. fmt.Println("recv failed, err", err)
  31. return
  32. }
  33. fmt.Println("接收到服务端发来的数据: ", string(buf[:n]))
  34. }
  35. }

UDP编程

  • 服务端
  1. package main
  2. import (
  3. "fmt"
  4. "net"
  5. )
  6. func main() {
  7. listen, err := net.ListenUDP("udp", &net.UDPAddr{
  8. IP: net.IPv4(0, 0, 0, 0),
  9. Port: 30000,
  10. })
  11. if err != nil {
  12. fmt.Println("listen failed, err:", err)
  13. return
  14. }
  15. defer listen.Close()
  16. for {
  17. var data [1024]byte
  18. n, addr, err := listen.ReadFromUDP(data[:]) // 接收数据
  19. if err != nil {
  20. fmt.Println("read udp failed, err:", err)
  21. continue
  22. }
  23. fmt.Printf("data:%v addr:%v count:%v\n", string(data[:n]), addr, n)
  24. _, err = listen.WriteToUDP(data[:n], addr) // 发送数据
  25. if err != nil {
  26. fmt.Println("write to udp failed, err:", err)
  27. continue
  28. }
  29. }
  30. }
  • 客户端
  1. package main
  2. import (
  3. "fmt"
  4. "net"
  5. )
  6. func main() {
  7. socket, err := net.DialUDP("udp", nil, &net.UDPAddr{
  8. IP: net.IPv4(0, 0, 0, 0),
  9. Port: 30000,
  10. })
  11. if err != nil {
  12. fmt.Println("连接服务端失败,err:", err)
  13. return
  14. }
  15. defer socket.Close()
  16. sendData := []byte("Hello server")
  17. _, err = socket.Write(sendData) // 发送数据
  18. if err != nil {
  19. fmt.Println("发送数据失败,err:", err)
  20. return
  21. }
  22. data := make([]byte, 4096)
  23. n, remoteAddr, err := socket.ReadFromUDP(data) // 接收数据
  24. if err != nil {
  25. fmt.Println("接收数据失败,err:", err)
  26. return
  27. }
  28. fmt.Printf("recv:%v addr:%v count:%v\n", string(data[:n]), remoteAddr, n)
  29. }

HTTP编程

  • 服务端
  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. )
  6. func main() {
  7. //http://127.0.0.1:8000/go
  8. // 单独写回调函数
  9. http.HandleFunc("/go", myHandler)
  10. // addr:监听的地址
  11. // handler:回调函数
  12. http.ListenAndServe("127.0.0.1:8000", nil)
  13. }
  14. // handler函数
  15. func myHandler(w http.ResponseWriter, r *http.Request) {
  16. fmt.Println(r.RemoteAddr, "连接成功")
  17. // 请求方式:GET POST DELETE PUT UPDATE
  18. fmt.Println("method:", r.Method)
  19. // /go
  20. fmt.Println("url:", r.URL.Path)
  21. fmt.Println("header:", r.Header)
  22. fmt.Println("body:", r.Body)
  23. // 回复
  24. w.Write([]byte("你好"))
  25. }
  • 客户端
  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "net/http"
  6. )
  7. func main() {
  8. //resp, _ := http.Get("http://www.baidu.com")
  9. //fmt.Println(resp)
  10. resp, _ := http.Get("http://127.0.0.1:8000/go")
  11. defer resp.Body.Close()
  12. // 200 OK
  13. fmt.Println(resp.Status)
  14. fmt.Println(resp.Header)
  15. buf := make([]byte, 1024)
  16. for {
  17. // 接收服务端信息
  18. n, err := resp.Body.Read(buf)
  19. if err != nil && err != io.EOF {
  20. fmt.Println(err)
  21. return
  22. } else {
  23. fmt.Println("读取完毕")
  24. res := string(buf[:n])
  25. fmt.Println(res)
  26. break
  27. }
  28. }
  29. }

websocket聊天室

server.go文件代码

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. "github.com/gorilla/mux"
  6. )
  7. func main() {
  8. router := mux.NewRouter()
  9. go h.run()
  10. router.HandleFunc("/ws", myws)
  11. if err := http.ListenAndServe("127.0.0.1:8080", router); err != nil {
  12. fmt.Println("err:", err)
  13. }
  14. }

hub.go文件代码

  1. package main
  2. import "encoding/json"
  3. var h = hub{
  4. c: make(map[*connection]bool),
  5. u: make(chan *connection),
  6. b: make(chan []byte),
  7. r: make(chan *connection),
  8. }
  9. type hub struct {
  10. c map[*connection]bool
  11. b chan []byte
  12. r chan *connection
  13. u chan *connection
  14. }
  15. func (h *hub) run() {
  16. for {
  17. select {
  18. case c := <-h.r:
  19. h.c[c] = true
  20. c.data.Ip = c.ws.RemoteAddr().String()
  21. c.data.Type = "handshake"
  22. c.data.UserList = user_list
  23. data_b, _ := json.Marshal(c.data)
  24. c.sc <- data_b
  25. case c := <-h.u:
  26. if _, ok := h.c[c]; ok {
  27. delete(h.c, c)
  28. close(c.sc)
  29. }
  30. case data := <-h.b:
  31. for c := range h.c {
  32. select {
  33. case c.sc <- data:
  34. default:
  35. delete(h.c, c)
  36. close(c.sc)
  37. }
  38. }
  39. }
  40. }
  41. }

data.go文件代码

  1. package main
  2. type Data struct {
  3. Ip string `json:"ip"`
  4. User string `json:"user"`
  5. From string `json:"from"`
  6. Type string `json:"type"`
  7. Content string `json:"content"`
  8. UserList []string `json:"user_list"`
  9. }

connection.go文件代码

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "github.com/gorilla/websocket"
  7. )
  8. type connection struct {
  9. ws *websocket.Conn
  10. sc chan []byte
  11. data *Data
  12. }
  13. var wu = &websocket.Upgrader{ReadBufferSize: 512,
  14. WriteBufferSize: 512, CheckOrigin: func(r *http.Request) bool { return true }}
  15. func myws(w http.ResponseWriter, r *http.Request) {
  16. ws, err := wu.Upgrade(w, r, nil)
  17. if err != nil {
  18. return
  19. }
  20. c := &connection{sc: make(chan []byte, 256), ws: ws, data: &Data{}}
  21. h.r <- c
  22. go c.writer()
  23. c.reader()
  24. defer func() {
  25. c.data.Type = "logout"
  26. user_list = del(user_list, c.data.User)
  27. c.data.UserList = user_list
  28. c.data.Content = c.data.User
  29. data_b, _ := json.Marshal(c.data)
  30. h.b <- data_b
  31. h.r <- c
  32. }()
  33. }
  34. func (c *connection) writer() {
  35. for message := range c.sc {
  36. c.ws.WriteMessage(websocket.TextMessage, message)
  37. }
  38. c.ws.Close()
  39. }
  40. var user_list = []string{}
  41. func (c *connection) reader() {
  42. for {
  43. _, message, err := c.ws.ReadMessage()
  44. if err != nil {
  45. h.r <- c
  46. break
  47. }
  48. json.Unmarshal(message, &c.data)
  49. switch c.data.Type {
  50. case "login":
  51. c.data.User = c.data.Content
  52. c.data.From = c.data.User
  53. user_list = append(user_list, c.data.User)
  54. c.data.UserList = user_list
  55. data_b, _ := json.Marshal(c.data)
  56. h.b <- data_b
  57. case "user":
  58. c.data.Type = "user"
  59. data_b, _ := json.Marshal(c.data)
  60. h.b <- data_b
  61. case "logout":
  62. c.data.Type = "logout"
  63. user_list = del(user_list, c.data.User)
  64. data_b, _ := json.Marshal(c.data)
  65. h.b <- data_b
  66. h.r <- c
  67. default:
  68. fmt.Print("========default================")
  69. }
  70. }
  71. }
  72. func del(slice []string, user string) []string {
  73. count := len(slice)
  74. if count == 0 {
  75. return slice
  76. }
  77. if count == 1 && slice[0] == user {
  78. return []string{}
  79. }
  80. var n_slice = []string{}
  81. for i := range slice {
  82. if slice[i] == user && i == count {
  83. return slice[:count]
  84. } else if slice[i] == user {
  85. n_slice = append(slice[:i], slice[i+1:]...)
  86. break
  87. }
  88. }
  89. fmt.Println(n_slice)
  90. return n_slice
  91. }

local.html文件代码

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title></title>
  5. <meta http-equiv="content-type" content="text/html;charset=utf-8">
  6. <style>
  7. p {
  8. text-align: left;
  9. padding-left: 20px;
  10. }
  11. </style>
  12. </head>
  13. <body>
  14. <div style="width: 800px;height: 600px;margin: 30px auto;text-align: center">
  15. <h1>演示聊天室</h1>
  16. <div style="width: 800px;border: 1px solid gray;height: 300px;">
  17. <div style="width: 200px;height: 300px;float: left;text-align: left;">
  18. <p><span>当前在线:</span><span id="user_num">0</span></p>
  19. <div id="user_list" style="overflow: auto;">
  20. </div>
  21. </div>
  22. <div id="msg_list" style="width: 598px;border: 1px solid gray; height: 300px;overflow: scroll;float: left;">
  23. </div>
  24. </div>
  25. <br>
  26. <textarea id="msg_box" rows="6" cols="50" onkeydown="confirm(event)"></textarea><br>
  27. <input type="button" value="发送" onclick="send()">
  28. </div>
  29. </body>
  30. </html>
  31. <script type="text/javascript">
  32. var uname = prompt('请输入用户名', 'user' + uuid(8, 16));
  33. var ws = new WebSocket("ws://127.0.0.1:8080/ws");
  34. ws.onopen = function () {
  35. var data = "系统消息:建立连接成功";
  36. listMsg(data);
  37. };
  38. ws.onmessage = function (e) {
  39. var msg = JSON.parse(e.data);
  40. var sender, user_name, name_list, change_type;
  41. switch (msg.type) {
  42. case 'system':
  43. sender = '系统消息: ';
  44. break;
  45. case 'user':
  46. sender = msg.from + ': ';
  47. break;
  48. case 'handshake':
  49. var user_info = {'type': 'login', 'content': uname};
  50. sendMsg(user_info);
  51. return;
  52. case 'login':
  53. case 'logout':
  54. user_name = msg.content;
  55. name_list = msg.user_list;
  56. change_type = msg.type;
  57. dealUser(user_name, change_type, name_list);
  58. return;
  59. }
  60. var data = sender + msg.content;
  61. listMsg(data);
  62. };
  63. ws.onerror = function () {
  64. var data = "系统消息 : 出错了,请退出重试.";
  65. listMsg(data);
  66. };
  67. function confirm(event) {
  68. var key_num = event.keyCode;
  69. if (13 == key_num) {
  70. send();
  71. } else {
  72. return false;
  73. }
  74. }
  75. function send() {
  76. var msg_box = document.getElementById("msg_box");
  77. var content = msg_box.value;
  78. var reg = new RegExp("\r\n", "g");
  79. content = content.replace(reg, "");
  80. var msg = {'content': content.trim(), 'type': 'user'};
  81. sendMsg(msg);
  82. msg_box.value = '';
  83. }
  84. function listMsg(data) {
  85. var msg_list = document.getElementById("msg_list");
  86. var msg = document.createElement("p");
  87. msg.innerHTML = data;
  88. msg_list.appendChild(msg);
  89. msg_list.scrollTop = msg_list.scrollHeight;
  90. }
  91. function dealUser(user_name, type, name_list) {
  92. var user_list = document.getElementById("user_list");
  93. var user_num = document.getElementById("user_num");
  94. while(user_list.hasChildNodes()) {
  95. user_list.removeChild(user_list.firstChild);
  96. }
  97. for (var index in name_list) {
  98. var user = document.createElement("p");
  99. user.innerHTML = name_list[index];
  100. user_list.appendChild(user);
  101. }
  102. user_num.innerHTML = name_list.length;
  103. user_list.scrollTop = user_list.scrollHeight;
  104. var change = type == 'login' ? '上线' : '下线';
  105. var data = '系统消息: ' + user_name + ' 已' + change;
  106. listMsg(data);
  107. }
  108. function sendMsg(msg) {
  109. var data = JSON.stringify(msg);
  110. ws.send(data);
  111. }
  112. function uuid(len, radix) {
  113. var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
  114. var uuid = [], i;
  115. radix = radix || chars.length;
  116. if (len) {
  117. for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
  118. } else {
  119. var r;
  120. uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
  121. uuid[14] = '4';
  122. for (i = 0; i < 36; i++) {
  123. if (!uuid[i]) {
  124. r = 0 | Math.random() * 16;
  125. uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
  126. }
  127. }
  128. }
  129. return uuid.join('');
  130. }
  131. </script>