<返回更多

go语言网络编程之socket sever的实现

2019-07-01    
加入收藏

首先说一下socket,网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket(百度百科)。

go语言网络编程之socket sever的实现

图片来源于网络

其本质就是就是编程接口(API),对TCP、UDP的封装。使用时我们可以指定使用的协议,今天主要使用TCP,目前我们大多数使用的还是TCP,虽然速度没有UDP快,但是更安全,如果有能力的同学,可以使用UDP同时在上层能够检测到传输数据是否有丢失,这个不是很简单做到的。今天就以TCP为例,说一下Go语言实现一个简单的sever。

go语言的网络编程主要是net包,我们使用:

func Listen(network, address string) (Listener, error)

这个接口来监听我们的端口,并且指定协议。这里会返回一个Listener对象,就是一个接口,其中实现了三个方法:Accept(),Close(),Addr()。其中Accept返回一个Conn对象,这个就是我们最终需要的,这里面包括了请求数据。看一下简单的代码实现:

func main() {
 addr := "0.0.0.0:8080"
 listener, err := net.Listen("tcp", addr)
 if err != nil {
 panic(err)
 }
 defer listener.Close()
 for {
 conn, err := listener.Accept()
 if err != nil {
 break
 }
 go handleReq(conn) // 启用一个协程处理请求
 }
}
func handleReq(conn net.Conn) {
 // todo
}

上面的代码实现了对本地8080端口的监听,每当有一个请求过来时,我们单独一个协程来处理这个请求,这样不至于一个请求阻塞在这里。

接下来我们就是对请求的处理,在看handleReq方法的具体实现:

func handleReq(conn net.Conn) {
 defer conn.Close()
 data := make([]byte, 1024)
 _, err := conn.Read(data)
 if err != nil {
 panic(err)
 }
 // 获取收到的数据后,存到 data 中,根据实际需求做处理。
 fmt.Println(string(data))
 // 处理之后,我们将需要的信息返回给客户端。
 res := "收到了你的请求"
 _, err = conn.Write([]byte(res))
 if err != nil {
 panic(err)
 }
}

在方法中我们接收一个conn,就是与客户端的连接,我们可以想象成sever与client的连接有一个管道,我们在管道中传输数据,而这个conn对象就是这个管道,我们先从这个管道中读取客户端发来的数据,接着根据业务需求来正确的处理,例如这个请求可能是一个用户登录的请求,我们发来的数据就是用户输入的用户名和密码等信息,在我们知道这是一个用户登录的请求时,就知道接下来该怎么做了。

那么我们如何知道这个是用户登录的请求呢?这时我们就可以通过一个规定,传过来的数据可以是一个strct,其中一个字段是Type,我们可以根据这个Type来知道这到底是一个什么请求,然后在对请求数据做处理。比如,查询一下这个用户名是否存在,密码是否正确等,然后将对应信息返回即可。这时,我们通过这根管道已经发送完数据,将管道关闭就可以了:

defer conn.Close()

建议大家多用defer,go语言提供这个很大程度的方便了写代码。

至此我们sever的简单实例就完成了,我们回头再看,我们先是使用for循环,不断的接收客户端的请求,每当有一个请求,我们创建一个协程来处理,这样我们就可以不断的接收请求,只需要将于客户端连接的管道给一个协程就好了。

这是最简单的sever的实现,但是我们在项目中,其实可以对其封装,多利用go的并发特性,使用channel来通信,例如,我们可以将sever封装成一个对象,sever监听开始时,创建一个协程来等待客户端的接口,同时创建一个协程读取请求数据,还可以创建一个协程来对每个请求数据单独处理等,多个协程工作效率会更好的,对并发很高时还是很有效的。

go语言网络编程之socket sever的实现
声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>