【Go基础】搭建TCP服务端、客户端

- 日理万妓 2022-09-03 14:25 398阅读 0赞

搭建TCP服务端、客户端

  • 搭建TCP服务端、客户端

    • TCP基础介绍
    • 服务端Listen函数
    • 客户端Dial函数
    • 搭建TCP服务端、客户端示例
    • 相关资料

TCP基础介绍

  TCP协议(Transmission Control Protocol)是一个安全、可靠、稳定、有序的数据报传输协议。如果说网络层(通过ip地址)解决了主机识别的问题,那么TCP协议则是(通过端口号)解决了如何识别主机上唯一一个进程的问题。

  TCP还定义数据报的请求序号和确认序号,以确保消息的准确有序。

  TCP通过三次握手、四次挥手,保障传输的安全性。
在这里插入图片描述

服务端Listen函数

Listen函数:

func Listen(network, address string) (Listener, error)

  • network:网络类型,可以填写tcpudp
  • address:设定服务器地址,格式为[ip]:端口, ip可以省略,缺省默认值为0.0.0.0
  • error:返回nil代表无错误,否者存在错误
  • Listener:监听者对象,用于后续的步骤处理

    • Listener

      // A Listener is a generic network listener for stream-oriented protocols.
      //
      // Multiple goroutines may invoke methods on a Listener simultaneously.
      type Listener interface {

      1. // Accept waits for and returns the next connection to the listener.
      2. Accept() (Conn, error)
      3. // Close closes the listener.
      4. // Any blocked Accept operations will be unblocked and return errors.
      5. Close() error
      6. // Addr returns the listener's network address.
      7. Addr() Addr

      }

    • Listener#Accept返回的Conn

      // Conn is a generic stream-oriented network connection.
      //
      // Multiple goroutines may invoke methods on a Conn simultaneously.
      type Conn interface {

      1. // Read reads data from the connection.
      2. // Read can be made to time out and return an error after a fixed
      3. // time limit; see SetDeadline and SetReadDeadline.
      4. Read(b []byte) (n int, err error)
      5. // Write writes data to the connection.
      6. // Write can be made to time out and return an error after a fixed
      7. // time limit; see SetDeadline and SetWriteDeadline.
      8. Write(b []byte) (n int, err error)
      9. // Close closes the connection.
      10. // Any blocked Read or Write operations will be unblocked and return errors.
      11. Close() error
      12. // LocalAddr returns the local network address.
      13. LocalAddr() Addr
      14. // RemoteAddr returns the remote network address.
      15. RemoteAddr() Addr
      16. // SetDeadline sets the read and write deadlines associated
      17. // with the connection. It is equivalent to calling both
      18. // SetReadDeadline and SetWriteDeadline.
      19. //
      20. // A deadline is an absolute time after which I/O operations
      21. // fail instead of blocking. The deadline applies to all future
      22. // and pending I/O, not just the immediately following call to
      23. // Read or Write. After a deadline has been exceeded, the
      24. // connection can be refreshed by setting a deadline in the future.
      25. //
      26. // If the deadline is exceeded a call to Read or Write or to other
      27. // I/O methods will return an error that wraps os.ErrDeadlineExceeded.
      28. // This can be tested using errors.Is(err, os.ErrDeadlineExceeded).
      29. // The error's Timeout method will return true, but note that there
      30. // are other possible errors for which the Timeout method will
      31. // return true even if the deadline has not been exceeded.
      32. //
      33. // An idle timeout can be implemented by repeatedly extending
      34. // the deadline after successful Read or Write calls.
      35. //
      36. // A zero value for t means I/O operations will not time out.
      37. SetDeadline(t time.Time) error
      38. // SetReadDeadline sets the deadline for future Read calls
      39. // and any currently-blocked Read call.
      40. // A zero value for t means Read will not time out.
      41. SetReadDeadline(t time.Time) error
      42. // SetWriteDeadline sets the deadline for future Write calls
      43. // and any currently-blocked Write call.
      44. // Even if write times out, it may return n > 0, indicating that
      45. // some of the data was successfully written.
      46. // A zero value for t means Write will not time out.
      47. SetWriteDeadline(t time.Time) error

      }

