如何用rawsocket接收tcp数据包

lekang 2007-06-25 12:05:34
我是个初学者,对网络编程比较感兴趣,我想用c#rawsocket方式监视进出网卡的tcp数据包,想了解tcp包里面的内容,请各位高手老师给个实现的思路和实现的方法。
...全文
604 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
lekang 2007-07-02
  • 打赏
  • 举报
回复
waiting............
lekang 2007-07-02
  • 打赏
  • 举报
回复
怎么能接收本机发出的数据包啊?
lekang 2007-07-02
  • 打赏
  • 举报
回复
对不起各位,这几天没有上网。
上面的例子怎么看不到本机发出去的数据包啊
lekang 2007-06-25
  • 打赏
  • 举报
回复
waiting.......
给个思路吧!
Red_angelX 2007-06-25
  • 打赏
  • 举报
回复
public void Run()
{
IAsyncResult ar = socket.BeginReceive(receive_buf_bytes, 0, len_receive_buf, SocketFlags.None, new AsyncCallback(CallReceive), this);
}

private void CallReceive(IAsyncResult ar)
{
int received_bytes;
received_bytes = socket.EndReceive(ar);
Receive(receive_buf_bytes, received_bytes);
if (KeepRunning) Run();
}

public class PacketArrivedEventArgs : EventArgs
{
/*******************************************
* ReceiveBuffer 所有的包
* MessageBuffer 去除IPHeader后的包
* MessageData 去除UserHeader后的包
* UserHeader s_port d_port length checksum
*******************************************/
public PacketArrivedEventArgs()
{
this.protocol = "";
this.destination_port = "";
this.origination_port = "";
this.destination_address = "";
this.origination_address = "";
this.ip_version = "";

this.total_packet_length =0;
this.message_length =0;
this.header_length =0;

this.receive_buf_bytes=new byte[len_receive_buf];
this.ip_header_bytes=new byte[len_receive_buf];
//this.message_bytes=new byte[len_receive_buf];
}
//是否为接收包
public bool IsSend
{
get { return OriginationAddress.Equals(localip); }
}
public string Protocol
{
get {return protocol;}
set {protocol=value;}
}
public string DestinationPort
{
get {return destination_port;}
set {destination_port=value;}
}
public string OriginationPort
{
get {return origination_port;}
set {origination_port=value;}
}
public string DestinationAddress
{
get {return destination_address;}
set {destination_address=value;}
}
public string OriginationAddress
{
get {return origination_address;}
set {origination_address=value;}
}
public string IPVersion
{
get {return ip_version;}
set {ip_version=value;}
}
public uint PacketLength
{
get {return total_packet_length;}
set {total_packet_length=value;}
}
public uint MessageLength
{
get {return message_length;}
set {message_length=value;}
}
public uint HeaderLength
{
get {return header_length;}
set {header_length=value;}
}
public byte [] ReceiveBuffer
{
get {return receive_buf_bytes;}
set {receive_buf_bytes=value;}
}
public byte [] IPHeaderBuffer
{
get {return ip_header_bytes;}
set {ip_header_bytes=value;}
}
public byte [] MessageBuffer
{
get {return message_bytes;}
set {message_bytes=value;}
}
/// <summary>
/// 数据包正文
/// </summary>
public byte[] MessageData
{
get { return message_datas; }
set { message_datas = value; }
}

private string protocol;
private string destination_port;
private string origination_port;
private string destination_address;
private string origination_address;
private string ip_version;
private uint total_packet_length;
private uint message_length;
private uint header_length;
private byte []receive_buf_bytes = null;
private byte []ip_header_bytes = null;
private byte []message_bytes = null;
private byte []message_datas = null;
}

public delegate void PacketArrivedEventHandler(
Object sender, PacketArrivedEventArgs args);

public event PacketArrivedEventHandler PacketArrival;

protected virtual void OnPacketArrival(PacketArrivedEventArgs e)
{
if (PacketArrival != null)
{
PacketArrival(this, e);
}
}
}
}
Red_angelX 2007-06-25
  • 打赏
  • 举报
回复
//This file contains the RawSocket class. The goal of this class is to have a generic packet
//sniffing kind of class that fires events when an incoming IP packet is received. The event
//gives the user access to everything contained in the IP packet and hopefully makes creating
//your own packet sniffer quite easy. The event args returned with the event give the user of
//the class access to things like the from and to IP address, ports, protocol, etc. and even the
//contents of the message in the form of a byte array.

