linux c构造tcp报文,Go语言linux下构造tcp数据包(不使用net包和Cgo)

Golang可以通过syscall包中的相关socket函数(Windows和Linux中syscall中网络编程的函数不太一样)来进行网络编

程,可以用我们熟悉的方法使用raw socket,因为最近在搞一些协议的学习,所以特意试了试,和普通的linux+C的

socket编程基本没什么区别。

代码如下:

package main

import (

"bytes"

"encoding/binary"

. "fmt"

"strconv"

"strings"

"syscall"

"unsafe"

)

type TCPHeader struct {

SrcPort uint16

DstPort uint16

SeqNum uint32

AckNum uint32

Offset uint8

Flag uint8

Window uint16

Checksum uint16

UrgentPtr uint16

}

type PsdHeader struct {

SrcAddr uint32

DstAddr uint32

Zero uint8

ProtoType uint8

TcpLength uint16

}

func inet_addr(ipaddr string) uint32 {

var (

segments []string = strings.Split(ipaddr, ".")

ip [4]uint64

ret uint64

)

for i := 0; i < 4; i++ {

ip[i], _ = strconv.ParseUint(segments[i], 10, 64)

}

ret = ip[3]<<24 + ip[2]<<16 + ip[1]<<8 + ip[0]

return uint32(ret)

}

func htons(port uint16) uint16 {

var (

high uint16 = port >> 8

ret uint16 = port<<8 + high

)

return ret

}

func CheckSum(data []byte) uint16 {

var (

sum uint32

length int = len(data)

index int

)

for length > 1 {

sum += uint32(data[index])<<8 + uint32(data[index+1])

index += 2

length -= 2

}

if length > 0 {

sum += uint32(data[index])

}

sum += (sum >> 16)

return uint16(^sum)

}

func main() {

var (

msg string

psdheader PsdHeader

tcpheader TCPHeader

)

Printf("Input the content: ")

Scanf("%s", &msg)

/*填充TCP伪首部*/

psdheader.SrcAddr = inet_addr("127.0.0.1")

psdheader.DstAddr = inet_addr("127.0.0.1")

psdheader.Zero = 0

psdheader.ProtoType = syscall.IPPROTO_TCP

psdheader.TcpLength = uint16(unsafe.Sizeof(TCPHeader{})) + uint16(len(msg))

/*填充TCP首部*/

tcpheader.SrcPort = htons(3000)

tcpheader.DstPort = htons(8080)

tcpheader.SeqNum = 0

tcpheader.AckNum = 0

tcpheader.Offset = uint8(uint16(unsafe.Sizeof(TCPHeader{}))/4) << 4

tcpheader.Flag = 2 //SYN

tcpheader.Window = 60000

tcpheader.Checksum = 0

/*buffer用来写入两种首部来求得校验和*/

var (

buffer bytes.Buffer

)

binary.Write(&buffer, binary.BigEndian, psdheader)

binary.Write(&buffer, binary.BigEndian, tcpheader)

tcpheader.Checksum = CheckSum(buffer.Bytes())

/*接下来清空buffer,填充实际要发送的部分*/

buffer.Reset()

binary.Write(&buffer, binary.BigEndian, tcpheader)

binary.Write(&buffer, binary.BigEndian, msg)

/*下面的操作都是raw socket操作,大家都看得懂*/

var (

sockfd int

addr syscall.SockaddrInet4

err error

)

if sockfd, err = syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_TCP); err != nil {

Println("Socket() error: ", err.Error())

return

}

defer syscall.Shutdown(sockfd, syscall.SHUT_RDWR)

addr.Addr[0], addr.Addr[1], addr.Addr[2], addr.Addr[3] = 127, 0, 0, 1

addr.Port = 8080

if err = syscall.Sendto(sockfd, buffer.Bytes(), 0, &addr); err != nil {

Println("Sendto() error: ", err.Error())

return

}

Println("Send success!")

}

如果转载请注明文章出处:http://blog.csdn.net/gophers/article/details/20393601

有疑问加站长微信联系(非本文作者)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值