客户端Dial函数

Dial函数:

func Dial(network, address string) (Conn, error)

  • network:网络类型,可以填写tcpudp
  • address:设定服务器地址,格式为[ip]:端口, ip可以省略,缺省默认值为0.0.0.0
  • error:返回nil代表无错误,否者存在错误
  • Conn:和服务端通信的连接对象。

    注:Conn对象的具体信息上文已经给出,这里不再赘述。

搭建TCP服务端、客户端示例

  • TCP服务端

    import (

    1. "fmt"
    2. "log"
    3. "net"

    )

    func main() {

    1. // 1. 绑定ip和端口,设置监听
    2. listener, err := net.Listen("tcp", "localhost:8888")
    3. if err != nil {
    4. log.Panic("Failed to Listen", err)
    5. }
    6. // 延迟关闭,释放资源
    7. defer listener.Close()
    8. // 2. 循环等待新连接
    9. for {
    10. // 从连接列表获取新连接
    11. conn, err := listener.Accept()
    12. if err != nil {
    13. fmt.Println("Failed to Accept", err)
    14. }
    15. // 3. 与新连接通信(为了不同步阻塞,这里开启异步协程进行函数调用)
    16. go handle_conn(conn)
    17. }

    }

    /* 处理连接 */
    func handle_conn(conn net.Conn) {

    1. defer conn.Close()
    2. fmt.Println("New connection ", conn.RemoteAddr())
    3. // 通信
    4. buf := make([]byte, 256)
    5. for {
    6. // 从网络中读
    7. readBytesCount, err := conn.Read(buf)
    8. if err != nil {
    9. fmt.Println("Failed to read", err)
    10. break
    11. }
    12. // 提示:buf[:n]的效果为:读取buf[总长度-n]至buf[n]处的字节
    13. fmt.Println("服务端收到数据:\t", string(buf[:readBytesCount]))
    14. // 写回网络 -- 收到什么就写回什么,即:回射服务器
    15. writeByteCount, err := conn.Write(buf[:readBytesCount])
    16. if err != nil {
    17. fmt.Println("Failed to write", err)
    18. break
    19. }
    20. fmt.Printf("write success %d bytes\n", writeByteCount)
    21. }

    }

  • TCP客户端

    import (

    1. "fmt"
    2. "net"
    3. "os"

    )

    func main() {

    1. // 1. 建立连接
    2. conn, err := net.Dial("tcp", "localhost:8888")
    3. if err != nil {
    4. fmt.Println("Failed to Dial")
    5. return
    6. }
    7. // 延迟关闭,释放资源
    8. defer conn.Close()
    9. // 2. 与服务端通信
    10. buf := make([]byte, 256)
    11. for {
    12. // 2.1 从控制台读取输入
    13. readBytesCount, _ := os.Stdin.Read(buf)
    14. // 2.2 写到网络(即:发送请求)
    15. conn.Write(buf[:readBytesCount])
    16. // 2.3 读网络(即:获取响应)
    17. readBytesCount, _ = conn.Read(buf)
    18. // 2.4 输出到控制台
    19. // 提示:buf[:n]的效果为:读取buf[总长度-n]至buf[n]处的字节
    20. os.Stdout.Write(buf[:readBytesCount])
    21. }

    }

  • 通信测试

先启动server端,再启动client端,然后在client端的控制台进行任意输入触发进行TCP请求,

  1. 在server端控制台,可看到来自client的请求信息
    xx
  2. 在client端控制台,可看到来自server端的响应信息
    在这里插入图片描述

^_^ 整理自《Go语言区块链应用开发从入门到精通》高野 编著

^_^ 本文已经被收录进《程序员成长笔记》 ,笔者JustryDeng

发表评论

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

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

相关阅读

    相关 Springboot+NettyTCP服务

    Netty是业界最流行的nio框架之一,它具有功能强大、性能优异、可定制性和可扩展性的优点 Netty的优点: 1.API使用简单,开发入门门槛低。 2.功能十分强大,预

    相关 TCP客户服务

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