- 浏览: 768664 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (1045)
- 数据结构 (36)
- UML与设计模式 (42)
- c++ (87)
- rust (36)
- Qt (41)
- boost模板元编程 (43)
- Linux (77)
- 汇编 (4)
- 其它 (2)
- 烹饪 (3)
- unix c / socket (73)
- 软件工程 (4)
- shell (53)
- Python (37)
- c++ primer 5th(c++11) (22)
- 数据库/MySQL (27)
- 数据存储 (4)
- lisp (7)
- git (4)
- Utility (3)
- CDN与DNS (54)
- Http (53)
- php (7)
- nginx/lua/openresty (41)
- redis (11)
- TCP/IP (16)
- 互联网 (6)
- kernel (2)
- go (34)
- 区块链 (43)
- 比特股 (13)
- 以太坊 (23)
- 比特币 (23)
- 密码学 (10)
- EOS (53)
- DAG (1)
- docker (1)
- filecoin (7)
- solidity (65)
- ipfs (8)
- 零知识证明 (1)
- openzeppelin (3)
- java (1)
- defi (7)
- Ton (0)
最新评论
testTcp.h
testTcp.cpp
#ifndef TESTTCP_H #define TESTTCP_H #include <endian.h> #pragma pack(1) //ip协议头 struct IPHeader { unsigned char headerLen:4; unsigned char version:4; unsigned char tos; //服务类型 unsigned short totalLen; //总长度 unsigned short id; //标识 unsigned short flagOffset; //3位标志+13位片偏移 unsigned char ttl; //TTL unsigned char protocol; //协议 unsigned short checksum; //首部检验和 unsigned int srcIP; //源IP地址 unsigned int dstIP; //目的IP地址 }; //TCP首部 struct TCPHeader { unsigned short srcPort; //源端口 unsigned short dstPort; //目的端口 //封包序号 如果 TCP 数据太大时(大于 IP 封包的容许程度), 就得要进行分段.这个 Sequence Number 就是记录每个封包的序号, //可以让收受端重新将 TCP 的数据组合起来。序号字段的值则指的是本报文段所发送的数据的第一个字节的序号 unsigned int seqNum; //确认号 为了确认主机端确实有收到我们 client 端所送出的封包数据,我们 client 端当然希望能够收到主机方面的响应,那就是这个 Acknowledge Number 的用途了 //当 client 端收到这个确认码时,就能够确定之前传递的封包已经被正确的收下了.这个号是期望收到对方的下一个报文段的数据的第一个字节的序号 unsigned int ackNum; #if LITTLE_ENDIAN unsigned char reserved1:4; //保留6位中的4位首部长度 unsigned char headerLen:4; //tcp头部长度 //flags unsigned char fin:1; // 用来释放一个连接。当FIN=1时表示要求释放连接。 unsigned char syn:1; //同步当SYN=1时,表示这是一个连接请求或连接接受报文。 unsigned char rst:1; //复位,当TCP连接中出现了严重差错,必须释放连接。 unsigned char psh:1; //当两个应用程序进行通信时,当PSH=1时,表示尽快地用“推送”给应用程序,而不用等到缓冲区满了再向上交付。 unsigned char ack:1; //当ACK=1时,确认字段有效,在连接建立后的所有报文段都必须把ACK置为1。 unsigned char urg:1; //紧急指针,当URG=1时,表示紧急指针有效,应该尽快传送。用来处理避免TCP数据流中断 unsigned char reseverd2:2; //保留6位中的2位 #else unsigned char headerLen:4; //tcp头部长度 unsigned char reserved1:4; //保留6位中的4位首部长度 unsigned char reseverd2:2; //保留6位中的2位 unsigned char urg:1; //当URG=1时,表示紧急指针有效,应该尽快传送。 unsigned char ack:1; //当ACK=1时,确认字段有效,在连接建立后的所有报文段都必须把ACK置为1。 unsigned char psh:1; //当两个应用程序进行通信时,当PSH=1时,表示尽快地用“推送”给应用程序,而不用等到缓冲区满了再向上交付。 unsigned char rst:1; //复位,当TCP连接中出现了严重差错,必须释放连接。 unsigned char syn:1; //同步当SYN=1时,表示这是一个连接请求或连接接受报文。 unsigned char fin:1; // 用来释放一个连接。当FIN=1时表示要求释放连接。 #endif unsigned short windownSize; //16位窗口大小 unsigned short checksum; //16位TCP检验和 unsigned short urgPtr; //16位紧急指针 当URG=1时.表示紧急指针有效.应该尽快传送,不要按本来的列队次序传送 }; //TCP伪首部 struct PseudoHeader { unsigned int srcIP; //源地址 unsigned int dstIP; //目的地址 unsigned char mustBeZero;//置空,用于填充对齐 unsigned char protocol; //协议类型 unsigned short len; //TCP长度 }; //Max Segment Size最大segment长度 struct MSSOption { unsigned char kind; unsigned char length; unsigned short maxValue; }; //Selective Acknowledgment struct SACKOption { unsigned char kind; unsigned char length; }; //rtt即等于现在的时间tcp_time_stamp减去Timestamp Echo Reply struct TimestampsOption { unsigned char kind; unsigned char length; unsigned int timestamp; unsigned int timestampReply; }; struct NoOperation { unsigned char type; }; struct WindowScaleOption { unsigned char kind; unsigned char length; unsigned char shiftCount; }; #pragma pack() #endif // TESTTCP_H
testTcp.cpp
#include "testTcp.h" #include <iostream> #include <stdio.h> #include <string.h> #include <arpa/inet.h> #include <netinet/ip.h> #include <errno.h> using namespace std; int g_tcpSeqNum = 111; int g_tcpAckNum = 0; //ip数字转字符串 void ipLLToStr(long long ip_num,char* ip_str) { unsigned int iptok1 = (ip_num & 0xFF000000) >> 24; unsigned int iptok2 = (ip_num & 0x00FF0000) >> 16; unsigned int iptok3 = (ip_num & 0x0000FF00) >> 8; unsigned int iptok4 = ip_num & 0x000000FF; char ip[32]; bzero(ip,sizeof(ip)); snprintf(ip,sizeof(ip),"%d.%d.%d.%d",iptok1,iptok2,iptok3,iptok4); strcpy(ip_str,ip); } //打印ip头 void printIPHeader(IPHeader* ipHeader) { char srcIPStr[64] = "",dstIPStr[64]=""; ipLLToStr(ntohl(ipHeader->srcIP),srcIPStr); ipLLToStr(ntohl(ipHeader->dstIP),dstIPStr); int totalLen = ntohs(ipHeader->totalLen); char ipHeaderStr[256] = ""; snprintf(ipHeaderStr,sizeof(ipHeaderStr),"ip header: version:%d,tos:%d,protocol:%d,ttl:%d,srcIP:%s,dstIP:%s,totalLen:%d" ,ipHeader->version,ipHeader->tos,ipHeader->protocol,ipHeader->ttl,srcIPStr,dstIPStr,totalLen); cout << ipHeaderStr << endl; } //打印tcp头 void printTCPHeader(TCPHeader* tcpHeader) { char tcpHeaderStr[256] = ""; snprintf(tcpHeaderStr,sizeof(tcpHeaderStr),"tcp header:srcPort:%d,dstPort:%d,seqNum:%u,ackNum:%u,headerLen:%d,fin:%d,syn:%d,rst:%d" ",psh:%d,ack:%d,urg:%d,windowsSize:%d,checksum:%d,urgPtr:%d",ntohs(tcpHeader->srcPort),ntohs(tcpHeader->dstPort) ,ntohl(tcpHeader->seqNum),ntohl(tcpHeader->ackNum),tcpHeader->headerLen<<2,tcpHeader->fin,tcpHeader->syn,tcpHeader->rst ,tcpHeader->psh,tcpHeader->ack,tcpHeader->urg,ntohs(tcpHeader->windownSize),ntohs(tcpHeader->checksum),tcpHeader->urgPtr); cout << tcpHeaderStr << endl; } //构造IP头 void buildIPHeader(IPHeader* ipHeader,int totalLen,int srcIPNum,int dstIPNum) { ipHeader->headerLen = sizeof(IPHeader)>>2; ipHeader->version = IPVERSION; //服务类型 ipHeader->tos = 0; ipHeader->totalLen = htons(totalLen); ipHeader->id=htons(0); //设置flag标记为0 ipHeader->flagOffset=htons(0x02 << 13); ; //运用的协议为TCP协议 ipHeader->protocol=IPPROTO_TCP; //一个封包在网络上可以存活的时间 ipHeader->ttl=64; ipHeader->srcIP = srcIPNum; ipHeader->dstIP = dstIPNum; } //tcp和udp的校验和算法是相同的 unsigned short calChecksum(unsigned short* buffer, int size) { unsigned long cksum = 0; while(size>1) { cksum += *buffer++; size -= sizeof(unsigned short); } if(size){ cksum += *(unsigned char*)buffer; } cksum = (cksum>>16) + (cksum&0xffff); //将高16bit与低16bit相加 cksum += (cksum>>16); //将进位到高位的16bit与低16bit 再相加 return (unsigned short)(~cksum); } //构造tcp协议头 void buildTCPHeader(TCPHeader* tcpHeader,sockaddr_in* srcAddr,sockaddr_in* dstAddr,IPHeader* ipHeader,int headerLen,int seqNum,int ackNum,char syn,char ack) { tcpHeader->srcPort = srcAddr->sin_port; tcpHeader->dstPort = dstAddr->sin_port; tcpHeader->seqNum = htonl(seqNum); tcpHeader->ackNum = htonl(ackNum); tcpHeader->urg = 0; tcpHeader->ack = ack; tcpHeader->psh = 0; tcpHeader->rst = 0; tcpHeader->syn = syn; tcpHeader->fin = 0; tcpHeader->windownSize = htons(14600); tcpHeader->checksum = 0; tcpHeader->urgPtr = 0; tcpHeader->headerLen = headerLen>>2; //根据伪首部的buf计算ip头的校验和 char psdHeaderBuf[256] = ""; PseudoHeader* psdHeader = (PseudoHeader*)psdHeaderBuf; psdHeader->srcIP = ipHeader->srcIP; psdHeader->dstIP = ipHeader->dstIP; psdHeader->mustBeZero = 0; psdHeader->protocol = ipHeader->protocol; psdHeader->len = htons(sizeof(TCPHeader)); memcpy(psdHeaderBuf+sizeof(PseudoHeader),tcpHeader,sizeof(TCPHeader)); tcpHeader->checksum = calChecksum((unsigned short*)psdHeaderBuf, sizeof(PseudoHeader)+sizeof(TCPHeader)); } //发送syn int sendTcp(int sockfd,sockaddr_in* srcAddr,sockaddr_in* dstAddr,char syn,char ack,bool addMssOption,bool addSACKOption,bool addTsOption,bool addNoOption ,bool addWindowScale) { char buf[1024] = ""; int totalLen = sizeof(IPHeader) + sizeof(TCPHeader); if(addMssOption){ totalLen += sizeof(MSSOption); } if(addSACKOption){ totalLen += sizeof(SACKOption); } if(addTsOption){ totalLen += sizeof(TimestampsOption); } if(addNoOption){ totalLen += sizeof(NoOperation); } if(addWindowScale){ totalLen += sizeof(WindowScaleOption); } int pos = 0; IPHeader* ipHeader = (IPHeader*)buf; buildIPHeader(ipHeader,totalLen,srcAddr->sin_addr.s_addr,dstAddr->sin_addr.s_addr); printIPHeader(ipHeader); pos += sizeof(IPHeader); TCPHeader* tcpHeader = (TCPHeader*)(buf+pos); buildTCPHeader(tcpHeader,srcAddr,dstAddr,ipHeader,totalLen-sizeof(IPHeader),g_tcpSeqNum++,g_tcpAckNum,syn,ack); printTCPHeader(tcpHeader); pos += sizeof(TCPHeader); if(addMssOption) { MSSOption* mssOption = (MSSOption*)(buf+pos); mssOption->kind = 2;//htons(2); mssOption->length = sizeof(MSSOption);//htons(4); mssOption->maxValue = htons(1460); pos += sizeof(MSSOption); } if(addSACKOption) { SACKOption* sackOption = (SACKOption*)(buf+pos); sackOption->kind = 4; sackOption->length = sizeof(SACKOption); pos += sizeof(SACKOption); } if(addTsOption) { TimestampsOption* tsOption = (TimestampsOption*)(buf+pos); tsOption->kind = 8; tsOption->length = sizeof(TimestampsOption); tsOption->timestamp = htonl(111); tsOption->timestampReply = 0; pos += sizeof(TimestampsOption); } if(addNoOption) { NoOperation* noOption = (NoOperation*)(buf+pos); noOption->type = 1; pos += sizeof(NoOperation); } if(addWindowScale) { WindowScaleOption* windowScaleOption = (WindowScaleOption*)(buf+pos); windowScaleOption->kind = 3; windowScaleOption->length = sizeof(WindowScaleOption); windowScaleOption->shiftCount = 6; } if(sendto(sockfd,buf,totalLen,0,(struct sockaddr *)dstAddr,sizeof(*dstAddr))<0){ perror("sendto error"); } return 0; } //解析syn+ack void parseSynAck(int sockfd,sockaddr_in* dstAddr) { char recvBuf[1024] = ""; socklen_t cliLen = sizeof(dstAddr); int recvLen = recvfrom(sockfd,recvBuf,sizeof(recvBuf),0,(sockaddr*)&dstAddr,&cliLen); if(recvLen<=0) { cout << "parse syc ack fail,recvLen:" << recvLen << endl; return; } int pos = 0; IPHeader* ipHeader = (IPHeader*)recvBuf; pos += sizeof(IPHeader); printIPHeader(ipHeader); TCPHeader* tcpHeader = (TCPHeader*)(recvBuf+pos); printTCPHeader(tcpHeader); g_tcpSeqNum = ntohl(tcpHeader->ackNum); } int main() { int sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_TCP); if( sockfd < 0) { cout << strerror(errno) << endl; return -1; } char srcStr[32] = "172.16.96.52"; char dstStr[32] = "192.168.145.51"; int srcPort = 50852; int dstPort = 6699; sockaddr_in srcAddr; bzero(&srcAddr,sizeof(srcAddr)); srcAddr.sin_family=AF_INET; srcAddr.sin_addr.s_addr = inet_addr(srcStr); srcAddr.sin_port = htons(srcPort); sockaddr_in dstAddr; bzero(&dstAddr,sizeof(dstAddr)); dstAddr.sin_family=AF_INET; dstAddr.sin_addr.s_addr = inet_addr(dstStr); dstAddr.sin_port = htons(dstPort); //IPPROTO_TP说明用户自己填写IP报文 //IP_HDRINCL表示由内核来计算IP报文的头部校验和,和填充那个IP的id int on = 1; setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on)); cout << "syn:" << endl; char syn = 1,ack = 0; sendTcp(sockfd,&srcAddr,&dstAddr,syn,ack,true,true,true,true,true); cout << "syn+ack:" << endl; parseSynAck(sockfd,&dstAddr); //ack // syn = 0,ack = 1; // sendTcp(sockfd,&srcAddr,&dstAddr,syn,ack,true,true,true,true,true); return 0; } syn: ip header: version:4,tos:0,protocol:6,ttl:64,srcIP:172.16.96.52,dstIP:192.168.145.51,totalLen:60 tcp header:srcPort:50852,dstPort:6699,seqNum:111,ackNum:0,headerLen:40,fin:0,syn:1,rst:0,psh:0,ack:0,urg:0,windowsSize:14600,checksum:59258,urgPtr:0 syn+ack: ip header: version:4,tos:0,protocol:6,ttl:62,srcIP:192.168.145.51,dstIP:172.16.96.52,totalLen:60 tcp header:srcPort:6699,dstPort:50852,seqNum:3363298119,ackNum:112,headerLen:40,fin:0,syn:1,rst:0,psh:0,ack:1,urg:0,windowsSize:14480,checksum:34955,urgPtr:0 //理论上在这我们应该发送一个ack,但实际上在发完syn后,操作系统内核收到syc+ack,它检查内核里的socket, //发现没有一个socket对应于这个包,于是自动回复rst,关闭连接,所以我们无法再回复ack,因为连接已断开
发表评论
-
滑动窗口与拥塞控制
2017-09-29 14:47 762滑动窗口:用作流量控制: 1.发送端和接收端各维护一个独立的发 ... -
柔性数组
2017-09-20 09:53 510#include <iostream> #i ... -
rawsocket发送dns包
2017-09-14 15:18 618#include <stdio.h> #in ... -
rawsocket发送icmp包
2017-09-06 09:54 665#include <stdio.h> #in ... -
netfilter
2016-10-04 20:31 484http://blog.chinaunix.net/uid-2 ... -
gdb的简单使用
2016-09-19 15:18 419注意编译的时间加上-g参数 1.调试运行 gdb a.out ... -
TCP各状态的意义
2016-03-01 14:06 425各个状态的意义如下: LISTEN - 侦听来自远方TCP端 ... -
log
2015-03-30 17:42 456log.h #ifndef __LOG_H__ #def ... -
TIMEWAIT与CLOSEWAIT
2015-03-17 11:32 665http://blog.csdn.net/kobejayand ... -
TcpClient
2015-01-16 17:46 476TcpClient.h #ifndef TCPCLIENT ... -
信号量
2014-09-26 10:20 686#include <semaphore.h> ... -
共享内存
2014-09-17 10:39 603SharedMemory.h #ifndef SHARED ... -
记录锁
2014-09-11 16:32 442#include <errno.h> #in ... -
popen
2014-09-06 14:50 643#include <stdio.h> #in ... -
大小端存储
2014-09-05 09:29 608#include <stdio.h> i ... -
条件变量(cond)
2014-09-01 11:02 887#include <pthread.h> # ... -
读写锁
2014-09-01 10:33 734#include <pthread.h> # ... -
trylock
2014-09-01 10:07 673#include <pthread.h> # ... -
线程分离
2014-09-01 10:00 698http://www.cnblogs.com/mydomain ... -
线程返回值传出
2014-08-31 09:56 537#include <pthread.h> # ...
相关推荐
总结来说,基于Raw Socket的UDP数据发送和接收是一项涉及网络协议底层操作的技术,适用于需要高度定制网络包的应用。它要求开发者具备深厚的网络协议知识,以确保数据的正确传输和解析。在实际应用中,务必谨慎操作...
在本主题中,“RawSend_RawSocket基于MAC发送_sock_raw_C++_原始Socket发送_”指的是使用C++语言通过原始套接字(Raw Socket)向指定MAC地址发送以太网数据帧的过程。以下将详细介绍这一技术及其相关知识点。 1. **...
注意,如果需要发送TCP或UDP数据,还需要构造相应的传输层头部。 4. 发送数据:使用`sendto()`或`write()`函数将构造好的数据包发送到目标IP地址。 5. 接收响应:如果需要,可以创建另一个Raw Socket来接收响应...
在计算机网络编程中,"raw socket发送报文"是一个高级话题,主要涉及到网络协议栈的底层操作。Raw sockets允许程序员直接操作数据链路层(如Ethernet或PPP)的数据包,而不是通过传输层协议(如TCP或UDP)进行通信。...
本篇将重点探讨"IP包读取分析(raw socket)"这一主题,特别关注在Windows环境下如何使用raw socket进行网络通信。 首先,我们需要理解什么是raw socket。Raw socket是一种允许程序员访问网络协议栈的底层接口,它...
**rawsocket抓包侦听**是一种网络数据包捕获技术,它通过使用操作系统底层的原始套接字(raw sockets)来直接访问网络层的数据包,而不是通过应用层协议(如TCP或UDP)进行通信。这种方法使得开发者可以直接查看和...
Raw Socket允许我们直接操作网络层的数据包,而不必通过更高级的TCP或UDP协议栈。 首先,理解ICMP协议至关重要。ICMP是IP协议的一部分,主要用于在IP层传输错误和控制信息。它包括但不限于网络不可达、超时、参数...
例如,`RawSocketTest.cpp`和`RawSocket_Test.cpp`可能包含测试Raw Socket功能的代码,而`PacketStruct.h`可能定义了用于存储和解析报文结构的类或结构体。`NetCapture`系列的文件可能是项目工程文件,用于编译和...
RAW Socket是操作系统提供的一种底层网络编程接口,允许程序员直接操作网络协议栈,而不依赖于标准的TCP、UDP等协议。使用RAW Socket,开发者可以构建自定义的协议,实现更灵活的网络通信。然而,这也意味着需要...
2. 数据链路层的直接操作:通过raw socket发送的数据不会自动添加IP或TCP/UDP头部,所以需要手动构造这些头部,包括IP地址和端口号等信息。 3. 打开raw socket:在Linux下,使用`socket(AF_PACKET, SOCK_RAW, htons...
在压缩包文件名称列表中,"rawsocket"可能是源代码文件或相关资源文件的名称。实际操作时,可以解压该文件,查看源代码以了解如何在具体编程语言中实现raw socket的功能。 总结,raw sockets提供了一种直接与网络...
在本项目中,多线程用于同时处理多个Raw Socket通信任务,比如接收和发送数据可能由不同的线程负责。在Windows上,可以使用`CreateThread()`函数创建新线程,或者使用`std::thread`库(如果项目使用C++11及以上版本...
**原始套接字(Raw Socket)深度解析** 原始套接字,或称为“raw socket”,在计算机网络编程中扮演着重要角色。它允许程序员访问网络协议的底层细节,包括IP和TCP/IP协议栈的直接交互。这个大合集提供了一系列关于...
TCP RAW_SOCKET工作在OSI模型的网络层或更低层,它允许应用程序访问IP头部和TCP头部,甚至可以创建自己的IP包和TCP包。通过这种方式,开发者可以直接操控网络数据的封装和解封装,实现更灵活的网络通信。 二、使用...
【Python使用Raw Socket进行TCP SYN扫描】 在网络安全领域,端口扫描是一种常见的技术,用于检测目标主机上开放的服务。端口扫描分为多种类型,其中包括TCP SYN扫描,它是一种非侵入性的扫描方法,不会完全建立TCP...
Raw Socket的工作原理是,它允许程序发送和接收未封装在任何特定协议(如TCP或UDP头)中的IP数据包。通过这种方式,我们可以捕获网络上的原始数据包,对其进行解析和分析,从而理解网络通信的细节。 描述中提到,这...
标题中的“用RawSocket实现的Sniffer的C++Builder源程序”揭示了这是一个使用C++Builder编程环境,通过Raw Socket技术开发的网络嗅探器(Sniffer)项目。网络嗅探器是一种工具,用于捕获并分析网络上的数据包,这...
在IT领域,原始套接字(Raw Socket)是一种特殊的网络编程接口,允许程序员直接操作网络协议的底层细节,包括IP头部、TCP头部或UDP头部。它不像普通的套接字那样处理高层协议的数据封装和解封装,而是允许我们访问...