网 络 编 程
如何用Go语言网络编程,Go语言库中提供了net包,支持基于IP层,TCP/UDP层及更高的层面(HTTP,FTP)等网络协议。ip层被称为RawSocket。
Socket编程
传统的Socket编程时一般会一步步展开调用。如下:
- 建立Socket:使用socket()函数
- 绑定socket函数:使用bind()函数
- 监听:使用listen()函数,或者链接使用connect()函数
- 连接:使用accept()函数
- 接收:使用receive()函数。或者发送:使用send()函数 Go语言中把上述所有的步骤进行了封装和抽象,只需要调用一个函数net.Dial()搞定!!!
Dial()函数
Dial()函数如下:
func Dial(net, addr string) (Conn, error)
- net:网络协议的名字
- addr:IP地址或域名,可以带端口号如需要访问8080端口ip:8080 连接成功返回连接对象,连接失败返回error信息。举例说明:
TCP连接:
conn, err := net.Dial("tcp", "192.168.0.1:9100")
UDP链接:
conn, err := net.Dial("udp", "192.168.0.1:339")
ICMP链接(协议名称)
conn, err := net.Dial("ip4:icmp", "www.juejin.cn")
ICMP链接(协议编号):
conn, err := net.Dial("ip4:1", "117.34.47.240")
成功建立连接后,可以进行数据的发送和接收。发送数据时,使用conn的Write()成员方法,接收数据时使用Read()方法。
HTTP 编程
HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网上应用最为广泛的一种网络协议,定义了客户端和服务端之间请求与响应的传输标准。
Go语言标准库内建提供了net/http包,涵盖了HTTP客户端和服务端的具体实现。使用net/http包,可以很方便地编写HTTP客户端或服务端的程序。
HTTP客户端
基本方法
net/http包的Client类型提供了如下的方法,可以用最简洁的方式实现HTTP请求:
func (c *Client) Get(url string) (r *Response, err error)
func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, err
error)
func (c *Client) PostForm(url string, data url.Values) (r *Response, err error)
func (c *Client) Head(url string) (r *Response, err error)
func (c *Client) Do(req *Request) (resp *Response, err error)
http.Get()
java中利用工具类RestTemplate,请求目标url,返回json对象如下:
@Autowired
private RestTemplate restTemplate;
JSONObject jsonObject = restTemplate.getForObject(url, JSONObject.class);
Go语言中需要调用一个网站返回网站信息打印,如下:
resp, err := http.Get("https://juejin.cn/")
if err != nil {
// 处理错误 ...
return
}
defer resp.Body.close()
io.Copy(os.Stdout, resp.Body)
http.Post()
java中post请求利用工具类RestTemplate,请求目标url,请求body内容为json,返回字符串为String格式如下:
@Autowired
private RestTemplate restTemplate;
String strsuiteAccessToken= restTemplate.postForObject(url, json, String.class);
Go语言中post方法需要传三个参数:请求目标url,资源类型(MIMEType),数据的比特流([]byte形式)。如下上传图片的post请求:
resp, err := http.Post("http://ks3.com/upload", "image/jpeg", &imageDataBuf)
if err != nil {
// 处理错误
return
}
if resp.StatusCode != http.StatusOK {
// 处理错误
return
}
// ...
http.PostForm()
http.PostForm()方法实现了标准编码格式为application/x-www-form-urlencoded的表单提交,一般是前端HTML页面提交Form表单里面的内容提交到后台用Form表单提交。如下:
resp, err := http.PostForm("http://jeujin.com/post", url.Values{"title":
{"article title"}, "content": {"article body"}})
if err != nil {
// 处理错误
return
}
// ...
http.Head()
HTTP中的Head请求方式表明只请求目标URL的头部信息,同http.Get()方法一样,只需传入目标URL一个参数即可
resp, err := http.Head("http://juejin.com/")
(*http.Client).Do()
如果发起的HTTP请求需要更多的定制信息,我们希望设定一些自定义的Http Header字段,比如设定自定义的"User-Agent",而不是默认的 "Go http package",比如我需要在Head加一个加密字段用于验签。
req, err := http.NewRequest("GET", "http://example.com", nil)
// ...
req.Header.Add("User-Agent", "Gobook Custom User-Agent")
req.Header.Add("sign", "13w9kjkjijdkw")
// ...
// ...
client := &http.Client{ //... }
resp, err := client.Do(req)
除了基本HTTP操作,Go语言标准库也暴露了比较底层的HTTP相关库,让开发者可以基于这些库灵活定制HTTP服务和使用HTTP服务。比如自定义http.Client,自定义http.Transport,和自定义 http.RoundTripper接口。
GO语言中的HTTP可以抽象的分为“业务层”和“传输层”,通常调用方式在业务层写的,他们只关注业务的本身逻辑,而无需关心非业务相关的技术如下细节:
- HTTP 底层传输细节
- HTTP 代理
- gzip 压缩
- 连接池及其管理
- 认证(SSL或其他认证方式) HTTP Client 在底层抽象了http.RoundTripper 接口,而http.Transport实现了该接口,从而能够处理更多的细节,这一层可称为“传输层”,通过业务层封装目标url,目标资源,请求参数等,经过传输层去请求目标资源,然后响应请求。在客户端和服务端建立连接和断开连接,http协议还有很经典的“三次握手四次挥手”的约定。这是后话下回分解!!
备注
本文正在参与「掘金Golang主题学习月」, 点击查看活动详情。