设为首页 收藏本站
查看: 1383|回复: 0

[经验分享] golang socket 实现分析(一)

[复制链接]

尚未签到

发表于 2018-9-20 06:49:23 | 显示全部楼层 |阅读模式
  socket:tcp/udp、ip构成了网络通信的基石,tcp/ip是面向连接的通信协议
  要求建立连接时进行3次握手确保连接已被建立,关闭连接时需要4次通信来保证客户端和,服务端都已经关闭
  在通信过程中还有保证数据不丢失,在连接不畅通时还需要进行超时重试等等
  所以socket就是封装了这一套基于tcp/udp/ip协议细节,提供了一系列套接字接口进行通信
  client端通过以下方式与Server端进行通信
DSC0000.png

  先看看再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 -1, os.NewSyscallError("socket", err)  }
  //设置socket位非阻塞
if err = syscall.SetNonblock(s, true); err != nil {  closeFunc(s)
return -1, 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

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-597067-1-1.html 上篇帖子: golang中的rpc包用法 下篇帖子: slice小结
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表