1.1go语言Socket

Socket编程基本原理

Socket编程是指在网络编程中使用Socket接口进行应用程序开发的过程。Socket(套接字)是网络通信中的一个基本概念,是一个抽象的数据结构,用于描述网络中的一个端点。Socket包含了IP地址、端口号、协议类型等信息,用于标识网络中的一个特定的进程或设备。

Socket编程基于两个概念:客户端和服务器。客户端是指发起请求的一方,服务器是指提供服务的一方。通过在网络上建立连接,客户端可以向服务器发送请求,服务器则处理请求并将响应返回给客户端。

Socket编程需要使用一种特殊的协议,这种协议包含了一系列规定的数据格式和交互方式。目前主流的Socket协议有TCP和UDP。TCP协议是一种面向连接的协议,提供数据传输的可靠性。UDP协议则是一种无连接的协议,数据传输不可靠但速度快。

  • TCP(传输控制协议)​:面向连接,可靠,有序,基于字节流。
  • UDP(用户数据报协议)​:无连接,不可靠,无序,基于数据报。

Go 语言提供了强大的 net 包,简化了 Socket 编程,使得开发者无需直接操作底层的系统调用即可实现网络通信。


TCP Socket 编程

TCP 是一种面向连接的协议,适用于需要可靠数据传输的场景。

服务器端实现

以下是一个简单的 TCP 服务器示例,它监听指定端口,接受客户端连接,并回显接收到的消息。

package main

import (
    "bufio"
    "fmt"
    "net"
)

func handleConnection(conn net.Conn) {
    defer conn.Close()
    reader := bufio.NewReader(conn)
    for {
        // 读取客户端发送的数据
        message, err := reader.ReadString('\n')
        if err != nil {
            fmt.Println("读取数据错误:", err)
            break
        }
        fmt.Printf("收到消息: %s", message)
        // 回显消息给客户端
        conn.Write([]byte("Echo: " + message))
    }
}

func main() {
    // 监听本地 8080 端口
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        fmt.Println("监听端口失败:", err)
        return
    }
    defer listener.Close()
    fmt.Println("服务器正在监听端口 8080...")

    for {
        // 接受客户端连接
        conn, err := listener.Accept()
        if err != nil {
            fmt.Println("接受连接失败:", err)
            continue
        }
        // 处理连接(可以并发处理多个连接)
        go handleConnection(conn)
    }
}

说明

  1. 使用 net.Listen 监听指定地址和端口。
  2. 使用 listener.Accept 接受客户端连接,返回一个 net.Conn 对象。
  3. 为每个连接启动一个新的 goroutine 处理,实现并发处理多个客户端。

客户端实现

以下是一个简单的 TCP 客户端示例,它连接到服务器并发送消息。

package main

import (
    "bufio"
    "fmt"
    "net"
    "os"
)

func main() {
    // 连接到服务器(localhost:8080)
    conn, err := net.Dial("tcp", "localhost:8080")
    if err != nil {
        fmt.Println("连接服务器失败:", err)
        return
    }
    defer conn.Close()

    reader := bufio.NewReader(os.Stdin)
    for {
        // 从标准输入读取用户输入
        fmt.Print("请输入消息: ")
        message, _ := reader.ReadString('\n')
        // 发送消息到服务器
        _, err := conn.Write([]byte(message))
        if err != nil {
            fmt.Println("发送消息失败:", err)
            return
        }
        // 接收服务器回显的消息
        response, err := bufio.NewReader(conn).ReadString('\n')
        if err != nil {
            fmt.Println("接收消息失败:", err)
            return
        }
        fmt.Print("服务器回显: " + response)
    }
}

说明

  1. 使用 net.Dial 连接到服务器。
  2. 从标准输入读取用户输入并发送到服务器。
  3. 接收服务器的回显消息并显示。

UDP Socket 编程

UDP 是一种无连接的协议,适用于对实时性要求高但对可靠性要求不高的场景。下面将分别介绍如何使用 Go 实现 UDP 服务器和客户端。

服务器端实现

以下是一个简单的 UDP 服务器示例,它监听指定端口,接收客户端发送的数据,并回显消息。

package main

import (
    "fmt"
    "net"
)

func main() {
    // 监听本地 8081 端口的 UDP
    addr, err := net.ResolveUDPAddr("udp", ":8081")
    if err != nil {
        fmt.Println("解析地址失败:", err)
        return
    }

    conn, err := net.ListenUDP("udp", addr)
    if err != nil {
        fmt.Println("监听 UDP 失败:", err)
        return
    }
    defer conn.Close()
    fmt.Println("UDP 服务器正在监听端口 8081...")

    buffer := make([]byte, 1024)
    for {
        // 读取客户端发送的数据
        n, clientAddr, err := conn.ReadFromUDP(buffer)
        if err != nil {
            fmt.Println("读取数据错误:", err)
            continue
        }
        message := string(buffer[:n])
        fmt.Printf("收到来自 %s 的消息: %s", clientAddr, message)

        // 回显消息给客户端
        _, err = conn.WriteToUDP([]byte("Echo: "+message), clientAddr)
        if err != nil {
            fmt.Println("发送消息失败:", err)
        }
    }
}

说明

  1. 使用 net.ResolveUDPAddr 解析 UDP 地址。
  2. 使用 net.ListenUDP 监听 UDP 端口。
  3. 使用 ReadFromUDP 接收数据,并获取客户端地址。
  4. 使用 WriteToUDP 发送数据回客户端。

客户端实现

以下是一个简单的 UDP 客户端示例,它发送消息到服务器并接收回显。

package main

import (
    "bufio"
    "fmt"
    "net"
    "os"
)

func main() {
    // 解析服务器地址
    serverAddr, err := net.ResolveUDPAddr("udp", "localhost:8081")
    if err != nil {
        fmt.Println("解析服务器地址失败:", err)
        return
    }

    // 创建一个 UDP 连接(实际上是无连接的)
    conn, err := net.DialUDP("udp", nil, serverAddr)
    if err != nil {
        fmt.Println("连接 UDP 服务器失败:", err)
        return
    }
    defer conn.Close()

    reader := bufio.NewReader(os.Stdin)
    for {
        // 从标准输入读取用户输入
        fmt.Print("请输入消息: ")
        message, _ := reader.ReadString('\n')
        // 发送消息到服务器
        _, err := conn.Write([]byte(message))
        if err != nil {
            fmt.Println("发送消息失败:", err)
            return
        }
        // 接收服务器回显的消息
        buffer := make([]byte, 1024)
        n, err := conn.Read(buffer)
        if err != nil {
            fmt.Println("接收消息失败:", err)
            return
        }
        fmt.Print("服务器回显: " + string(buffer[:n]))
    }
}

说明

  1. 使用 net.ResolveUDPAddr 解析服务器地址。
  2. 使用 net.DialUDP 创建一个 UDP 连接(实际上是无连接的)。
  3. 发送和接收数据类似于 TCP 客户端。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chxii

小小打赏,大大鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值