Golang 的 socket 编程 (四):解决粘包问题及制定通信协议
一、概述 前面已经完成了一个完美的多并发 CS 模型,但美中不足的是没有解决粘包问题。 1.1 什么是粘包问题? 在网络传输中,数据都是通过数据流来传输的,也就是以比特来传输。传输的过程中我们可能会遇到各种各样的问题导致数据传输异常,最常见的就是网络发送时延。网络时延会导致服务端此时收到的数据的时间有偏 ... 阅读更多
一、概述 前面已经完成了一个完美的多并发 CS 模型,但美中不足的是没有解决粘包问题。 1.1 什么是粘包问题? 在网络传输中,数据都是通过数据流来传输的,也就是以比特来传输。传输的过程中我们可能会遇到各种各样的问题导致数据传输异常,最常见的就是网络发送时延。网络时延会导致服务端此时收到的数据的时间有偏 ... 阅读更多
一、概述 上一篇实现了一个 server 和 client 通信,完成了小写转大写的功能,但是是一个单任务式的响应:客户端发送连接接收响应,程序结束;服务端则接收数据响应数据也结束!就实际需要而言,并没有很大的用处,所以现在我们就给客户端和服务端添加上并发功能。 逻辑其实很简单,就是利用 golang 的 gor ... 阅读更多
一、概述 上一篇介绍了基本的函数和结构类型,这里就可以开始写服务端和客户端通信小程序了,通信的基本的流程如下: 如果服务端使用 Listen 来监听,那么可以不用 ResolveTCPAddr 函数。 现在我们就来写一个 server 和 client,实现功能:client 发送数据到 server,server 将 ... 阅读更多
工作的原因接触到 socket,要使用 socket 实现一个长连接。之前只在 C/C++上用过 socket,而且在学校的时候也只是简单的做聊天室小程序,并没有涉及到长连接。突然用到工作项目上,心里还是有点悬的,毕竟网上的资料也不是很多。这里就一步一步记录下学习的过程、遇到的问题以及最重要的——解决问题的方 ... 阅读更多
一、说明 切片 (slice) 是 golang 里面的可变长元素类型,不是数组或数组指针,本质是一个结构体。 slice 的声明如下 (位于安装目录下的 src/runtime/slice.go):
|
1 2 3 4 5 |
type slice struct { array unsafe.Pointer //array 是一个指针,指向实际的数据地址。 len int //slice 的长度 cap int //slice 的容量 } |
值得注意的是,切片除了有一个 len 属性表明当前 ... 阅读更多
一、 StructTag 介绍 StructTag 是 go 语言结构体中的一个标记字段,放在字段声明的后面,一般只有特定情况下会用到,如 json 的转化。 使用的时候只要把标记的字段用两个`包起来即可,标签内的语法形式通常为 key:"value",多个标记用空格隔开。 [crayon-69523229cf06 ... 阅读更多
一、说明 http.Header 结构包含请求头信息,官方定义如下,其实就是一个 map[string][]string 结构:
|
1 2 |
// A Header represents the key-value pairs in an HTTP header. type Header map[string][]string |
二、常用方法 因为就是一个简单的 map 结构,所以方法的运用也十分简单,常用的四种方法: 2.1 添加请求头字段 ... 阅读更多
一、说明 http.Response 是我们请求服务器之后得到的响应数据,结构如下:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
type Response struct { Status string StatusCode int Proto string ProtoMajor int ProtoMinor int Header Header Body io.ReadCloser ContentLength int64 TransferEncoding []string Close bool Trailer Header Request *Request TLS *tls.ConnectionState } |
其中常用的属性说明如下: Status:响应状态,字符串,"200 OK" StatusCode:响应状态码,200 、 304 、 404 等 Proto:协 ... 阅读更多
一、用法 range 类似迭代器,可以遍历数组,字符串,map 等等,对象的不同,返回的结果也不同。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package main import "fmt" func main(){ //数组的遍历 a := [3]int {1, 2, 3} for i, n := range a{ fmt.Println(i, n) } //切片的遍历 b := []int{2, 3, 4} for i, n := range b{ fmt.Println(i, n) } //map 的遍历 c := map[string]int{"Hello":1, "World":2} for k, v := range c{ fmt.Println(k, v) } } |
结果:
|
1 2 3 4 5 6 7 8 9 10 |
0 1 1 2 2 3 0 2 1 3 2 4 Hello 1 World 2 |
二、注意事项 1. range 会复制对象,而不是不是直接在原对 ... 阅读更多
一、常量 golang 中的常量和其他语言里的常量大多相同,必须在编译期有确定的值。
|
1 2 3 |
const x, y int = 1, 2 const Pi = 3.14 const str = "Hello World" |
也可以使用常量组的形式来声明:
|
1 2 3 4 5 |
const ( a = 1 b = "Hello World" c = false ) |
二、枚举 golang 中的枚举使用 iota 关键字来实 ... 阅读更多