目前学到网络部分,记录一下Go语言实现网络编程的方法。
1、net库
1.1 net.Listen()函数
-
功能:
net.Listen()函数用于在本地指定地址和端口上创建一个监听器。它使得服务器能够接受进入的连接请求。支持TCP,UDP等协议 -
用法:
listener, err := net.Listen("tcp", ":8080") if err != nil { // 处理错误 } defer listener.Close() for { conn, err := listener.Accept() if err != nil { // 处理错误 } // 处理连接 }
1.2 Dial()函数
Dial()函数是用于建立网络连接的一个重要函数,主要位于net包中。它允许程序与其他网络服务(如TCP或UDP)建立连接,是客户端连接服务端所使用的函数
conn, err := net.Dial(network, address)
参数说明:
-
network:指定网络类型,常见的值有:
"tcp":表示建立TCP连接。"udp":表示建立UDP连接。- 还有其他类型,如
"unix"等用于Unix域套接字的连接。
-
address:指定要连接的地址和端口,格式一般是
"host:port",例如:"localhost:8080"表示连接本机的8080端口。
返回值:
- conn:返回一个连接对象,实现了
net.Conn接口,通过这个对象可以进行数据的读写操作。 - err:如果连接建立失败,则返回一个错误对象,通常会提供失败的原因。
2、HTTP客户端
2.1 http.request类
http.Request对象封装了请求的所有信息,例如请求方法、URL、头部信息、请求体等,以下是Request对象的定义
type Request struct {
Method string // HTTP 请求方法,例如 "GET"、"POST"
URL *url.URL // 请求的 URL
Proto string // HTTP 协议版本,例如 "HTTP/1.1"
ProtoMajor int // 主协议版本号,例如 1
ProtoMinor int // 次协议版本号,例如 1
Header Header // HTTP 请求头
Body io.ReadCloser // 请求体,通常用于 POST、PUT 请求
ContentLength int64 // 请求体的长度,若未知则为 -1
TransferEncoding []string // 传输编码,如 "chunked"
Host string // 请求的主机名
Form url.Values // 提交的表单数据(用于解析 URL 或表单的参数)
PostForm url.Values // 仅包含 POST 请求的表单数据
MultipartForm *multipart.Form // 包含多部分文件上传的表单数据
Trailer Header // 后续的 Trailer 部分头
RemoteAddr string // 客户端的 IP 地址(仅在服务端有效)
RequestURI string // 原始的请求 URI
TLS *tls.ConnectionState // TLS 连接状态信息(如果是 HTTPS 请求)
Cancel <-chan struct{} // 当请求取消时关闭的信道
Response *Response // 与请求关联的响应,通常为空
}
2.2 http.Response类
在go当中response是一个返回的对象,具体来说,它是一个http.Response类型的实例。在Go语言的net/http包中,http.Response表示HTTP响应的信息,包括从服务器返回的数据和相关的元数据。以下是request类中包含的信息。
- Status:响应状态码的字符串表示,例如
"200 OK",指示请求的结果。 - StatusCode:响应状态码的整型值,例如
200,相应的HTTP状态码。 - Header:一个表示响应头的类型为
http.Header的值,包含了服务器返回的所有HTTP头部信息。 - Body:一个
io.ReadCloser类型的值,表示响应体的内容。这是你读取服务器返回的数据的地方。 - ContentLength:响应体的字节长度。
- TransferEncoding:指定了响应的传输编码。
- TLS:如果请求是通过HTTPS进行的,
TLS字段包含了相关的TLS连接信息。
2.3 http.Get()
要请求一个资源,只需调用 http.Get()方法(等价于 http.DefaultClient.Get())即可,示例代码
resp, err := http.Get("http://example.com/")
if err != nil { // 处理错误 ...
return
}
defer resp.Body.close() // 关闭http响应体
io.Copy(os.Stdout, resp.Body)
!!!注意关闭响应体实质上就是关闭了连接
HTTP/1.1允许持久连接(也称为HTTP Keep-Alive),即在同一连接上可以发送多个请求和响应。关闭响应体不仅使当前请求的连接关闭,也告诉底层网络库释放与这个HTTP响应相关的所有资源,包括与服务器的连接。
2.4 http.Post()
要以POST 的方式发送数据,也很简单,只需调用 http.Post()方法并依次传递下面的 3 个参数即可:
- 请求的目标 URL
- 将要 POST 数据的资源类型(MIMEType)
- 数据的比特流([]byte 形式)
resp, err := http.Post("http://example.com/upload", "image/jpeg", &imageDataBuf)
if err != nil{ // 处理错误
return
}
if resp.StatusCode != http.StatusOK {// 处理错误
return
}
2.5 http.Client类
http.Client 是 Go 语言标准库 net/http 中用于发送 HTTP 请求和接收 HTTP 响应的结构体。它提供了一系列配置选项,能够满足不同的 HTTP 通信需求。比较灵活,当只需要获取一个资源时,直接使用http.get()会更加的方便
主要功能和使用方式:
-
创建 HTTP 客户端:
client := &http.Client{}这行代码创建了一个新的 HTTP 客户端实例。可以使用它来发起多个请求。
-
自定义设置:
http.Client允许你自定义请求的超时设置、代理、Cookie、TLS 配置等。虽然在上述代码中没有显示这些设置,但你可以通过http.Client的字段来进行配置,比如Timeout字段可以设置请求的超时时间。http.client适用于实现复杂操作时使用,当简单的获取一个资源时使用http.Get()会更加方便client := &http.Client{ Timeout: 10 * time.Second, // 设置请求超时时间 } -
发起请求: 使用
client.Do(req)方法来发送 HTTP 请求,并返回http.response结构体对象。这里req是之前构造的http.request对象。resp, err := client.Do(req) -
处理响应:
resp是一个*http.Response类型的对象,可以用来获取响应的状态、头部,和响应体等信息。你需要记得在处理完响应体后调用defer resp.Body.Close()来关闭响应体,从而释放相关资源。 -
错误处理: 在发送请求和读取响应体时,通常需要进行错误处理,以确保程序异常时能够给出适当的提示信息。
if resp.StatusCode != 200 { // 请求出错时,状态码会返回200 log.Fatal("bad Status Code:", resp.StatusCode, "body", string(bodyText)) }
2.6 http.NewRequest函数
函数用于创建一个新的http.Request对象。这个函数允许你指定请求方法(如GET、POST等)、请求的URL以及请求体(对于非GET/HEAD请求)。
函数定义如下:
func NewRequest(method, url string, body io.Reader) (*Request, error)
// 是net/http标准库中的一个库函数,用于创建并返回一个http.Request对象
参数:
method:HTTP 方法,通常是"GET"、"POST"、"PUT"、"DELETE"等字符串。在此例中,方法是"POST"。url:目标请求的 URL。在此例中是https://api.interpreter.caiyunai.com/v1/dict。body:请求体(即要发送的数据)。类型为io.Reader,可以是nil(对于没有请求体的请求),也可以是任何实现了io.Reader接口的对象(例如bytes.NewReader返回的对象)。此例中的data是请求体的内容。
返回值:
*Request:返回一个指向http.Request对象的指针,代表构建的 HTTP 请求。error:返回构建请求时可能发生的错误。如果url格式不正确或参数无效,会返回错误。
学习总结
net库是Go语言中处理网络通信的核心库,它提供了丰富的功能,包括TCP/IP、UDP、HTTP等协议的支持。在学习net库的过程中,我深刻感受到了Go语言相对于C++语言在网络编程这一方面的的简洁和高效。
这次学习让我对Go语言的网络编程有了更深入的理解,也让我更加熟悉和掌握了net库的使用方法。我相信,在未来的学习和工作中,我会更加熟练地运用net库进行网络通信编程。