/******************************************
* Fixed Some Problem
* Modify By Red_angelX
* Build 2007.4.24
*****************************************/


namespace QQFamilyAnalytics
{
using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Windows.Forms;

[StructLayout(LayoutKind.Explicit)]
public struct IPHeader
{
[FieldOffset(0)] public byte ip_verlen; //IP version and IP Header length Combined
[FieldOffset(1)] public byte ip_tos; //Type of Service
[FieldOffset(2)] public ushort ip_totallength; //Total Packet Length
[FieldOffset(4)] public ushort ip_id; //Unique ID
[FieldOffset(6)] public ushort ip_offset; //Flags and Offset
[FieldOffset(8)] public byte ip_ttl; //Time To Live
[FieldOffset(9)] public byte ip_protocol; //Protocol (TCP, UDP, ICMP, Etc.)
[FieldOffset(10)] public ushort ip_checksum; //IP Header Checksum
[FieldOffset(12)] public uint ip_srcaddr; //Source IP Address
[FieldOffset(16)] public uint ip_destaddr; //Destination IP Address
}

public class RawSocket
{
private bool error_occurred;
public bool KeepRunning;
private static int len_receive_buf;
byte [] receive_buf_bytes;
private Socket socket = null;
private static string localip;

public RawSocket()
{
error_occurred=false;
len_receive_buf = 4096;
receive_buf_bytes = new byte[len_receive_buf];
}

public void CreateAndBindSocket(string IP)
{
localip = IP;
socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
socket.Blocking = false;
socket.Bind(new IPEndPoint(IPAddress.Parse(IP), 0));

if (SetSocketOption()==false) error_occurred=true;
}

public void Shutdown()
{
if(socket != null)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}

private bool SetSocketOption()
{
bool ret_value = true;
try
{
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, 1);

byte []IN = new byte[4]{1, 0, 0, 0};
byte []OUT = new byte[4];
int SIO_RCVALL = unchecked((int)0x98000001);
int ret_code = socket.IOControl(SIO_RCVALL, IN, OUT);
ret_code = OUT[0] + OUT[1] + OUT[2] + OUT[3];
if(ret_code != 0) ret_value = false;
}
catch(SocketException)
{
ret_value = false;
}
return ret_value;
}

public bool ErrorOccurred
{
get
{
return error_occurred;
}
}

unsafe private void Receive(byte [] buf, int len)
{
byte temp_protocol=0;
uint temp_version=0;
uint temp_ip_srcaddr=0;
uint temp_ip_destaddr=0;
short temp_srcport=0;
short temp_dstport=0;
IPAddress temp_ip;

PacketArrivedEventArgs e=new PacketArrivedEventArgs();

fixed(byte *fixed_buf = buf)
{
IPHeader * head = (IPHeader *) fixed_buf;
e.HeaderLength=(uint)(head->ip_verlen & 0x0F) << 2;

temp_protocol = head->ip_protocol;
switch(temp_protocol)
{
case 1: e.Protocol="ICMP"; break;
case 2: e.Protocol="IGMP"; break;
case 6: e.Protocol="TCP"; break;
case 17: e.Protocol="UDP"; break;
default: e.Protocol= "UNKNOWN"; break;
}

temp_version =(uint)(head->ip_verlen & 0xF0) >> 4;
e.IPVersion = temp_version.ToString();

temp_ip_srcaddr = head->ip_srcaddr;
temp_ip_destaddr = head->ip_destaddr;
temp_ip = new IPAddress(temp_ip_srcaddr);
e.OriginationAddress =temp_ip.ToString();
temp_ip = new IPAddress(temp_ip_destaddr);
e.DestinationAddress = temp_ip.ToString();

temp_srcport = *(short *)&fixed_buf[e.HeaderLength];
temp_dstport = *(short *)&fixed_buf[e.HeaderLength+2];
e.OriginationPort=IPAddress.NetworkToHostOrder(temp_srcport).ToString();
e.DestinationPort=IPAddress.NetworkToHostOrder(temp_dstport).ToString();

e.PacketLength =(uint)len;
e.MessageLength =(uint)len - e.HeaderLength;
//这里确定长度
e.MessageBuffer = new byte[e.MessageLength];
e.MessageData = new byte[e.MessageLength - 8];

e.ReceiveBuffer=buf;
Array.Copy(buf,0,e.IPHeaderBuffer,0,(int)e.HeaderLength);
Array.Copy(buf,(int)e.HeaderLength,e.MessageBuffer,0,(int)e.MessageLength);
Array.Copy(e.MessageBuffer, 8, e.MessageData, 0, e.MessageData.Length);
}

OnPacketArrival(e);
}
RedGoldFish 2007-06-25
  • 打赏
  • 举报
回复
tcp数据包应该有头的,也就是说一个包的开始几个Byte应该把它所在的这个包的大小和起始终了都描述清楚. 如果没有这个头,包之间就很难分开了.

头的定义最简单的方法是: 最开始两个Byte定义为包开始的特征字,比如00,然后规定若干位,比如4表示整个包的长度.

通常的手法是把每次得到的byte[] 放到加到一个缓存里,比如一个List<byte>, 然后靠每个包的头把各个包拆出来.

cellblue 2007-06-25
  • 打赏
  • 举报
回复
使用嗅探器
lekang 2007-06-25
  • 打赏
  • 举报
回复
我知道接收ip数据包这样设置socket,
socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, 1);
接收icmp数据包用socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);然后用socket.recevefrom()方法接收.
不知道tcp数据包怎么用rawsocket接收啊.

