Golang http Programação

workflows web

  • servidor Works Web pode ser resumido simplesmente como
    • Cliente estabelece para o servidor através da conexão protocolo TCP TCP / IP
    • O cliente envia para o servidor HTTP pacote de solicitação de protocolo, os recursos do servidor que pedem no documento
    • O servidor envia para o pacote de resposta protocolo HTTP cliente, se o recurso solicitado contém conteúdo linguagem dinâmica, o servidor chama as alças motor de interpretação de "conteúdo dinâmico" linguagens dinâmicas e processar a volta dados resultantes para o cliente
    • Cliente e servidor está desligado. Pelo cliente interpreta o documento HTML, o resultado de renderização de gráficos na tela do cliente

protocolo HTTP

  • Hypertext Transfer Protocol (HTTP, Hypertext Transfer Protocol) é o protocolo de rede mais amplamente utilizado da Internet, que detalha as regras de comunicação mútua entre o navegador eo servidor Web, o protocolo de transferência de documentos da World Wide Web para transferir dados através da Internet
  • protocolo HTTP através do protocolo TCP normalmente realizado

http servidor

package main

import (
    "fmt"
    "net/http"
)

// /go handler
func goHandler(w http.ResponseWriter, r *http.Request) {
    // 获取远程地址
    fmt.Println(r.RemoteAddr, "连接成功")
    // 获取请求类型
    fmt.Println("请求方法: ", r.Method)
    // 获取url路径
    fmt.Println("url path: ", r.URL.Path)
    // 获取header数据
    fmt.Println("header: ", r.Header)
    // 获取请求body内容
    fmt.Println("body: ", r.Body)

    // 返回信息
    _, _ = w.Write([]byte("hello world"))
}

func main()  {
    // 单独写回掉函数
    http.HandleFunc("/go", goHandler)

    // 启动http监听
    _ = http.ListenAndServe("127.0.0.1:8000", nil)
}

http pacote do cliente

package main

import (
    "fmt"
    "io"
    "net/http"
)

func main() {
    resp, err := http.Get("http://127.0.0.1:8000/go")
    if err != nil {
        fmt.Println("获取数据失败, err: ", err)
        return
    }
    defer resp.Body.Close()
    // 获取http状态码
    fmt.Println("status: ", resp.Status)
    // 获取header信息
    fmt.Println("header: ", resp.Status)

    buf := make([]byte, 124)
    for {
        // 接收服务端数据
        n, err := resp.Body.Read(buf)

        fmt.Println(string(buf[:n]))

        if err == io.EOF {
            break
        }

        if err != nil {
            fmt.Println("数据读取失败, err: ", err)
            continue
        }
    }
}

implementos de pacotes TCP do cliente

package main

import (
    "fmt"
    "io"
    "net"
)

func main() {
    conn, err := net.Dial("tcp", "127.0.0.1:8000")
    if err != nil {
        fmt.Println("connect err: ", err)
        return
    }
    defer conn.Close()
    msg := "GET /go HTTP/1.1\r\n"
    msg += "Host: 127.0.0.1:8000\r\n"
    msg += "Connection: close\r\n"
    msg += "\r\n\r\n"

    _, err = io.WriteString(conn, msg)
    if err != nil {
        fmt.Println("write string failed, ", err)
        return
    }
    buf := make([]byte, 4096)
    for {
        n, err := conn.Read(buf)
        if err == io.EOF {
            break
        }
        if err != nil {
            fmt.Println("recv data has err, ", err)
            break
        }
        fmt.Println(string(buf[:n]))
    }
}

outro erro

golang GET 出现 x509: certificado assinado por uma autoridade desconhecida

Nós vamos escrever um programa para tentar estabelecer uma conexão e comunicação com o servidor HTTPS.

//gohttps/4-https/client1.go
package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    resp, err := http.Get("https://localhost:8081")
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}

Executar este cliente, temos o seguinte erro:

$go run client1.go
error: Get https://localhost:8081: x509: certificate signed by unknown authority

Neste ponto, o log de erro do servidor também dá dicas:

2015/04/30 16:03:31 http: TLS handshake error from 127.0.0.1:62004: remote error: bad certificate

Obviamente, do ponto de vista do cliente o log, vá para perceber o padrão é cliente-servidor para passar sobre a verificação do certificado digital, mas o cliente Nota: Este certificado é emitido por um desconhecido CA do!

Client1.go podemos modificar o código para que do lado do cliente ignorar a verificação de certificados:

//gohttps/4-https/client2.go
package main

import (
"crypto/tls"
"fmt"
"io/ioutil"
"net/http"
)

func main() {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
resp, err := client.Get("https://localhost:8081")

    if err != nil {
        fmt.Println("error:", err)
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))

}

, Certificado de servidor do cliente não serão verificados, definindo a verdade a InsecureSkipVerify tls.Config. Aplicação dos resultados também confirmou isso:

$go run client2.go
Hi, This is an example of http service in golang!

http pedido conjunto cabeçalho

package main
import (
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
    "encoding/json"
)

func main() { //生成client 参数为默认
    client := &http.Client{}
    //生成要访问的url
    url := "http://somesite/somepath/"
    //提交请求
    reqest, err := http.NewRequest("GET", url, nil)

    //增加header选项
    reqest.Header.Add("Cookie", "xxxxxx")
    reqest.Header.Add("User-Agent", "xxx")
    reqest.Header.Add("X-Requested-With", "xxxx")

    if err != nil {
        panic(err)
    }
    //处理返回结果
    response, _ := client.Do(reqest)
    defer response.Body.Close()
}

