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
有疑问加站长微信联系(非本文作者)