构造icmp头,并sendto的程序 (顶者有分)(200分)

  • 主题发起人 主题发起人 baiduan
  • 开始时间 开始时间
B

baiduan

Unregistered / Unconfirmed
GUEST, unregistred user!
用socket发送icmp的程序。
顶者有分,解决了另外开贴给分200;
另外问:为什么可以用udp包
穿透防火墙访问远程主机?
解决了另外开贴给分100;
 
我第一个顶
 
先来一篇
http://www.programfan.com/article/showarticle.asp?id=2289
 
看了,不是我需要的。
郁闷。。。。。。。
现在请教一个问题咋就那么难滴?
 
用原始套接字
 
//大家可以新建立一个工程,
//然后放上2 个memo,一个button
//然后把下面的代码贴上去就可以看了
//程序病状是可以接受其他程序的ping的回复
//但是自己的ping回复接受不到
//除了addrstr:='66.249.89.99';
//------------------------begin-------------------
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,winsock, StdCtrls;
const
icmp_echo_reply = 0;
icmp_echoreq = 8;
IP_RECORD_ROUTE = $7;
type
TForm1 = class(TForm)
Memo1: TMemo;
Memo2: TMemo;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
PICMP_HDR = ^ICMP_HDR;
ICMP_HDR = packed record
PType: BYTE;
Code: BYTE;
Checksum: word;
ICMPid: word;
icmpseq: word;
data:array [0..31] of char;
end;
type
icmp_data = packed record
time: dword;
dest_ip: ulong;
end;
type
Pipoptinfo = ^Tipoptinfo;
Tipoptinfo = packed record
code: byte;
len: byte;
ptr: byte;
buf: array[0..8] of dword;
end;
type
iphdr = record //IP头结构
h_lenver: byte; //4位首部长度+4位IP版本号
tos: byte; //8位服务类型TOS
total_len: word; //16位总长度(字节)
ident: word; //16位标识
frag_and_flags: word; //3位标志位
ttl: byte; //8位生存时间 TTL
proto: byte; //8位协议 (TCP, UDP 或其他)
checksum: word; //16位IP首部校验和
sourceIP: Longword; //32位源IP地址
destIP: Longword; //32位目的IP地址
end;
function recvf(addrstr: string): integer; stdcall;
function cksum(addr: PWord; len: integer): Cardinal;
var
Form1: TForm1;

implementation
{$R *.dfm}
var
hs: Thandle;
isgo:integer;
//csock: Tsocket;
function cksum(addr: PWord; len: integer): Cardinal;
var
nleft: integer;
w: PWord;
answer: cardinal;
sum: integer;
begin
nleft := len;
w := addr;
sum := 0;

while (nleft > 1) do
begin
sum := sum + w^;
Integer(w) := Integer(w) + SizeOf(Word);
nleft := nleft - 2;
end;

if(nleft = 1) then
begin
sum := sum + Word(w^);
end;

sum := sum shr 16 + sum and $ffff;
sum := sum + sum shr 16;
answer := not sum;
result := answer;
end;

