我想往局域网内的另一台电脑发送一个自定义的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;
}