zoukankan      html  css  js  c++  java
  • net包之IPConn

    TCP和UDP并不是建立在IP层之上唯一的协议。该网站:http://www.iana.org/assignments/protocol-numbers 列表上大约有140关于它们(该列表往往在Unix系统的/etc/protocols文件上。)。TCP和UDP在这个名单上分别为6和17。

    Go允许你建立所谓的原始套接字,使您可以使用这些其它协议通信,或甚至建立你自己的。但它提供了最低限度的支持: 它会连接主机, 写入和读取和主机之间的数据包。在接下来的章节中,我们将着眼于设计和实现自己的基于TCP之上的协议; 这部分认为同样的问题存在于IP层。

    为了简单起见,我们将使用几乎最简单的例子: 如何发送一个ping消息给主机。Ping使用"echo"命令的ICMP协议。这是一个面向字节协议, 客户端发送一个字节流到另一个主机, 并等待主机的答复。格式如下:

    • 首字节是8, 表示echo消息
    • 第二个字节是0
    • 第三和第四字节是整个消息的校验和
    • 第五和第六字节是一个任意标识
    • 第七和第八字节是一个任意的序列号
    • 该数据包的其余部分是用户数据

    下面的程序将准备一个IP连接,发送一个ping请求到主机,并得到答复。您可能需要root权限才能运行成功。

    /* Ping
     */
    package main
    
    import (
            "bytes"
            "fmt"
            "io"
            "net"
            "os"
    )
    
    func main() {
            if len(os.Args) != 2 {
                    fmt.Println("Usage: ", os.Args[0], "host")
                    os.Exit(1)
            }
    
            addr, err := net.ResolveIPAddr("ip", os.Args[1])
            if err != nil {
                    fmt.Println("Resolution error", err.Error())
                    os.Exit(1)
            }
    
            conn, err := net.DialIP("ip4:icmp", addr, addr)
            checkError(err)
    
            var msg [512]byte
            msg[0] = 8  // echo
     msg[1] = 0  // code 0
     msg[2] = 0  // checksum, fix later
     msg[3] = 0  // checksum, fix later
     msg[4] = 0  // identifier[0]
     msg[5] = 13 //identifier[1]
     msg[6] = 0  // sequence[0]
     msg[7] = 37 // sequence[1]
     len := 8
    
            check := checkSum(msg[0:len])
            msg[2] = byte(check >> 8)
            msg[3] = byte(check & 255)
    
            _, err = conn.Write(msg[0:len])
            checkError(err)
    
            _, err = conn.Read(msg[0:])
            checkError(err)
    
            fmt.Println("Got response")
            if msg[5] == 13 {
                    fmt.Println("identifier matches")
            }
            if msg[7] == 37 {
                    fmt.Println("Sequence matches")
            }
    
            os.Exit(0)
    }
    
    func checkSum(msg []byte) uint16 {
            sum := 0
    
            // assume even for now
     for n := 1; n < len(msg)-1; n += 2 {
                    sum += int(msg[n])*256 + int(msg[n+1])
            }
            sum = (sum >> 16) + (sum & 0xffff)
            sum += (sum >> 16)
            var answer uint16 = uint16(^sum)
            return answer
    }
    
    func checkError(err error) {
            if err != nil {
                    fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
                    os.Exit(1)
            }
    }
    
    func readFully(conn net.Conn) ([]byte, error) {
            defer conn.Close()
    
            result := bytes.NewBuffer(nil)
            var buf [512]byte
            for {
                    n, err := conn.Read(buf[0:])
                    result.Write(buf[0:n])
                    if err != nil {
                            if err == io.EOF {
                                    break
                            }
                            return nil, err
                    }
            }
            return result.Bytes(), nil
    }
    
  • 相关阅读:
    Python之面向对象新式类和经典类
    Python之面向对象继承和派生
    Python之面向对象类和对象
    Python之面向对象的程序设计
    Python之面向对象函数式编程
    Python之内置函数
    列表解析与生成器表达式
    03: 交换机基本原理与配置
    02: 网络布线与数制转换
    01:数据封装解封的过程
  • 原文地址:https://www.cnblogs.com/zhepama/p/3028501.html
Copyright © 2011-2022 走看看