07月20日, 2018

goweb-038-常用包net+http

网络操作(计算机网络相关知识可以利用此包实践)

net

  • net包提供了可移植的网络I/O接口,包括TCP/IPUDP、域名解析和Unixsocket
  • 本包提供了对网络原语的访问,大部分使用者只需要DialListenAccept函数提供的基本接口;以及相关的ConnListener接口。

过程

  1. 服务端程序 Listen 监听某个端口,等待客户端程序的连接请求Accept
  2. 客户端程序 Dial 申请连接。
  3. 服务端程序 处理连接请求并建立网络连接 Conn
  4. 双方在Conn 进行读Read/写Write操作传递数据。

代码示例
server

package main
import (
	"net"
)
func main() {
	//监听端口
	listen, _ := net.Listen("tcp", `:88`)
	for {
		//等待连接连接并建立连接
		conn, _ := listen.Accept()
		//通过连接发送数据
		conn.Write([]byte(`hello 我是服务端`))
	}
}

client

package main
import (
	"fmt"
	"net"
)
func main() {
	//请求建立连接
	conn, _ := net.Dial("tcp", ":88")
	//数据容器
	buf := make([]byte, 1024)
	//读取数据到容器
	l, _ := conn.Read(buf)
	//打印输出
	fmt.Println(string(buf[:l]))
}

模拟http
浏览器访问 http://127.0.0.1:86/查看效果

alt

package main
import (
	"fmt"
	"net"
)
func main() {
	//监听端口
	listen, _ := net.Listen("tcp", `:86`)
	//等待连接连接并建立连接
	conn, _ := listen.Accept()
	//http半双工需要先读取里面的数据
	buf := make([]byte, 1024)
	l, _ := conn.Read(buf)
	fmt.Println(string(buf[:l]))
	//通过连接发送数据
	//http 协议格式
	conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Type: text/plain;charset=UTF-8\r\n\r\n数据开始:net模拟http"))
	conn.Close()
}

浏览器
alt
控制台
alt

http

官方文档
net的上层封装
- http包提供了HTTP客户端和服务端的实现。

Get, Head, Post, and PostForm make HTTP (or HTTPS) requests:

//普通get请求
resp, err := http.Get("http://example.com/")
//上传文件
bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)
fileWriter, _ := bodyWriter.CreateFormFile("file", "main.go")
fh, _ := os.Open("main.go")
defer fh.Close()
io.Copy(fileWriter, fh)
ctype := bodyWriter.FormDataContentType()
bodyWriter.Close()
http.Post("http://127.0.0.1/up", ctype, bodyBuf)

//提交数据
resp, err := http.PostForm("http://example.com/form",
	url.Values{"key": {"Value"}, "id": {"123"}})

The client must close the response body when finished with it:

resp, err := http.Get("http://example.com/")
if err != nil {
	// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
// ...

For control over HTTP client headers, redirect policy, and other settings, create a Client:

client := &http.Client{
}

resp, err := client.Get("http://example.com")
// ...

req, err := http.NewRequest("GET", "http://example.com", nil)
// ...
req.Header.Add("If-None-Match", `W/"wyzzy"`)
resp, err := client.Do(req)

爬取页面

package main
import (
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
)
func main() {
	//发送http请求
	resp, err := http.Get("http://www.cwnu.edu.cn/")
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	//读取响应数据
	body, err := ioutil.ReadAll(resp.Body)
	//解析 a标签里面的 href数据
	reg, _ := regexp.Compile(`<a.+href="(http.+?)"`)
	res := reg.FindAllStringSubmatch(string(body), -1)
	for idx := range res {
		fmt.Println(res[idx][1])
		//后续数据处理
	}
}

web

版本1

package main

import (
	"net/http"
)

func index(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte(`hello`))
}
func main() {
	http.HandleFunc(`/first`, index)
	http.ListenAndServe(":8080", nil)
}

alt

巴拉巴拉。。。✍

版本2

package main
import (
	"io/ioutil"
	"net/http"
	"os"
)
func index(w http.ResponseWriter, r *http.Request) {
	//读取html文件
	f, _ := os.Open(`./index.html`)
	//读取数据
	buf, _ := ioutil.ReadAll(f)
	//写入到响应
	w.Write(buf)

}
func main() {
	http.HandleFunc(`/first`, index)
	//静态文件访问 css img js 等
	http.Handle("/res/", http.StripPrefix("/res/", http.FileServer(http.Dir("./res"))))
	http.ListenAndServe(":8080", nil)
}

html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>hello</title>
</head>
<body>
    <div>index.html</div>
    <script src="/res/js.js"></script>
</body>
</html>

js 文件

alert("res js")

本文链接:/posts/goweb-038/

-- EOF --