golang socket 分析
socket:tcp/udp、ip构成了网络通信的基石,tcp/ip是面向连接的通信协议
要求建立连接时进行3次握手确保连接已被建立,关闭连接时需要4次通信来保证客户端和,服务端都已经关闭
在通信过程中还有保证数据不丢失,在连接不畅通时还需要进行超时重试等等
所以socket就是封装了这一套基于tcp/udp/ip协议细节,提供了一系列套接字接口进行通信
client端通过以下方式与Server端进行通信
先看看再golang中如何进行socket编程
// 创建socket文件描述符,绑定ip:port,改变socket状态为监听状态
ln, err := net.Listen("tcp", addr)
// 返回时关闭tcp连接
defer l.Close()
if err != nil {
return err
}
for {
// 从socket recive队列里获取一个建立好的连接
conn,err := ln.Accept()
if err != nil {
return err
}
// 新起一个goroutine处理连接
go handler(conn)
} func handler(conn net.Con) {
// 关闭连接
conn.Close()
}
介绍几个跟socket相关的底层函数
socketFunc func(int, int, int) (int, error) = syscall.Socket //创建一个socket文件描述符
func Bind(fd int, sa Sockaddr) (err error) //绑定一个本机IP:port到socket文件描述符上
listenFunc func(int, int) error = syscall.Listen //监听是否有tcp连接请求
acceptFunc func(int) (int, syscall.Sockaddr, error) = syscall.Accept //获取一个建立好的tcp连接
connectFunc func(int, syscall.Sockaddr) error = syscall.Connect //发起tcp连接请求
closeFunc func(int) error = syscall.Close //关闭连接
下面介绍下在golang中socket接口是如何通过这几个底层函数完成socket封装的。
socket:创建的socket默认是阻塞的,通过syscall.SetNonblock()可以将socket设置为非阻塞模式
func sysSocket(family, sotype, proto int) (int, error) {
syscall.ForkLock.RLock()
//创建socket文件描述符
s, err := socketFunc(family, sotype, proto)
if err == nil {
// 关闭从父线程拷贝过来的文件描述符后,再执行子线程程序
syscall.CloseOnExec(s)
}
syscall.ForkLock.RUnlock()
if err != nil {
return -, os.NewSyscallError("socket", err)
} //设置socket位非阻塞
if err = syscall.SetNonblock(s, true); err != nil {
closeFunc(s)
return -, os.NewSyscallError("setnonblock", err)
}
return s, nil
}
listen:设置socket文件描述符为监听状态,把监听到的请求放入未完成的请求队列中,完成3次握手后,会把连接放入已完成的请求队列中等待accept获取处理
func (fd *netFD) listenStream(laddr sockaddr, backlog int) error {
if err := setDefaultListenerSockopts(fd.sysfd); err != nil {
return err
}
if lsa, err := laddr.sockaddr(fd.family); err != nil {
return err
} else if lsa != nil {
//绑定ip:port
if err := syscall.Bind(fd.sysfd, lsa); err != nil {
return os.NewSyscallError("bind", err)
}
}
//监听socket文件描述符
if err := listenFunc(fd.sysfd, backlog); err != nil {
return os.NewSyscallError("listen", err)
}
if err := fd.init(); err != nil {
return err
}
lsa, _ := syscall.Getsockname(fd.sysfd)
fd.setAddr(fd.addrFunc()(lsa), nil)
return nil
}
accept:从已完成的队列里取出一个tcp连接,返回的是由内核根据当前socket信息创建的全新的tcp连接来处理数据的,同时原始创建好的socket还可以继续监听其他连接请求,如果没有获取到则阻塞当前goroutine
func accept(s int) (int, syscall.Sockaddr, error) {
//获取连接
ns, sa, err := acceptFunc(s)
if err == nil {
syscall.CloseOnExec(ns)
}
if err != nil {
return -1, nil, os.NewSyscallError("accept", err)
}
//设置为非阻塞
if err = syscall.SetNonblock(ns, true); err != nil {
closeFunc(ns)
return -1, nil, os.NewSyscallError("setnonblock", err)
}
return ns, sa, nil
}
connect:client端发起连接请求
//发起连接请求
func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time, cancel <-chan struct{}) error {
switch err := connectFunc(fd.sysfd, ra); err {
//异常处理
....
}
}
close:
//关闭连接请求
func (fd *netFD) destroy() {
//关闭连接
fd.pd.Close()
//释放系统资源
closeFunc(fd.sysfd)
fd.sysfd = -
runtime.SetFinalizer(fd, nil)
}
golang socket 分析的更多相关文章
- Golang逃逸分析
Golang逃逸分析 介绍逃逸分析的概念,go怎么开启逃逸分析的log. 以下资料来自互联网,有错误之处,请一定告之. sheepbao 2017.06.10 什么是逃逸分析 wiki上的定义 In ...
- golang socket与Linux socket比较分析
在posix标准推出后,socket在各大主流OS平台上都得到了很好的支持.而Golang是自带runtime的跨平台编程语言,Go中提供给开发者的socket API是建立在操作系统原生socket ...
- Linux下Golang Socket编程原理分析与代码实现
在POSIX标准推出后,socket在各大主流OS平台上都得到了很好的支持.而Golang是自带Runtime的跨平台编程语言,Go中提供给开发者的Socket API是建立在操作系统原生Socket ...
- golang socket 实现分析(一)
socket:tcp/udp.ip构成了网络通信的基石,tcp/ip是面向连接的通信协议 要求建立连接时进行3次握手确保连接已被建立,关闭连接时需要4次通信来保证客户端和,服务端都已经关闭 在通信过程 ...
- Golang socket
1.本例子实现了一个简单的TCP echo.客户端发送Hello,服务端回应World. 参考:<Socket编程> 2.服务端代码 package main import ( " ...
- golang trace 分析 简例
今天,通过一个例子,一方面熟悉trace在自定义范围内的分析,另一方面golang 在协程调度策略上的浅析. Show Code // trace_example.go package main im ...
- golang逃逸分析和竞争检测
最近在线上发现一块代码逻辑在执行N次耗时波动很大1ms~800ms,最开始以为是gc的问题,对代码进行逃逸分析,看哪些变量被分配到堆上了,后来发现是并发编程时对一个切片并发的写,导致存在竞争,类似下面 ...
- [转] golang socket
server.go package main import ( "net" "fmt" "io/ioutil" "time&quo ...
- Golang Socket编程
Socket编程 在很多底层网络应用开发者的眼里一切编程都是Socket,话虽然有点夸张,但却也几乎如此了,现在的网络编程几乎都是用Socket来编程.你想过这些情景么?我们每天打开浏览器浏览网页时, ...
随机推荐
- 简单的java Hadoop MapReduce程序(计算平均成绩)从打包到提交及运行
[TOC] 简单的java Hadoop MapReduce程序(计算平均成绩)从打包到提交及运行 程序源码 import java.io.IOException; import java.util. ...
- Biztalk AS2开发经验总结
一. 准备证书 4 1. 升级win2008 R2证书服务 4 2. 申请证书 6 二. 配置证书 13 1. 为AS2配置证书 13 2. ...
- Java如何判断字符串中包含有全角,半角符号
首先介绍下全角跟半角之间的区别: 在计算机屏幕上,一个汉字要占两个英文字符的位置,人们把一个英文字符所占的位置称为"半角",相对地把一个汉字所占的位置称为"全角" ...
- Use Prerender to improve AngularJS SEO
Use Prerender to improve AngularJS SEO Nuget Package of ASP.NET MVC HttpModule for prerender.io: Ins ...
- yii2 邮件发送(有图有真相)
经典的密码找回方案是发送邮件到用户邮箱然后修改密码,下面利用yii2 高级版的mail功能,进行邮件的发送,如下图 1.在comm/config/main-local.php中添加 'mailer' ...
- PHP编码规范实例
<?php /** * 符合psr-1,2的编程实例 * * @author 作者 描述 */ namespace Standard; // 顶部命名空间 / ...
- duilib绘制边框
在使用Duilib时,有时候需要绘制边框,绘制边框时候,上下左右都会有边框线:可在使用时,有时候不需要绘制四边(如果绘制四边,两个有边框的控制放在一起,就有一边会很粗),那该如何处理?,其实用法很简单 ...
- 爬虫:把廖雪峰的教程转换成 PDF 电子书
写爬虫似乎没有比用 Python 更合适了,Python 社区提供的爬虫工具多得让你眼花缭乱,各种拿来就可以直接用的 library 分分钟就可以写出一个爬虫出来,今天就琢磨着写一个爬虫,将廖雪峰的 ...
- 通过oledb驱动读取excel、csv数据丢失解决方案
1.问题出现 在开发应用程序的过程中,比较常用一功能就是通过oledb驱动读取excel.csv.text等文件:而最近有客户反映,在使用短信平台(下载地址:http://www.sms1086.co ...
- oracle系列笔记(2)---多表查询
多表查询 这篇文章主要讲四点: (1)oracle多表查询 (2)SQL99标准的连接查询 (3)子查询 (4)分级查询 oracle多表查询有两种方式,一种是oracle所 ...