为什么我用RawSocket自定义IP包却总是发送不出去?
我想往局域网内的另一台电脑发送一个自定义的IP包。
同样的程序,用C写了一份,又用Delphi写了一份,为什么Delphi发不出去,而用VC写的却没有问题?
每次SendTo返回,都是SOCKET_ERROR。我检查过所生成的包,没有问题,就是缓冲中的内容无法通过SendTo发送出去。
我的环境是WIN2000,Delphi7。
////////////Delphi版的///////////////////////////
uses WinSock,IdWinSock2 使用了这2个库
///////////////////////////////////////////////
procedure TForm1.Button1Click(Sender: TObject);
var
iErrorCode:integer;
wsd:TWSADATA ;
s:TSocket;
ip_header:IPHeader;
tcp_header:_TCPHeader;
psd_header:_PSD_HEADER;
remote:sockaddr_in;
ptr:PByte;
bOpt:integer;
iTotalSize:WORD;
iTCPSize:WORD;
sendBuf:pByte;
srcPort,destPort:WORD;
iAck:Cardinal;
begin
if WSAStartup(MAKEWORD(2,2),wsd)=0 then
begin
s:=socket(AF_INET, SOCK_RAW, IPPROTO_IP);
if s<>INVALID_SOCKET then
begin
bOpt:=1;
iErrorCode:=setsockopt(s,IPPROTO_IP,IP_HDRINCL,@bOpt,sizeof(bOpt));
if iErrorCode<>SOCKET_ERROR then
begin
iTotalSize:=44;
iTCPSize:=24;
GetMem(sendBuf,iTotalSize);
ip_header.h_lenver:=(4 shl 4 or sizeof(ip_header) div sizeof(Cardinal));
ip_header.total_len:=htons(iTotalSize);
ip_header.tos:=0;
ip_header.ident:=htons(17393);
ip_header.frag_and_flags:=0;
ip_header.ttl:=57;
ip_header.proto:=IPPROTO_TCP;
ip_header.checksum:=0;
ip_header.sourceIP:=inet_addr('192.168.1.2');
ip_header.destIP:=inet_addr('192.168.1.3');
ip_header.checksum:=checksum(pWord(@ip_header),20);
//////////////////////////////////////////////////////////////
srcPort:=80;
DestPort:=1300;
iAck:=132100121;
tcp_header.th_sport:=htons(srcPort);
tcp_header.th_dport:=htons(destPort);
tcp_header.th_seq:=htonl($581A784D);
tcp_header.th_ack:=htonl(iAck+1);
tcp_header.th_lenres:=(iTCPSize div sizeof(Cardinal) shl 4 or 0);
tcp_header.th_flag:=$12;
tcp_header.th_win:=htons(65535);
tcp_header.th_urp:=0;
tcp_header.th_sum:=0;
///////////////////////////////////////////////////
psd_header.saddr:=ip_header.sourceIP;
psd_header.daddr:=ip_header.destIP;
psd_header.mbz:=0;
psd_header.ptcl:=IPPROTO_TCP;
psd_header.tcpl:=htons(iTCPSize);
ZeroMemory(sendBuf,iTotalSize);
///////////////////////////////////////////////////
CopyMemory(sendBuf,@psd_header,sizeof(psd_header));
ptr:=sendBuf;
inc(ptr,sizeof(psd_header));
CopyMemory(ptr,@tcp_header,sizeof(tcp_header));
inc(ptr,sizeof(tcp_header));
ptr^:=$02;
inc(ptr);
ptr^:=$04;
inc(ptr);
ptr^:=$05;
inc(ptr);
ptr^:=$b4;
tcp_header.th_sum:=checksum(pWord(sendBuf),sizeof(psd_header)+24);
ZeroMemory(sendBuf,iTotalSize);
////////////////////////////////////////////////////
CopyMemory(sendBuf,@ip_header,sizeof(ip_header));
ptr:=sendBuf;
inc(ptr,sizeof(ip_header));
CopyMemory(ptr,@tcp_header,sizeof(tcp_header));
ptr:=sendBuf;
inc(ptr,sizeof(ip_header)+sizeof(tcp_header));
ptr^:=$02;
inc(ptr);
ptr^:=$04;
inc(ptr);
ptr^:=$05;
inc(ptr);
ptr^:=$b4;
remote.sin_family:= AF_INET;
remote.sin_port:= htons(destPort);
remote.sin_addr.s_addr:= inet_addr('192.168.1.3');
iErrorCode:=sendto(s,sendBuf,iTotalSize,0,@remote,sizeof(remote));//就是执行到这
//返回为SOCKET_ERROR
if iErrorCode<>SOCKET_ERROR then
begin
iTotalSize:=40;
iTCPSize:=20;
CloseSocket(s);
FreeMem(sendBuf);
end;
end;
end;
end;
end;
//////////////////////////////////////////////////////////
////////////VC++版//////////////////////////////////////
#include <winsock2.h>
#include <ws2tcpip.h>
///////////////////////////////////////////////////////
void CTest1Dlg::sendTCP_SYNACK(char *szSrcIP, char *szDestIP, unsigned short srcPort, unsigned short destPort, unsigned int iAck)
{
int iErrorCode;
WSADATA wsd;
SOCKET s;
IP_HEADER ip_header;
TCP_HEADER tcp_header;
PSD_HEADER psd_header;
struct sockaddr_in remote;
char * ptr=NULL;
//创建socket
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
return;
s=socket(AF_INET, SOCK_RAW, IPPROTO_IP);
if (s==INVALID_SOCKET)
return;
BOOL bOpt = TRUE;
iErrorCode = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt));
if (iErrorCode==SOCKET_ERROR)
{
closesocket(s);
return;
}
//---end-
//伪装连接
unsigned short iTotalSize=44;
unsigned short iTCPSize=24;
char *sendBuf=new char[iTotalSize];
ip_header.h_lenver=(4<<4 | sizeof(ip_header)/sizeof(unsigned long));
//高四位版本号,低四位首部长度
ip_header.total_len=htons(iTotalSize); //16位总长度
ip_header.tos=0;
ip_header.ident=htons(17393);
ip_header.frag_and_flags=0;
ip_header.ttl=57;
ip_header.proto=IPPROTO_TCP;
ip_header.checksum=0; //16位校验和
ip_header.sourceIP=inet_addr(szSrcIP); //32位远地址·
ip_header.destIP=inet_addr(szDestIP); //32位目的地址·
ip_header.checksum=checksum((USHORT *)&ip_header,20);
//填充TCP首部
tcp_header.th_sport=htons(srcPort); //源端口
tcp_header.th_dport=htons(destPort); //目的端口
tcp_header.th_seq=htonl(0x581A784D); //SYN序列号
tcp_header.th_ack=htonl(iAck+1); //应答序号
tcp_header.th_lenres=(iTCPSize/sizeof(unsigned long)<<4|0); //TCP长度和保留位
tcp_header.th_flag=0x12; //SYN 标志
tcp_header.th_win=htons(65535); //窗口大小
tcp_header.th_urp=0; //紧急指针
tcp_header.th_sum=0; //校验和
//填充TCP伪首部(只用于生成校验和)
psd_header.saddr=ip_header.sourceIP;
psd_header.daddr=ip_header.destIP;
psd_header.mbz=0;
psd_header.ptcl=IPPROTO_TCP;
psd_header.tcpl=htons(iTCPSize);
ZeroMemory(sendBuf,iTotalSize);
//计算tcp校验和,包含伪TCP header
memcpy(sendBuf,&psd_header,sizeof(psd_header));
ptr=sendBuf+sizeof(psd_header);
memcpy(ptr,&tcp_header,sizeof(tcp_header));
ptr=sendBuf+sizeof(psd_header)+sizeof(tcp_header);
*ptr=(char)0x02;*(ptr+1)=(char)0x04;*(ptr+2)=(char)0x05;*(ptr+3)=(char)0xb4;
tcp_header.th_sum=checksum((USHORT *)sendBuf,sizeof(psd_header)+24);
ZeroMemory(sendBuf,iTotalSize);
//填充发送缓冲区
memcpy(sendBuf,&ip_header,sizeof(ip_header));
ptr=sendBuf+sizeof(ip_header);
memcpy(ptr,&tcp_header,sizeof(tcp_header));
ptr=sendBuf+sizeof(ip_header)+sizeof(tcp_header);
*ptr=(char)0x02;*(ptr+1)=(char)0x04;*(ptr+2)=(char)0x05;*(ptr+3)=(char)0xb4;
remote.sin_family = AF_INET;
remote.sin_port = htons(destPort);
remote.sin_addr.s_addr = inet_addr(szDestIP);
iErrorCode = sendto(s, sendBuf, iTotalSize, 0, (SOCKADDR *)&remote, sizeof(remote));
if(iErrorCode==SOCKET_ERROR)
return;
iTotalSize=40;
iTCPSize=20;
// end--------
closesocket(s);
delete[] sendBuf;
return;
}
问题点数:0、回复次数:7Top
1 楼lovend(颓废之吻)回复于 2005-06-04 19:04:06 得分 0
帮你顶Top
2 楼qinmaofan(采菊南山下【抵制日货】)回复于 2005-06-06 15:27:02 得分 0
请调试看是到哪里出的错,并用 wsagetlasterror 查看错误代码。Top
3 楼xukaiming(许开明)回复于 2005-06-06 16:33:32 得分 0
mark
Top
4 楼chwdong(chwdong)回复于 2005-06-06 21:39:40 得分 0
1、每次发送要加延时,防止对方没有处理,导致丢包
2、不要再调试环境实用程序,而是通过memo或日至文件监视过程Top
5 楼lovend(颓废之吻)回复于 2005-06-07 00:37:44 得分 0
帮你顶Top
6 楼heluqing(鉴之小河〖劳累求充实〗)(vcl .net)回复于 2005-06-07 13:36:28 得分 0
关注,最近也在搞这个...Top
7 楼heluqing(鉴之小河〖劳累求充实〗)(vcl .net)回复于 2005-06-09 16:24:01 得分 0
upup...Top




