【go网络编程】-Socket编程

栏目: 服务器 · 发布时间: 5年前

内容简介:网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。Socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作"套接字",用于描述IP地址和端口

什么是socket

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

建立网络通信连接至少要一对端口号(socket)。socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供 程序员 做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。

Socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原意那样,像一个多孔插座。插座是用来给插头提供一个接口让其通电的,此时我们就可以将插座当做一个服务端,不同的插头当做客户端。

客户端Dial()

按照指定大小循环读取

func main() {
    addr := "wwww.baidu.com:80" //定义主机名
    conn,err := net.Dial("tcp",addr) //拨号操作,需要指定协议。
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(conn.RemoteAddr().String()) //220.181.57.217:80
    fmt.Println(conn.LocalAddr()) //192.168.0.120:62662
    fmt.Println(reflect.TypeOf(conn.LocalAddr())) //*net.TCPAddr
    fmt.Println(reflect.TypeOf(conn.RemoteAddr()))
    n,err := conn.Write([]byte("GET / HTTP/1.1\r\n\r\n")) //向服务端发送数据。用n接受返回的数据大小。
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("写入的大小是:",n)//18

    buf := make([]byte,10) //定义一个切片的长度是1024。

    for  {
        n,err = conn.Read(buf) //接收到的内容大小。
        if err == io.EOF {
            conn.Close()
        }
        fmt.Print(string(buf[:n]))
    }

    fmt.Println(string(buf[:n])) //将接受的内容都读取出来。
}

按行读取

r := bufio.NewReader(conn) //将这个链接(connection)包装以下。将conn的内容都放入r中,但是没有进行读取
    for  {
        line,err := r.ReadString('\n') //将r的内容也就是conn的数据按照换行符进行读取。
        if err == io.EOF {
            conn.Close()
        }
        fmt.Print(line)
    }

io读取http请求

io.Copy(os.Stdout,conn)

服务端Listen()

package main

import (
    "net"
    "log"
    "time"
)

func Handle_conn(conn net.Conn) { //这个是在处理客户端会阻塞的代码。
    //var buf = make([]byte, 10) //读取信息
    //n, err := c.Read(buf)

    conn.Write([]byte("xxxxx\n"))  //通过conn的wirte方法将这些数据返回给客户端。
    conn.Write([]byte("hello world!\n"))
    time.Sleep(time.Minute)
    conn.Close() //与客户端断开连接。
}

func main() {
    addr := "0.0.0.0:8080" //表示监听本地所有ip的8080端口,也可以这样写:addr := ":8080"
    listener,err := net.Listen("tcp",addr)
    if err != nil {
        log.Fatal(err)
    }
    defer listener.Close()

    for  {
        conn,err := listener.Accept() //用conn接收链接
        if err != nil {
            log.Fatal(err)
        }
        go Handle_conn(conn)  //开启多个协程。
    }
}

特殊情况

建立连接

  • 网络不可达或对方服务未启动
  • 对方服务的listen backlog满

对方服务器很忙,瞬间有大量client端连接尝试向server建立,server端的listen backlog队列满,server accept不及时((即便不accept,那么在backlog数量范畴里面,connect都会是成功的,因为new conn已经加入到server side的listen queue中了,accept只是从queue中取出一个conn而已),这将导致client端Dial阻塞。我们还是通过例子感受Dial的行为特点:

  • 网络延迟较大,Dial阻塞并超时

服务端Socket读

  • Socket中无数据

连接建立后,如果对方未发送数据到socket,接收方(Server)会阻塞在Read操作上,这和前面提到的“模型”原理是一致的。执行该Read操作的goroutine也会被挂起。runtime会监视该socket,直到其有数据才会重新

调度该socket对应的Goroutine完成read。

  • Socket中有部分数据

如果socket中有部分数据,且长度小于一次Read操作所期望读出的数据长度,那么Read将会成功读出这部分数据并返回,而不是等待所有期望数据全部读取后再返回。

  • 读取操作超时

客户端Socket写

  • 写阻塞

TCP连接通信两端的OS都会为该连接保留数据缓冲,一端调用Write后,实际上数据是写入到OS的协议栈的数据缓冲的。TCP是全双工通信,因此每个方向都有独立的数据缓冲。当发送方将对方的接收缓冲区以及自身的发送缓冲区写满后,Write就会阻塞。

  • 写入部分数据
  • 写入超时

如果非要给Write增加一个期限,那我们可以调用SetWriteDeadline方法。我们copy一份client5.go,形成client6.go,在client6.go的Write之前增加一行timeout设置代码:

conn.SetWriteDeadline(time.Now().Add(time.Microsecond * 10))

ICMP

ICMP是用来对网络状况进行反馈的协议,可以用来侦测网络状态或检测网路错误。

参考文章

TCP


以上所述就是小编给大家介绍的《【go网络编程】-Socket编程》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

无线:网络文化中激进的经验主义

无线:网络文化中激进的经验主义

[英] 阿德里安·麦肯齐 / 张帆 / 上海译文出版社 / 2018-9

本书研究了无线是如何成为当代人类经验的主角的。从路由器、智能电话、电子书、城市到在线工作、服务协议、玩具以及国家等各个方面,人们已经感觉到了无线技术所引发的变革。本书作者援引一个世纪之前的哲学技术来分析当代最前沿的后网络时代的人类状况。基于威廉•詹姆斯的实用主义哲学相关的彻底经验主义,作者提出了把失序的无线网络世界与人们的感知匹配起来的新方式。一起来看看 《无线:网络文化中激进的经验主义》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具