MENU

【Go】简单实现一个tcp服务器

October 19, 2022 • Golang

序言

众所周知,TCP 协议是当今互联网中的一个非常重要的一环,正是因为有了 TCP 这个协议,才能保证数据能够无误地在设备之间传输

最新的 http3 协议已经抛弃了 tcp 的方式,改用了 udp + quic 来实现了数据的传输

先说一下 TCP/IP 的一些基础:

  1. TCP 是传输层的一个协议,是在 IP (网络层)之上实现的,这个协议一般是操作系统层面就已经实现了
  2. TCP 协议是面向连接的,提供了可靠交付功能(数据传输不会丢失,发送方发送的内容和接收方接收到的内容是一致的)

TCP四层与OSI七层

代码实现

服务端

在实现之前,我们先讲一下思路:

  1. 因为 tcp 是面向连接的,所以我们应该先尝试建立一个连接,建立的过程我们不需要管,操作系统已经帮我们实现了
  2. 然后,我们需要有一个独立的协程负责处理这个连接,监听连接发送过来的数据

按照这个思路,我们简单实现一下:

/*
 * @Author: NorthCity1984
 * @LastEditTime: 2022-10-18 23:47:00
 * @Description
 * @Website: https://grimoire.cn
 * Copyright (c) NorthCity1984 All rights reserved.
 */
package main

import (
    "log"
    "net"
)

/**
负责处理一个连接,监听并打印
*/
func accept(conn net.Conn) {
    defer conn.Close()
    for {
        buffer := [256]byte{}
        n, err := conn.Read(buffer[:])

        if err != nil {
            log.Println(err)
            break
        }
        log.Println("message: ", string(buffer[:n]))
    }
}

func main() {
    // 启动一个 tcp server, 在 3000 端口监听
    listen, err := net.Listen("tcp", ":3000")
    if err != nil {
        log.Fatal(err)
    }
    defer listen.Close()

    for {
        // 等待连接,在没有连接的时候,主进程会在这里阻塞,
        // 直到有 client 请求连接
        conn, err := listen.Accept()
        if err != nil {
            log.Println(err)
            break
        }
        log.Println("accept from:", conn.RemoteAddr())
        // 启动一个 goroutine 处理这个连接
        go accept(conn)
    }
}

客户端

客户端就比服务端更简单了,因为不需要应付多个服务端,那客户端只需要一个 tcp 就够了,我们简单写一下

/*
 * @Author: NorthCity1984
 * @LastEditTime: 2022-10-18 23:53:41
 * @Description:
 * @Website: https://grimoire.cn
 * Copyright (c) NorthCity1984 All rights reserved.
 */
package main

import (
    "fmt"
    "log"
    "net"
)

func main() {
    // 创建一个 tcp 客户端
    conn, err := net.Dial("tcp", ":3000")
    if err != nil {
        log.Panicln(err)
    }
    defer conn.Close()

    for {
        var input string
        fmt.Scan(&input)
        _, err := conn.Write([]byte(input)) // 写入 tcp 连接中
        if err != nil {
            log.Println(err)
            break
        }
    }
}

Tips

因为 tcp 实际传输的是字节,因此你甚至可以用一些同样是 tcp 协议的客户端来请求这个服务端口,比如 ssh,虽然连不上就对了(乐

作者:NorthCity1984
出处:https://grimoire.cn/golang/go-tcp.html
版权:本文《【Go】简单实现一个tcp服务器》版权归作者所有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任