golang实现tcp客户端服务端程序

我不是女神ヾ 2022-12-31 01:20 339阅读 0赞

服务端代码:

  1. package main
  2. import (
  3. "bufio"
  4. "errors"
  5. "flag"
  6. "fmt"
  7. "net"
  8. "os"
  9. "strconv"
  10. )
  11. // 指定一个命令行参数的名字
  12. var port int
  13. func Init() {
  14. flag.IntVar(&port, "port", 8081, "set your server port")
  15. }
  16. func main() {
  17. // 初始化命令行变量
  18. Init()
  19. flag.Parse()
  20. // 监听端口
  21. portStr := strconv.Itoa(port)
  22. if portStr == "" {
  23. fmt.Println("端口不正确,请确认")
  24. return
  25. }
  26. listen, err := net.Listen("tcp", ":" + portStr)
  27. if err != nil {
  28. fmt.Println("监听端口" + portStr + "失败", err)
  29. }
  30. fmt.Println("监听" + portStr + "成功!")
  31. for {
  32. // 等待连接
  33. conn, err := listen.Accept()
  34. if err != nil {
  35. fmt.Println("建立连接失败了")
  36. }
  37. fmt.Println("建立连接成功了")
  38. // STEP - 1 处理发送消息
  39. go func(conn net.Conn) {
  40. handleSend(conn)
  41. }(conn)
  42. // STEP - 2 处理接收消息
  43. // 必须要这个for 保持程序一直处于唤醒状态,一直读取conn里面的流
  44. var receiveError error
  45. for {
  46. //go func(conn net.Conn) {
  47. receiveError= handleReceive(conn)
  48. if receiveError !=nil {
  49. break
  50. }
  51. //}(conn)
  52. }
  53. if receiveError != nil {
  54. break
  55. }
  56. }
  57. }
  58. func handleReceive(conn net.Conn) error{
  59. //fmt.Println("handleReceive Method")
  60. buff := make([]byte, 4096)
  61. cnt, err := conn.Read(buff)
  62. if cnt == 0 || err != nil {
  63. fmt.Println("[WARN]-----断开连接------")
  64. fmt.Println("[WARN]------END--------")
  65. return errors.New("连接错误")
  66. }
  67. receiveData := string(buff)
  68. fmt.Println("你收到了消息:", receiveData)
  69. return nil
  70. }
  71. func handleSend(conn net.Conn) {
  72. // 读取命令行里面的字符
  73. //fmt.Println("handleSend Method")
  74. r := bufio.NewReader(os.Stdin)
  75. var line string
  76. for {
  77. fmt.Println("Send Message->")
  78. rawLineBytes, _, _ := r.ReadLine()
  79. line = string(rawLineBytes)
  80. if len(line) < 1 {
  81. continue
  82. }
  83. // 发送
  84. fmt.Println("你发送了数据: [YOU]:" + line)
  85. //conn.Write([]byte("[SERVER]: " + line))
  86. _, err := fmt.Fprintf(conn, "[SERVER]: " + line)
  87. if err != nil {
  88. fmt.Println("发送数据失败")
  89. }
  90. }
  91. }
  92. 启动代码:
  93. ```go
  94. go run main.go -port=8081

客户端代码:

  1. package main
  2. import (
  3. "bufio"
  4. "errors"
  5. "flag"
  6. "fmt"
  7. "io"
  8. "net"
  9. "os"
  10. "time"
  11. )
  12. var serverPort int
  13. var serverIP string
  14. func Init() {
  15. flag.IntVar(&serverPort, "serverPort", 8081, "set the server PORT you connect with")
  16. flag.StringVar(&serverIP, "serverIP", "127.0.0.1", "set the server IP you will connect with")
  17. }
  18. func main() {
  19. // 初始化命令行参数
  20. Init()
  21. flag.Parse()
  22. // 连接server端
  23. serverAddress := fmt.Sprintf("%s:%d", serverIP, serverPort)
  24. conn, err := net.DialTimeout("tcp", serverAddress, time.Second * 3)
  25. // 连接失败
  26. if err != nil {
  27. fmt.Println(fmt.Sprintf("连接[%s]失败了", serverAddress))
  28. return
  29. }
  30. // 连接成功
  31. fmt.Println(fmt.Sprintf("建立连接成功了[%s] !", serverAddress))
  32. // 往conn这个写一个消息
  33. fmt.Fprintf(conn, "HEAD / HTTP/1.0\r\n\r\n")
  34. // STEP - 1 处理发送消息
  35. go func(conn net.Conn) {
  36. handleSend(conn)
  37. }(conn)
  38. // STEP - 2 处理接收消息
  39. // 必须要这个for 保持程序一直处于唤醒状态,一直读取conn里面的流
  40. for {
  41. err := handleReceive(conn)
  42. if err != nil {
  43. break
  44. }
  45. }
  46. }
  47. func handleReceive(conn net.Conn) error {
  48. //fmt.Println("handleReceive Method")
  49. buff := make([]byte, 4096)
  50. cnt, err := conn.Read(buff)
  51. // 收到的数据长度为0
  52. //if cnt == 0 || err != nil {
  53. if err != nil {
  54. fmt.Println("断开连接")
  55. fmt.Println("----------END-----------")
  56. fmt.Println(err, cnt, err == io.EOF)
  57. return errors.New("断开连接了")
  58. }
  59. fmt.Println("你收到了消息:", string(buff))
  60. return nil
  61. }
  62. func handleSend(conn net.Conn) {
  63. //fmt.Println("handleSend Method")
  64. r := bufio.NewReader(os.Stdin)
  65. var line string
  66. for {
  67. fmt.Println("Send Message->")
  68. rawLineBytes, _, _ := r.ReadLine()
  69. line = string(rawLineBytes)
  70. if len(line) < 1 {
  71. continue
  72. }
  73. fmt.Println("你发送了数据: [YOU]:" + line)
  74. _, err := fmt.Fprintf(conn, "[CLIENT]: " + line)
  75. if cnt == 0||err != nil {
  76. fmt.Println("发送数据失败")
  77. }
  78. }
  79. }

启动代码:

  1. go run main.go -serverPort=8081 -serverIp=127.0.0.1

tips:

1, 这个简单的网络应用有几个关键点
     A : for 循环 等待连接/ 等待用户从命令行输入
     B :go routine 协程处理发送或者接受消息,因为这两个动作,都是需要程序block住,所以必须 要用go routine

2,注意启动的时候端口占用情况,也许8081被占用

3,go build 的时候,windows/mac/linux平台有不同的命令。(自行搜索下

发表评论

表情:
评论列表 (有 0 条评论,339人围观)

还没有评论,来说两句吧...

相关阅读

    相关 TCP客户服务

    简介 socket(简称:套接字)是进程之间通信的一个工具,好比现实中的插座,所有的家用电器要想工作都是基于插座进行,进程之间想要进行网络通信需要基于这个socket,负