Go语言网络编程/Socket、http

GO语言和网络编程有关的包都在net包下,通过net包及其子包,可以实现各种协议编程、Socket编程、http编程、rpc编程等。

一、Socket编程

1、Dial函数

Go语言中 Dial() 函数用于创建网络连接,函数原型如下:

func Dial(network, address string) (Conn, error) {   
    var d Dialer 
    return d.Dial(network, address)
}

参数说明如下:

  • network 参数表示传入的网络协议(比如 tcp、udp 等);
  • address 参数表示传入的 IP 地址或域名,而端口号是可选的,如果需要指定的话,以:的形式跟在地址或域名的后面即可。如果连接成功,该函数返回连接对象,否则返回 error。

实际上,Dial() 函数是对 DialTCP()、DialUDP()、DialIP()、DialUnix() 函数的封装:

func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err error)
func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error)
func DialIP(netProto string, laddr, raddr *IPAddr) (c *IPConn, err error)
func DialUnix(net string, laddr, raddr *UnixAddr) (c *UnixConn, err error)

在成功建立连接后,我们就可以进行数据的发送和接收,发送数据时使用连接对象 conn 的 Write() 方法,接收数据时使用 Read() 方法。

2、Listen函数

net包下个Listen函数会监听一个地址,返回一个监听器对象。

func Listen(network, address string) (Listener, error) {  
    var lc ListenConfig   
    return lc.Listen(context.Background(), network, address)
}

3、Socket客户端/服务端

通过net包下的Dial和Listen函数来实现一个Socket编程。

服务器端:

通过Listen函数监听端口,接收来自客户端的请求。

监听器的Accept()方法是阻塞的,接收不到消息就会一直等待。

使用for循坏持续监听,并发处理接收的请求。

package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
)

func main() {

	listener, _ := net.Listen("tcp", ":8888")

	fmt.Println("开始监听...")

	for{
		conn, err := listener.Accept()//接收客户端发来的请求
		if err!=nil{
			fmt.Fprintln(os.Stdout,"错误:",err)
		}
		go handler(conn)//并发处理
		
	}

	defer listener.Close()//关闭监听器
}

func handler(conn net.Conn)  {//处理器

	defer  conn.Close()
	conn.Write([]byte("已经收到..."))//响应客户端的数据

	reader := bufio.NewReader(conn)

	s, _ := reader.ReadString('\n')

	fmt.Fprintln(os.Stdout,s)//将客户端发送的数据输出

}

客户端:

package main

import (
	"fmt"
	"net"
)

func main() {

	conn, _ := net.Dial("tcp", "127.0.0.1:8888")//建立Tcp连接

	defer  conn.Close()//关闭连接

	conn.Write([]byte("hello world"))//发出数据



	bytes := make([]byte, 100)
	n, _ := conn.Read(bytes)//读取数据

	fmt.Println(string(bytes[0:n]))

}

二、Http编程

http包提供了HTTP客户端和服务端的实现。

Get、Head、Post和PostForm函数发出HTTP/ HTTPS请求。

1、request

测试:

使用Get方法向测试网站发送一个请求。

package main

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

func main() {
    //使用Get请求获得一个
	resp, _ := http.Get("http://jsonplaceholder.typicode.com/users")

	l:=resp.Body//响应体

	io.Copy(os.Stdout, l)//将响应体数据输出
    //Fprint系函数按照默认格式输出、在此不适用
    
    
    request := resp.Request//获取请求
    
    
    fmt.Println("Header    ",request.Header)
	fmt.Println("Body    ",request.Body)
	fmt.Println("Method    ",request.Method)

	defer l.Close()

}

2、web服务

http包中还提供了web服务。

使用非常简单,只需要两步就可以启动一个简单的服务器:

1、设置一个入口处理器

使用http.HandleFunc()或者http.Handle()函数设置入口。

2、监听端口并启动服务

http.ListenAndServe()用于监听并启动服务。

package main

import (
	"fmt"
	"net/http"
)

func main() {
	
    //处理器设置,第一个为入口url,第二个为处理器函数名
	http.HandleFunc("/hello",hand)

    //监听地址,第二个参数为Handler,nil代表不使用Handler
	http.ListenAndServe(":8888",nil)
}


//处理器函数,必须接受w http.ResponseWriter, r *http.Request作为参数
func hand(w http.ResponseWriter, r *http.Request)  {

	fmt.Fprintln(w,"<h1>Hello Web</h1>")//将数据发送给响应写入
}

此时运行服务,访问浏览器 localhost:8888/hello,出现以下内容:

Hello Web

3、模板引擎

go标准库中自带了模板引擎。

所谓模板引擎就是某些文本可以重复使用,只有部分数据需要变更,能够将需要变更的部分数据用特定的语法代替,用于被实际数据注入的一种机制。

如下:{{data}}中的data可以从外界注入,外界注入什么数据就会输出hello 什么。

<body>
    <h1>hello  {{data}}</h1>
</body>

template包(html/template)实现了数据驱动的模板,用于生成可对抗代码注入的安全HTML输出。

go中的模本语法如下:

{{.}}
使用{{}}圈住数据,.代表注入的数据。
如果注入的是结构体或者map,通过字段名字和key表示.

{{.Name}}拿到注入结构体的Name字段,如果字段不可见,即字段名小写,此时无法拿到数据
{{.k1}}拿到植入map的key为k1的value

测试:

import (
	"html/template"
	"os"
)

const tpl  ="hello world ,hello {{.}}"//模板字段

func main() {

    //给模板起个名字并解析tpl字段
	parse, _ := template.New("tpl_1").Parse(tpl)

    //开始解析,参数一是将解析后的数据输出、参数二是注入的数据
	parse.Execute(os.Stdout,"杰米")

}

//此时控制台:
hello world ,hello 杰米

模板引擎也常用于web中,用于对html的解析。

package main

import (
	"fmt"
	"html/template"
	"net/http"
)

func main() {

	http.HandleFunc("/hello",hand)

	http.ListenAndServe(":8888",nil)
}

func hand(w http.ResponseWriter, r *http.Request)  {



	fmt.Fprintln(w,"<h1>Hello Web</h1>")

    //从文件中解析
	files, err:= template.ParseFiles("you url/hello.html")

	if err!=nil{
		fmt.Println(err)
	}
    //写入响应中
	files.Execute(w,"jim")


}

posted @ 2020-11-25 11:37  cgl_dong  阅读(315)  评论(0编辑  收藏  举报