如何在Go中有效地使用网络功能?

huangapple go评论82阅读模式
英文:

How do you use the net functions effectively in Go?

问题

例如,具有基本数据包协议,如:

[packetType int][packetId int][data []byte]

并使用它创建一个客户端和服务器来执行简单的操作(例如聊天)。

英文:

For example, having basic packet protocol, like:

[packetType int][packetId int][data []byte]

And making a client and server doing simple things with it (egx, chatting.)

答案1

得分: 5

这是一个具有松散的恐慌错误处理的客户端和服务器。它们有一些限制:

  • 服务器一次只能处理一个客户端连接。您可以通过使用goroutines来修复这个问题。
  • 数据包始终包含100字节的有效负载。您可以通过在数据包中放置一个长度并且不使用encoding/binary来修复这个问题,但我保持了简单。

这是服务器的代码:

package main

import (
    "encoding/binary"
    "fmt"
    "net"
)

type packet struct {
    // 字段名称必须大写以进行编码/二进制处理。
    // 使用明确大小的类型非常重要。
    // 使用int32而不是int等。
    Type int32
    Id   int32
    // 这必须是数组而不是切片。
    Data [100]byte
}

func main() {
    // 在端口2000上设置一个监听器
    l, err := net.Listen("tcp", ":2000")
    if err != nil {
        panic(err.String())
    }

    for {
        // 开始监听连接
        conn, err := l.Accept()
        if err != nil {
            panic(err.String())
        }
        handleClient(conn)
    }
}

func handleClient(conn net.Conn) {
    defer conn.Close()

    // 一个客户端已连接;现在等待一个数据包
    var msg packet
    binary.Read(conn, binary.BigEndian, &msg)
    fmt.Printf("接收到一个数据包:%s\n", msg.Data)

    // 发送响应
    response := packet{Type: 1, Id: 1}
    copy(response.Data[:], "Hello, client")
    binary.Write(conn, binary.BigEndian, &response)
}

这是客户端。它发送一个类型为0、id为0、内容为“Hello, server”的数据包。然后它等待响应,打印它并退出。

package main

import (
    "encoding/binary"
    "fmt"
    "net"
)

type packet struct {
    Type int32
    Id   int32
    Data [100]byte
}

func main() {
    // 连接到本地主机的端口2000
    conn, err := net.Dial("tcp", ":2000")
    if err != nil {
        panic(err.String())
    }
    defer conn.Close()

    // 发送一个数据包
    msg := packet{}
    copy(msg.Data[:], "Hello, server")
    err = binary.Write(conn, binary.BigEndian, &msg)
    if err != nil {
        panic(err.String())
    }

    // 接收响应
    var response packet
    err = binary.Read(conn, binary.BigEndian, &response)
    if err != nil {
        panic(err.String())
    }
    fmt.Printf("响应:%s\n", response.Data)
}
英文:

Here's a client and server with sloppy panic error-handling. They have some limitations:

  • The server only handles one client connection at a time. You could fix this by using goroutines.
  • Packets always contain 100-byte payloads. You could fix this by putting a length in the packet somewhere and not using encoding/binary for the entire struct, but I've kept it simple.

Here's the server:

package main

import (
	"encoding/binary"
	"fmt"
	"net"
)

type packet struct {
	// Field names must be capitalized for encoding/binary.
	// It's also important to use explicitly sized types.
	// int32 rather than int, etc.
	Type int32
	Id   int32
	// This must be an array rather than a slice.
	Data [100]byte
}

func main() {
	// set up a listener on port 2000
	l, err := net.Listen("tcp", ":2000")
	if err != nil {
		panic(err.String())
	}

	for {
		// start listening for a connection
		conn, err := l.Accept()
		if err != nil {
			panic(err.String())
		}
		handleClient(conn)
	}
}

func handleClient(conn net.Conn) {
	defer conn.Close()

	// a client has connected; now wait for a packet
	var msg packet
	binary.Read(conn, binary.BigEndian, &msg)
	fmt.Printf("Received a packet: %s\n", msg.Data)

	// send the response
	response := packet{Type: 1, Id: 1}
	copy(response.Data[:], "Hello, client")
	binary.Write(conn, binary.BigEndian, &response)
}

Here's the client. It sends one packet with packet type 0, id 0, and the contents "Hello, server". Then it waits for a response, prints it, and exits.

package main

import (
	"encoding/binary"
	"fmt"
	"net"
)

type packet struct {
	Type int32
	Id   int32
	Data [100]byte
}

func main() {
	// connect to localhost on port 2000
	conn, err := net.Dial("tcp", ":2000")
	if err != nil {
		panic(err.String())
	}
	defer conn.Close()

	// send a packet
	msg := packet{}
	copy(msg.Data[:], "Hello, server")
	err = binary.Write(conn, binary.BigEndian, &msg)
	if err != nil {
		panic(err.String())
	}

	// receive the response
	var response packet
	err = binary.Read(conn, binary.BigEndian, &response)
	if err != nil {
		panic(err.String())
	}
	fmt.Printf("Response: %s\n", response.Data)
}

答案2

得分: 3

请查看Jan Newmarch的《使用Go进行网络编程》。

英文:

Check out Jan Newmarch's "Network programming with Go".

huangapple
  • 本文由 发表于 2011年9月22日 23:00:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/7516958.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定