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 实现分析(一)的更多相关文章

  1. golang 性能优化分析:benchmark 结合 pprof

    前面 2 篇 golang 性能优化分析系列文章: golang 性能优化分析工具 pprof (上) golang 性能优化分析工具 pprof (下) 一.基准测试 benchmark 简介 在 ...

  2. golang socket与Linux socket比较分析

    在posix标准推出后,socket在各大主流OS平台上都得到了很好的支持.而Golang是自带runtime的跨平台编程语言,Go中提供给开发者的socket API是建立在操作系统原生socket ...

  3. Linux下Golang Socket编程原理分析与代码实现

    在POSIX标准推出后,socket在各大主流OS平台上都得到了很好的支持.而Golang是自带Runtime的跨平台编程语言,Go中提供给开发者的Socket API是建立在操作系统原生Socket ...

  4. golang socket 分析

    socket:tcp/udp.ip构成了网络通信的基石,tcp/ip是面向连接的通信协议 要求建立连接时进行3次握手确保连接已被建立,关闭连接时需要4次通信来保证客户端和,服务端都已经关闭 在通信过程 ...

  5. Golang源码分析之目录详解

    开源项目「go home」聚焦Go语言技术栈与面试题,以协助Gopher登上更大的舞台,欢迎go home~ 导读 学习Go语言源码的第一步就是了解先了解它的目录结构,你对它的源码目录了解多少呢? 目 ...

  6. golang http server分析(一)

    http:http请求过程实质上是一个tcp连接通信,具体通过socket接口编码实现 在go中是通过listenAndServer()方法对外提供了一个http服务,在该方法中完成了socket的通 ...

  7. Golang socket

    1.本例子实现了一个简单的TCP echo.客户端发送Hello,服务端回应World. 参考:<Socket编程> 2.服务端代码 package main import ( " ...

  8. golang https server分析

    https: HTTPS是http安全版本的实现,在http与tcp之间加了一层ssl/tls安全传输协议 为了防止请求被监听.篡改.冒充,在tls实现过程中引入了数字证书机制,数字证书由第三方权威机 ...

  9. 基于Golang的逃逸分析(Language Mechanics On Escape Analysis)

    何为逃逸分析 在编译程序优化理论中,逃逸分析是一种确定指针动态范围的方法——分析在程序的哪些地方可以访问到指针.它涉及到指针分析和形状分析. 当一个变量(或对象)在子程序中被分配时,一个指向变量的指针 ...

随机推荐

  1. MSSQL-SQL SERVER一些使用中的技巧

    获取前一天时间"getdate() - 1" 获取上一小时时间"dateadd(hour, -1, getdate())" order by field1, f ...

  2. Docker基础概念及操作

    一.概念: Docker 属于Linux 容器的一种封装,提供简单易用的容器使用接口.目前最流行的Linux 容器解决方案. Docker 将应用程序与该程序的依赖,打包在一个文件里面.运行这个文件, ...

  3. img图片自适应宽和高[转]

    控制缩略图常见的是JS来控制,还有就是最直接的方法定义img的宽高:下面两种方法自适应宽和高,zhenzhai推荐使用CSS方法:一.CSS方法:主 要是在CSS设置最小值和最大值(max-width ...

  4. matplotlib热图

    1.基础知识点回顾 1.plot(x, y, marker='D')表示绘制折线图,marker设置样式菱形. 2.scatter(x, y, marker='s', color='r')绘制散点图, ...

  5. Mysql 数据备份与恢复,用户创建,授权

    Mysql 数据备份与恢复,用户创建,授权 1. Mysqldump >outfile.sql 2. Mysql –uxxx –pxxx < backfile.sql 3. Create  ...

  6. 上传一个 游戏server架构图

  7. Struts如何获取客户端ip地址

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...

  8. 程序员减少bug

    1.认真理解需求 2.构思好程序逻辑流程,再编写 3.编写单元测试 4.多进行case测试,做好功能测试 5.互相review代码

  9. javascript Dictionary data structures

    Dictionary常被称为数据字典,是一种用来保存键值对的数据结构,比如我们日常的电话本,就是一个Dictionary.我们通过键(名字),就可以访问到对应的值(电话号码).在C++与java中我们 ...

  10. Linux数据库:MYSQL启用和查看二进制日志

    在/etc/my.cnf文件中[mysqld]下加上: server-id = 1 (在整个Mysql集群中保证唯一) log-bin = binlog  log-bin-index = binlog ...