HTTP/2服务端与客户端例子(Go)

      圣诞节独自一人在家,火车票只抢到一张无座... 还是弄下Blog吧,不然Blog感觉要长草了。 

这是翻以前的测试代码整理贴上来的。

    一个完整的HTTP/2的服务端与客户端的Demo.  也许有人用得上。


服务端代码:

package main

/*
HTTP/2 服务端例子

Author: XCL
Date: 2016-12-25

HTTP2 测试证书生成.
go run $GOROOT/src/crypto/tls/generate_cert.go --host localhost

*/

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"golang.org/x/net/http2"
)

const (
	_HTTP2URLBase = "https://localhost:9000"
	_CertFile     = "../pem/cert.pem"
	_KeyFile      = "../pem/key.pem"
)

type handlerFunc func(w http.ResponseWriter, r *http.Request)

func main() {
	httpMux, http2Mux := getHttpMux()
	go httpSrv(httpMux)
	httpsSrv(http2Mux)
}

// Mux定义 -- 设置HTTP1.1访问转向HTTP2
func getHttpMux() (httpMux, http2Mux *http.ServeMux) {

	httpMux = http.NewServeMux()
	http2Mux = http.NewServeMux()

	x := make(map[string]handlerFunc, 0)
	x["/"] = Home
	x["/v1"] = Hello1

	for k, v := range x {
		redirectURL := http.RedirectHandler(_HTTP2URLBase+k, 307)
		httpMux.Handle(k, redirectURL)
		http2Mux.HandleFunc(k, v)
	}

	return
}

//HTTP服务
func httpSrv(mux *http.ServeMux) {
	log.Fatal(http.ListenAndServe(":9001", mux))
}

//HTTP2服务
func httpsSrv(mux *http.ServeMux) {
	srv := &http.Server{
		Addr:         ":9000",
		ReadTimeout:  10 * time.Second,
		WriteTimeout: 10 * time.Second,
		Handler:      mux,
	}
	http2.VerboseLogs = true
	http2.ConfigureServer(srv, &http2.Server{})

	log.Fatal(srv.ListenAndServeTLS(_CertFile, _KeyFile))
}

//Handler函数
func Home(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "RequestURI: %s\n", r.RequestURI)
	fmt.Fprintf(w, "Protocol: %s\n", r.Proto)
	fmt.Fprintf(w, "Home")
}

func Hello1(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "RequestURI: %s\n", r.RequestURI)
	fmt.Fprintf(w, "Protocol: %s\n", r.Proto)
	fmt.Fprintf(w, "Hello V1")
}


客户端:

package main

/*
HTTP/2 客户端例子

Author: XCL
Date: 2016-12-25


测试结果:
➜  client  : go run client.go
resp.Body:
 RequestURI: /v1
Protocol: HTTP/2.0
Hello V1

*/

import (
	"context"
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"time"

	"golang.org/x/net/http2"
)

func main() {
	url := "https://localhost:9000/v1"
	client(url)
}

func client(url string) {

	tr := &http2.Transport{
		AllowHTTP: true, //充许非加密的链接
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: true,
		},
	}
	httpClient := http.Client{Transport: tr}

	ctx, cancel := context.WithCancel(context.TODO())
	time.AfterFunc(5*time.Second, func() {
		cancel()
	})

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Fatal(err)
	}
	req = req.WithContext(ctx)
	resp, err := httpClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		fmt.Println("resp StatusCode:", resp.StatusCode)
		return
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("resp.Body:\n", string(body))
}


完毕! 

  

    Blog: http://blog.csdn.net/xcl168








  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是服务端代码,使用Go语言编写,通过HTTP协议提供文件下载服务: ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { http.HandleFunc("/download", func(w http.ResponseWriter, r *http.Request) { // 获取文件名 filename := r.URL.Query().Get("filename") if filename == "" { http.Error(w, "missing filename parameter", http.StatusBadRequest) return } // 打开文件 file, err := os.Open(filename) if err != nil { http.Error(w, fmt.Sprintf("failed to open file %s: %v", filename, err), http.StatusInternalServerError) return } defer file.Close() // 设置响应头 w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename)) w.Header().Set("Content-Type", "application/octet-stream") // 写入响应体 if _, err = io.Copy(w, file); err != nil { http.Error(w, fmt.Sprintf("failed to write file to response: %v", err), http.StatusInternalServerError) return } }) // 监听端口 if err := http.ListenAndServe(":8080", nil); err != nil { panic(err) } } ``` 客户端代码如下,通过HTTP协议从服务端获取文件并保存本地: ```go package main import ( "fmt" "io" "net/http" "os" ) func main() { // 获取命令行参数 if len(os.Args) != 4 { fmt.Println("usage: demo file [filename] [server address]") return } filename := os.Args[2] serverAddr := os.Args[3] // 发送请求 resp, err := http.Get(fmt.Sprintf("http://%s/download?filename=%s", serverAddr, filename)) if err != nil { fmt.Printf("failed to download file %s from server %s: %v\n", filename, serverAddr, err) return } defer resp.Body.Close() // 创建文件 file, err := os.Create(filename) if err != nil { fmt.Printf("failed to create file %s: %v\n", filename, err) return } defer file.Close() // 写入文件 if _, err = io.Copy(file, resp.Body); err != nil { fmt.Printf("failed to save file %s: %v\n", filename, err) return } fmt.Printf("file %s downloaded from server %s\n", filename, serverAddr) } ``` 使用命令 `go build` 分别编译服务端客户端程序,然后在不同的终端窗口中启动服务端客户端程序,即可进行文件下载。例如,启动服务端程序: ``` $ ./server ``` 启动客户端程序,并从服务端下载文件 `test.txt`: ``` $ ./client file test.txt 192.168.1.1 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值