http pedidos de proxy

package main

import (
    "crypto/tls"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "time"
)

// http proxy get方法
func httpProxyGet(dataUrl, proxyIp string) (data []byte,  err error) {
    transport := &http.Transport{
        TLSClientConfig:   &tls.Config{InsecureSkipVerify: true}, //ssl证书报错问题
        DisableKeepAlives: false,                                 //关闭连接复用,因为后台连接过多最后会造成端口耗尽
        MaxIdleConns:      -1,                                    //最大空闲连接数量
        IdleConnTimeout:   time.Duration(5 * time.Second),        //空闲连接超时时间
        Proxy: http.ProxyURL(&url.URL{
            Scheme: "http",
            Host:   proxyIp,
        }),
    }
    // 设置代理方式二
    //proxyUrl, _ := url.Parse("http://" + proxyIp)
    //transport.Proxy = http.ProxyURL(proxyUrl)

    // 创建http客户端
    client := &http.Client{
        Timeout:   time.Duration(30 * time.Second),
        Transport: transport,
    }

    request, err := http.NewRequest("GET", dataUrl, nil)
    if err != nil {
        return
    }
    // 请求数据
    resp, err := client.Do(request)
    if err != nil {
        err = fmt.Errorf("request %s, proxyIp: (%s),err: %v", dataUrl, proxyIp, err)
        return
    }
    defer resp.Body.Close()
    // 读取数据
    buf := make([]byte, 128)
    data = make([]byte, 0, 2048)
    for {
        n, err := resp.Body.Read(buf)
        data = append(data, buf[:n]...)

        if err == io.EOF {
            break
        }
        if err != nil {
            continue
        }
    }
    return
}


func main() {
    data, err := httpProxyGet("http://www.baidu.com/", "89.22.11.55:9000")
    if err != nil {
        println(err)
        return
    }
    fmt.Println(string(data))
}

Programação websocket

O que é WebSocket

  • protocolo WebSocket é uma comunicação duplex completa através de uma única ligação TCP
  • WebSocket permite a troca de dados entre o cliente eo servidor mais fácil, permitindo que o servidor para o cliente empurrar ativamente dados
  • Na API WebSocket, o navegador eo servidor só precisa completar um aperto de mão, você pode criar diretamente uma conexão persistente entre os dois, e transmissão de dados bidirecional
  • Você precisa instalar pacotes de terceiros:
    • cmd em:go get -u -v github.com/gorilla/websocket

exemplo WebSocket

o servidor

package main

import (
    "github.com/gorilla/websocket"
    "log"
    "net/http"
)

var upgrader = websocket.Upgrader{  // 配置websocker选项
    // 允许websocket跨域
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

func echo(w http.ResponseWriter, r *http.Request) {
    c, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Print("upgrade:", err)
        return
    }
    defer c.Close()
    for {
        mt, message, err := c.ReadMessage()
        if err != nil {
            log.Println("read:", err)
            break
        }
        log.Printf("recv: %s", message)
        err = c.WriteMessage(mt, message)
        if err != nil {
            log.Println("write:", err)
            break
        }
    }
}
func main() {
    log.SetFlags(0)
    http.HandleFunc("/echo", echo)
    log.Fatal(http.ListenAndServe("127.0.0.1:8081", nil))
}

cliente html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>websocket demo</title>
  </head>
  <body>
    <table>
      <tr>
        <td valign="top" width="50%">
          <p>
            Click "Open" to create a connection to the server, "Send" to send a
            message to the server and "Close" to close the connection. You can
            change the message and send multiple times.
          </p>
          <form>
            <button id="open">Open</button>
            <button id="close">Close</button>
            <input id="input" type="text" value="Hello world!" />
            <button id="send">Send</button>
          </form>
        </td>
        <td valign="top" width="50%">
          <div id="output"></div>
        </td>
      </tr>

      <script>
        window.addEventListener('load', function(evt) {
          var output = document.getElementById('output')
          var input = document.getElementById('input')
          var ws
          var print = function(message) {
            var d = document.createElement('div')
            d.innerHTML = message
            output.appendChild(d)
          }
          document.getElementById('open').onclick = function(evt) {
            if (ws) {
              return false
            }
            ws = new WebSocket('ws://127.0.0.1:8081/echo')
            ws.onopen = function(evt) {
              print('OPEN')
            }
            ws.onclose = function(evt) {
              print('CLOSE')
              ws = null
            }
            ws.onmessage = function(evt) {
              print('RESPONSE: ' + evt.data)
            }
            ws.onerror = function(evt) {
              print('ERROR: ' + evt.data)
            }
            return false
          }
          document.getElementById('send').onclick = function(evt) {
            if (!ws) {
              return false
            }
            print('SEND: ' + input.value)
            ws.send(input.value)
            return false
          }
          document.getElementById('close').onclick = function(evt) {
            if (!ws) {
              return false
            }
            ws.close()
            return false
          }
        })
      </script>
    </table>
  </body>
</html>

Acho que você gosta

Origin www.cnblogs.com/zhichaoma/p/12509733.html
Recomendado
Clasificación