golang socket 阻塞读取

发布时间:2024-12-23 03:58:21

Go语言(Golang)是一门由Google开发的开源编程语言,它以简洁、高效和并发性强而著称。在Go语言的标准库中,提供了一套完善的网络编程包,通过这些包,我们可以方便地进行Socket编程。

阻塞读取数据

在Socket编程中,我们经常需要从连接中读取数据。在Go语言中,使用net包提供的Conn接口的Read方法来进行阻塞读取。Read方法会一直阻塞,直到有数据可读或者出现错误。一般情况下,我们会将读取到的数据保存到缓冲区中。

阻塞写入数据

除了读取数据,我们也经常需要向连接中写入数据。在Go语言中,使用net包提供的Conn接口的Write方法来进行阻塞写入。Write方法会一直阻塞,直到数据完全写入或者出现错误。一般情况下,我们会将要写入的数据从缓冲区中发送出去。

实例:基于Socket的聊天应用

让我们来看一个简单的实例,使用Go语言进行Socket编程实现一个基于TCP协议的聊天应用。在这个应用中,我们将实现一个服务器和多个客户端之间的即时通讯。

首先,我们需要定义一个消息结构体,用于存储聊天消息的发送者和内容:

type Message struct {
    Sender  string
    Content string
}

接下来,我们可以实现一个简单的服务器,通过监听某个端口接受客户端的连接,并将收到的消息广播给所有其他客户端:

func main() {
    // 监听指定端口
    ln, _ := net.Listen("tcp", ":8080")
    defer ln.Close()

    // 创建一个广播通道
    broadcast := make(chan Message)

    for {
        // 接受客户端的连接
        conn, _ := ln.Accept()
        
        // 启动一个协程处理客户端消息
        go handleClient(conn, broadcast)
    }
}

func handleClient(conn net.Conn, broadcast chan Message) { 
    // 关闭连接时,广播当前客户端离线消息
    defer func() {
        message := Message{Sender: conn.RemoteAddr().String(), Content: "离线了"}
        broadcast <- message
        conn.Close()
    }()
    
    // 上线时,广播当前客户端在线消息
    message := Message{Sender: conn.RemoteAddr().String(), Content: "上线了"}
    broadcast <- message

    // 循环读取客户端消息并广播给其他客户端
    scanner := bufio.NewScanner(conn)
    for scanner.Scan() {
        content := scanner.Text()
        message := Message{Sender: conn.RemoteAddr().String(), Content: content}
        broadcast <- message
    }
}

在上述代码中,我们使用net包的Listen方法监听指定端口,并在有新的客户端连接时启动一个协程来处理客户端的消息。在handleClient函数中,我们通过Scanner对象从客户端连接中读取消息,并广播给所有其他客户端。

除了服务器端的代码之外,我们还可以实现一个客户端程序,用于与服务器建立连接,并发送和接受聊天消息:

func main() {
    conn, _ := net.Dial("tcp", "127.0.0.1:8080")
    defer conn.Close()

    go receiveMessages(conn)

    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() { 
        content := scanner.Text()
        fmt.Fprintf(conn, "%s\n", content)
    }
}

func receiveMessages(conn net.Conn) {
    scanner := bufio.NewScanner(conn)
    for scanner.Scan() {
        content := scanner.Text()
        fmt.Printf("收到消息:%s\n", content)
    }
}

在上述代码中,我们使用net包的Dial方法连接服务器,并在receiveMessages函数中通过Scanner对象从服务器连接中读取消息。在主函数中,我们使用bufio包的Scanner对象从标准输入获取用户输入,并将其发送给服务器。

通过这个简单的示例,我们可以看到,使用Go语言进行Socket编程非常简洁、高效。Go语言的并发机制让我们很容易地实现多个客户端同时连接,并实现即时通讯的功能。

相关推荐