function recvf(addrstr: string): integer; stdcall;
var
ms: Tsocket;
getbuf: array[0..1023] of byte;
sendbuf:array of byte;
len, flags: integer;
wd: wsadata;
h1, h2: integer;
sa_src: TSockAddr;
timeout: timeval;
csock: Tsocket;
ih1: icmp_hdr; //icmp头
idata: icmp_data;
sa_dest: sockaddr_in;
dsize: word;
seq_no: byte;
ipopt: tipoptinfo;
iph: iphdr; //ip头
rd: TFDSet;
pd:Tinaddr;
timeo:integer;
begin
addrstr:='66.249.89.99';
//addrstr:='127.0.0.1';
while 1=1 do
begin
wsastartup(2, wd);
csock := socket(af_inet, sock_raw, ipproto_icmp);
timeo:=10;
h1:= setsockopt(csock, SOL_SOCKET, SO_RCVTIMEO,
@timeout, sizeof(timeout));
if h1=SOCKET_ERROR then form1.Memo1.Lines.Add('setsockopt error')
else form1.Memo1.Lines.Add('setsockopt success');
zeromemory(@ih1,sizeof(ih1));
ih1.PType :=byte(icmp_echoreq);
ih1.Code := byte(0);
ih1.Checksum := 0;
seq_no := 0;
ih1.icmpseq := word(seq_no);
ih1.ICMPid :=word(GetCurrentProcessId);
ih1.Checksum:=0;
ih1.Checksum:=word(cksum(@ih1,sizeof(ih1)));
fillchar(ih1.data,sizeof(ih1.data),'e');
idata.time := gettickcount;
idata.dest_ip :=inet_addr(pchar(addrstr));
sa_dest.sin_family := AF_INET;
sa_dest.sin_port := htons(0);
sa_dest.sin_addr.S_addr:=inet_addr(pchar(addrstr));
setlength(sendbuf,sizeof(ih1)+32);
form1.Memo1.Lines.Add('ih1长度= '+inttostr(sizeof(ih1))+'idata的长度= '+inttostr(sizeof(idata)));
zeromemory(@sa_src,sizeof(sa_src));
len :=sizeof(sa_src);
h1:=sendto(csock,ih1,sizeof(ih1),0,sa_dest, sizeof(sa_dest));
h2 := recvfrom(csock, getbuf,sizeof(getbuf), 0, sa_src, len);
form1.Memo1.Lines.Add(inttostr(h1)+' '+ inttostr(h2));
if h2<=0 then
begin
sleep(500);
continue;
end;
//解析
dsize := sizeof(iph);
zeromemory(@ih1, dsize);
copymemory(@iph, @getbuf[0], dsize);
dsize := sizeof(ih1);
copymemory(@ih1, @getbuf[20], dsize);
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[28]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[29]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[30]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[31]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[32]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[33]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[34]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[35]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[36]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[37]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[38]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[39]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[56]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[57]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[58]));
form1.Memo2.Lines.Add('datalen= '+chr(getbuf[59]));
form1.Memo2.Lines.Add('tos=' + inttostr(iph.tos));
form1.Memo2.Lines.Add('total_len=' + inttostr(iph.total_len));
form1.Memo2.Lines.Add(inttostr(iph.ident));
form1.Memo2.Lines.Add('frag_and_flags='+inttostr(iph.frag_and_flags));
form1.Memo2.Lines.Add('ttl='+inttostr(iph.ttl));
form1.Memo2.Lines.Add('proto='+inttostr(iph.proto));
form1.Memo2.Lines.Add('checksum='+inttostr(iph.checksum));
pd.S_addr:=iph.sourceIP;
form1.Memo2.Lines.Add('sourceip=' + inttostr(iph.sourceIP));
form1.Memo2.Lines.Add('sourceip= '+inet_ntoa(pd));
form1.Memo2.Lines.Add('destip=' + inttostr(iph.destIP));
pd.S_addr:=iph.destIP;
form1.Memo2.Lines.Add('destip= '+inet_ntoa(pd));
form1.Memo2.Lines.Add('icmp type= '+inttostr(ih1.PType));
form1.Memo2.Lines.Add('icmp code= '+inttostr(ih1.Code));
form1.Memo2.Lines.Add('icmp checksum= '+inttostr(ih1.Checksum));
form1.Memo2.Lines.Add('icmp impid= '+inttostr(ih1.ICMPid));
form1.Memo2.Lines.Add('processid= '+inttostr(GetCurrentProcessId));
form1.Memo2.Lines.Add('icmp icmpseq= '+inttostr(ih1.icmpseq));
form1.Memo2.Lines.Add('sa_src.addr='+inet_ntoa(sa_src.sin_addr));
form1.Memo2.Lines.Add('sa_src.port='+inttostr(sa_src.sin_port));
form1.Memo2.Lines.Add('sa_src.family(af_inet)='+inttostr(sa_src.sa_family));
form1.Memo2.Lines.Add('sa_src.data='+sa_src.sa_data);
form1.Memo2.Lines.Add('sa_src.zero='+sa_src.sin_zero);
form1.Memo2.Lines.Add('--------------------------------------------');
sleep(500);
//end;
wsacleanup;
closesocket(csock);
result := 1;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ic: dword;
msg: string;
begin
ic := 2;
msg := '192.168.0.112'; //202.168.9.16
// recvf('202.168.9.16');

if hs<=0 then
begin
hs:=createthread(nil,0,@recvf,@msg,0,ic);
exit;
end;
if hs>0 then
begin
if isgo=0 then
begin
SuspendThread(hs);
isgo:=1;
exit;
end
else
begin
resumethread(hs);
isgo:=0;
exit;
end;
end;
end;

end.
//--------------------------------end----------------------
 
顶一下,学习ing
 
这个有什么问题吗? 细心一点就可以了,还有注意一下按网络顺序。
 
谁知道啊,我是新手,帮帮忙啦。。。。。。。。。。
 
每天都要自己顶一下。。。。。郁闷
 
一个一个来
第一个问题不会;
第2个问题是UDP是不建立连接的,也就是说,包与包之间你无法自动判断是否来自同一个地方,只能根据IP地址来确定。而socket是先建立连接再通信的,socket套接字已经把网络连接部分都集成在里面了,通俗地讲,就是你只要对一个socket操作,所有相互之间的通信信息都可以很容易地操作,不需要考虑是谁发过来的,怎么发回去
第3个问题:如果用两台都没有独立IP的计算机,不能实现的,这个时候只能做服务器中转,不然现在也不会有那么多的网络中转服务器了。如果有一台是有独立IP的,那么socket的服务器那台就应该有独立IP,这个时候就可以相互通信,第2个问题中,UDP就没办法实现信息返回了,因为CLIENT没有IP,无法发数据,而socket就可以,因为有连接在嘛。现在的路由器可以指定本地局域网内内某台电脑具有INTERNET独立IP,这个主要看网络运营商,租个IP也是要钱的^_^
 
帮顶!

╭=========================================╮

80G海量源代码,控件,书籍全免费狂下不停!

http://www.source520.com

个人网站站长开发推广同盟,让所有人知道你的世界!

http://www.source520.com/search/search.asp

╰=========================================╯
 
真tmd不容易,搞定,揭帖
ih1.Checksum:=0;
ih1.Checksum:=word(cksum(@ih1,sizeof(ih1)));
fillchar(ih1.data,sizeof(ih1.data),'e');
//改为
ih1.Checksum:=0;
fillchar(ih1.data,sizeof(ih1.data),'e');
ih1.Checksum:=word(cksum(@ih1,sizeof(ih1)));
//就差这么一点。
 
多人接受答案了。
 
后退
顶部