实验三 发送TCP数据包 实验目的: 设计一个发送TCP数据包的程序,并根据本设计说明TCP数据包的结构以及TCP协议与 IP协议的关系,使大家对TCP协议的工作原理有更深入的认识。 实验要求: 本程序的功能是填充一个TCP数据包,并发送给目的主机。 以命令行形式运行:SendTCP source_ip source_port dest_ip dest_port 其中SendTCP为程序名;source_ip为源IP地址; source_port为源端口; dest_ip为目的IP地址; dest_port为目的端口。 其他的TCP头部参数自行设定。 数据字段为"This is my homework of network!". 成功发送后在屏幕上输出"send OK"。 课程设计分析: 使用原始套接字 定义IP头部、TCP头部和伪头部的数据结构 填充数据包 发送数据包 设计思想: 本课程设计的目标是发送一个TCP数据包,可以利用原始套接字来完成这个工作。整个程 序由初始化原始套接字和发送TCP数据包两个部分组成。 创建一个原始套接字,并设置IP头选项 SOCKET sock; sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP); 或者: sock=WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED); 设置SOCK_RAW标志,表示我们声明的是一个原始套接字类型。 为使用发送接收超时设置,必须将标志位置位置为WSA_FLAG_OVERLAPPED。在本课程设计 中,发送TCP包时隐藏了自己的IP地址,因此我们要自己填充IP头,设置IP头操作选项。 其中flag设置为ture,并设定 IP_HDRINCL 选项,表明自己来构造IP头。注意,如果设置IP_HDRINCL 选项,那么必须具有 administrator权限,要不就必须修改注册表: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Afd\Parameter\ 修改键:DisableRawSecurity(类型为DWORD),把值修改为 1。如果没有,就添加。 BOOL Flag=TRUE; setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&Flag, sizeof(Flag)); int timeout=1000; setsockopt(sock, SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout, sizeof(timeout)); 在这里我们使用基本套接字SOL_SOCKET,设置SO_SNDTIMEO表示使用发送超时设置,超时 时间设置为1000ms。 构造IP头和TCP头 这里, IP头和TCP头以及TCP伪部的构造请参考下面它们的数据结构。 计算校验和的子函数 在填充数据包的过程中,需要调用计算校验和的函数checksum两次,分别用于校验IP头 和TCP头部(加上伪头部),其实现代码如下: USHORT checksum(USHORT *buffer, int size) { unsigned long cksum=0; while(size >1) { cksum+=*buffer++; size -=sizeof(USHORT); } if(size ) { cksum += *(UCHAR*)buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum); } 程序流程图: 源程序代码: #include #include #include tcpip.h> #include #include #include #include #include #pragma comment(lib,"ws2_32.lib") #define IPVER 4 //IP协议预定 #define MAX_BUFF_LEN 65500 //发送缓冲区最大值 typedef struct ip_hdr //定义IP首部 { UCHAR h_verlen; //4位首部长度,4位IP版本号 UCHAR tos; //8位服务类型TOS USHORT total_len; //16位总长度(字节) USHORT ident; //16
本文章将介绍如何使用RawSocket(原始套接字)开发网络嗅探器: 首先我们得了解什么是套接字,这个我就不多说,自己百度,百度百科比我说的好。 那么什么又是原始套接字呢,常用的套接字分为 SOCK_STREAM(流套接字) 用于TCPXY通讯。 SOCK_DGRAM(数据报套接字) 同于UDPXY通讯。 那么原始呢,他则是和名字一样原始套接字;举例:要想用流套接字进行一次TCP的发包,那么直接连接上对方服务器然后用Send就可以发送指定的内容,但其实发送的数据并不止你的那些内容,有一些东西是流套接字会给你自动补上的。TCP是属于IPXY的一个子XY,那么要发送一个TCP数据包就得加上(以太网XY报头这个先不提),IPXY的报头,和TCPXY报头,这些东西流套接字都会帮你处理,而原始套接字则不会(当然也可以设置让原始套接字构造IP报头)。原始套接字他有更多的用途,但相对来说也比流套接字或数据报套接字麻烦。 原始套接字还可以设置成允许接收本地所有的套接字数据。那么我们就利用这个功能来做嗅探器! 首先:1.使用  WSAStartup (合并短整数 (2, 2), WSADATA)  来初始化Winsocket服务 其参数有2个  第一个 (短整数型/双字节型):wVersionRequired  这个参数表明使用的winsock版本号,高位指定修订版本号,低位指定主版本号。第二个参数 WSADATA类型 用于接收Winsocket细节东西,咱不用管它。 //下面就不说那么详细了,源码里面全是注释,自己看。 2.然后使用socket (#AF_INET, #SOCK_RAW, #IPPROTO_IP)  来创建一个套接字   第一个参数应该是表明Internet地址格式反正只能固定这个,仅仅支持这个  参数2:表明要创建的是一个原始套接字,参数3:指定IPXY  IPXY包括其子XY TCP UDP 等。成功返回套接字句柄 3.  bind (s, addr, sizeof (addr))  将套接字绑定至指定网卡,参数1=套接字句柄    参数2为一个addr结构的值,该值表明要绑定的网卡IP及端口号 4.  ioctlsocket (Socket, 2550136833, 1) 将套接字的模式改变为允许接收所有数据 顺利完成上面的操作后咱就可以用Recv来接收数据包了,只要不断的调用Recv就OK。
Android Camera开发入门:目录 第一篇: 前景  一、Android Camera开发前景;      1)camera相关应用的领域      2)相关岗位介绍;      3)市场招聘介绍;      4)发展前景介绍;  二、学习这门课的重要性;      1)适合的人群;      2)熟悉和了解Android Camera 应用开发流程的重要性 第二篇: 开发环境安装  一、jdk、sdk的配置;  二、android studio的安装介绍;  三、adb命令的使用; 第三篇: Camera 常用api和最新框架介绍  一、android camera api介绍      1)camera1、camera2 区别;      2)camera 1、camera2 常用api介绍;      3)android camerax;  二、android camera最新框架介绍 第四篇:Camera api1实现预览、拍照、录像功能  一、预览  二、拍照  三、录像  四、获取实时预览流 第五篇: Camera2相机 打开功能实现第六篇: Camera2相机 预览功能实现  1)surfaceview、textureview 第七篇: Camera2相机 拍照功能实现 1)单拍; 第八篇:Camera2相机 录像功能实现1)正常录像 第九篇:Camera2预览方向、拍照方向设置     1) 预览变形问题如何处理? 第十篇:YUV流处理  1)如何获取实时预览流?  2)  思考:双码流方案如何实现?一边本地录像,一边后台推流 第十一篇:dumpsys media.camera 第十二篇:Camera2 Zoom变焦第十三篇:人脸识别(android 原生 & 三方人脸识别算法)第十四篇:Uvc UsbCamera第十五篇:Android Camera2拍摄RAW图第十六篇: Android Camera2同时打开前后摄 并 录像第十七篇: Android Camera2 视频慢动作  附:1)提供android开发相关资源      软件工具、Android相关学习书籍、学习相关网站博客等链接2)提供课程讲解中设计到的App 源码    * Camera API1使用源码    * Camera API2使用源码    * 调用三方算法人脸识别源码    *  录像慢动作源码    * Uvc UsbCamera相关源码3)课件
《计算机网络》课程设计 题 目 数据包发送和接受程序的实现 学 院 计算机学院 2012年12月21日 数据包发送和接受程序的实现 一、设计题目与要求 1.设计题目 发送TCP数据包 2.设计要求 本设计的功能是填充一个TCP数据包,并发送给目的主机。 1)以命令行形式运行:SendTCP source_ip source_port dest_ip dest_port,其中SendTCP是程序名,source_ip为源端IP地址,source_port为源端口号 ,dest_ip为目的地址,dest_port为目的端口号。 2)其他的TCP头部参数请自行设定。 3)数据字段为"This is my homework of network,I am happy!"。 4)成功发送后在屏幕上输出"send OK"。 三、详细设计 本课程设计的目标是发送一个TCP数据包,可以利用原始套接字来完成这个工作。整 个程序由初始化原始套接字和发送TCP数据包两个部分组成。 当应用进程需要通过TCP发送时,它就将此应用层报文传送给执行TCP协议的传输实体 。TCP传输实体将用户数据加上TCP报头,形成TCP数据包,在TCP数据包上增加IP头部, 形成IP包。如图- 1显示的是TCP数据包和IP包得关系。TCP协议的数据传输单位称为报文段,其格式如图- 2所示。报文段报头的长度是20B~60B,选项部分长度最多为40B。TCP报文段主要包括以下 字段。 端口号:端口号字段包括源端口号和目的端口号。每个端口号的长度是16位,分别表 示发送该TCP包的应用进程的端口号和接收TCP包的应用进程的端口号。 图-1 TCP数据包加上IP报头形成IP包 序号:长度为32位。由于TCP协议是面向数据流的,它所传送的报文段可以视为连续 的数据流,因此需要给每一字节编号。序号字段的"序号"指的是本报文段数据的第一个 字节的序号。 确认号:该字段的长度为32位,它表示接收端希望接收下一个TCP包的第一个字节的 序号。 报文长度:该字段长度为4位。TCP报文长度是以4B为一个单元来计算的,实际上报文 长度在20B~60B之间。因此这个字段的值在5~15之间。 图-2 TCP数据包头部的格式 保留:长度为6位,留做今后使用,目前全部置0. 控制:这个字段定义了6种不同的标志,每一个标志占一位,在同一时间可以设置一 位或多位。URG位为1时,表明应尽快把数据传送给应用程序,否则表明允许数据在缓存 中存放一段时间。RST位为1时,表明要强制切断连接。SYN位为1时,表明有确立连接的 请求,这时,把序号字段的初始值作为序号字段的值,以便开始通信。FIN位为1时,表 明发送放已经没有数据发送了。 窗口大小:长度为16位,指向必须紧急处理的数据的位置,因此最多能够传送的数据 为65535B。 紧急指针:该字段长度为16,指向必需紧急处理的位置,只有当标志URG=1时紧急指 针才生效。从TCP报头后面的报文数据开始,到紧急指针所指出长度的数据,就是必须紧 急处理的数据。 选项: 该字段可以多达40B,包括单字节选项和多字节选项。 校验和:该字段长度为16位,校验和的校验范围包括伪头部,TCP报头以及应用层来 的数据。其计算方法与IP协议头部校验和的计算方法一样。伪头部为12B,它本身并不是 TCP数据包的真头部,只是在计算校验和时,临时和TCP数据包连接在一起。伪头部的格 式如图-3所示 0 8 16 24 31 "源IP地址 " "目的IP地址 " "00000000 "协议号(6) "TCP长度 " 创建一个原始套接字,并设置IP头选项 SOCKET sock; sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP); 或者: sock=WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED); 这里,设置了SOCK_RAW标志,表示我们声明的是一个原始套接字类型。 为使用发送接收超时设置,必须将标志位置位置为WSA_FLAG_OVERLAPPED。在本课程设计 中,发送TCP包时隐藏了自己的IP地址,因此我们要自己填充IP头,设置IP头操作选项。 其中flag设置为ture,并设定 IP_HDRINCL 选项,表明自己来构造IP头。 setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&Flag, sizeof(Flag)); int timeout=1000; setsockopt(sock, SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout, sizeof(timeout)); 在这里我们

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