本人基本未写过通信方面程序,请大家帮忙解决,
在Delphi时如何实现发送以太网II协议的数据,网上说如果用Windows API实现,下面A条中的PR、SD、FCS是不用自己填的
不知道Delphi如何实现,请高手指点,谢谢!A.以太网的物理传输帧结构表
PR SD DA SA TYPE DATA FCS
同步位 分隔位 目的地址 源地址 类型字段 数据段 帧校验序列
7 1 6 6 2 46~1500 4 (此行都是占用 字节数)B.在网上找的相关函数和链接
socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))在Delphi中根本用不了 下面的链接讲的根本不行
http://blog.csdn.net/yanwenyuan0102/archive/2006/09/11/1209691.aspx
C.下了科来发包工具用了,好像发送时还要选择一个网卡,不知道他是如何实现的
D.自己写的一点代码,根本实现不了,不知道如何发送出去,/***
以下函数是用WS2_32.DLL中的
***/cosnt
SOCKET_ERROR = -1; type
//以太网
T_Ethernet = packed record
DescMac: array[0..5] of byte;
SrcMac: array[0..5] of byte;
Protocol: Word;
Data: array[0..1499] of byte;//最小46,最大1500
end;function TfrmMain.SendDataE(): Boolean;
Var
sh : TSocket;
ret : Integer;
Remote : TSockAddr;
iTotalSize : Word;
wsdata : TWSAdata;
DestIP, SrcMac, DestMac: string;
Ebuf: T_Ethernet;
begin // Startup Winsock 2
Result := False; ret := WSAStartup($0002, wsdata);
if ret <> 0 then
begin
memo1.lines.add('WSA Startup failed.');
exit;
end; with memo1.lines do
begin
add('WSA Startup:');
add('Desc.: ' + wsData.szDescription);
add('Status: ' + wsData.szSystemStatus);
end; try
try
// Create socket
SrcMac := edtSrcMac.Text;
if length(SrcMac) <> 12 then
begin
showmessage('源MAC地址输入有误!');
Exit;
end; DestMac := edtDestMac.Text;
if length(DestMac) <> 12 then
begin
showmessage('目的MAC地址输入有误!');
Exit;
end; if inet_addr(Pchar(DestIP)) = -1 then
begin
ShowMessage('目的IP输入非法。');
Exit;
end; if memSendE.Text = '' then
begin
ShowMessage('请输入待发送的内容。');
Exit;
end; ///此处要怎么调用??
//sh := Socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
sh := Socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (sh = INVALID_SOCKET) then
begin
memo1.lines.add('Socket() failed: '+IntToStr(WSAGetLastError));
exit;
end; Memo1.lines.add('Socket Handle = '+IntToStr(sh)); {
// Modified by Administrator 2010-12-20 16:23:07
// Option: Header Include
bOpt := 1;//这是网找的,只能设置IP帧格式
//ret := SetSockOpt(sh, IPPROTO_IP, IP_HDRINCL, @bOpt, SizeOf(bOpt));
//ret := SetSockOpt(sh, IPPROTO_RAW, IP_HDRINCL, @bOpt, SizeOf(bOpt));
} if ret = SOCKET_ERROR then
begin
Memo1.lines.add('setsockopt(IP_HDRINCL) failed: '+IntToStr(WSAGetLastError));
exit;
end; //end of // Modified by Administrator 2010-12-20 16:22:57
// Added by Administrator 2010-12-20 16:24:44
remote.sin_family := AF_INET;
remote.sin_port := htons(0);
remote.sin_addr.s_addr := inet_addr(PChar(DestIP));
//end of // Added by Administrator 2010-12-20 16:24:49
// Send the packet 我应如何填充,如何发送?????? /*
...
...
*/ //ret := SendTo(sh, Ebuf, iTotalSize, 0, Remote, SizeOf(Remote));
if ret = SOCKET_ERROR then
Memo1.Lines.Add('sendto() failed: '+IntToStr(WSAGetLastError))
else
Memo1.Lines.Add('send '+IntToStr(ret)+' bytes.'); // Close socket
CloseSocket(sh);
Result := True; except
on E: Exception do
begin
ShowMessage('数据发送出错,原因:' + e.Message);
end;
end;
finally
// Close Winsock 2
WSACleanup;
end;end;
在Delphi时如何实现发送以太网II协议的数据,网上说如果用Windows API实现,下面A条中的PR、SD、FCS是不用自己填的
不知道Delphi如何实现,请高手指点,谢谢!A.以太网的物理传输帧结构表
PR SD DA SA TYPE DATA FCS
同步位 分隔位 目的地址 源地址 类型字段 数据段 帧校验序列
7 1 6 6 2 46~1500 4 (此行都是占用 字节数)B.在网上找的相关函数和链接
socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))在Delphi中根本用不了 下面的链接讲的根本不行
http://blog.csdn.net/yanwenyuan0102/archive/2006/09/11/1209691.aspx
C.下了科来发包工具用了,好像发送时还要选择一个网卡,不知道他是如何实现的
D.自己写的一点代码,根本实现不了,不知道如何发送出去,/***
以下函数是用WS2_32.DLL中的
***/cosnt
SOCKET_ERROR = -1; type
//以太网
T_Ethernet = packed record
DescMac: array[0..5] of byte;
SrcMac: array[0..5] of byte;
Protocol: Word;
Data: array[0..1499] of byte;//最小46,最大1500
end;function TfrmMain.SendDataE(): Boolean;
Var
sh : TSocket;
ret : Integer;
Remote : TSockAddr;
iTotalSize : Word;
wsdata : TWSAdata;
DestIP, SrcMac, DestMac: string;
Ebuf: T_Ethernet;
begin // Startup Winsock 2
Result := False; ret := WSAStartup($0002, wsdata);
if ret <> 0 then
begin
memo1.lines.add('WSA Startup failed.');
exit;
end; with memo1.lines do
begin
add('WSA Startup:');
add('Desc.: ' + wsData.szDescription);
add('Status: ' + wsData.szSystemStatus);
end; try
try
// Create socket
SrcMac := edtSrcMac.Text;
if length(SrcMac) <> 12 then
begin
showmessage('源MAC地址输入有误!');
Exit;
end; DestMac := edtDestMac.Text;
if length(DestMac) <> 12 then
begin
showmessage('目的MAC地址输入有误!');
Exit;
end; if inet_addr(Pchar(DestIP)) = -1 then
begin
ShowMessage('目的IP输入非法。');
Exit;
end; if memSendE.Text = '' then
begin
ShowMessage('请输入待发送的内容。');
Exit;
end; ///此处要怎么调用??
//sh := Socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
sh := Socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (sh = INVALID_SOCKET) then
begin
memo1.lines.add('Socket() failed: '+IntToStr(WSAGetLastError));
exit;
end; Memo1.lines.add('Socket Handle = '+IntToStr(sh)); {
// Modified by Administrator 2010-12-20 16:23:07
// Option: Header Include
bOpt := 1;//这是网找的,只能设置IP帧格式
//ret := SetSockOpt(sh, IPPROTO_IP, IP_HDRINCL, @bOpt, SizeOf(bOpt));
//ret := SetSockOpt(sh, IPPROTO_RAW, IP_HDRINCL, @bOpt, SizeOf(bOpt));
} if ret = SOCKET_ERROR then
begin
Memo1.lines.add('setsockopt(IP_HDRINCL) failed: '+IntToStr(WSAGetLastError));
exit;
end; //end of // Modified by Administrator 2010-12-20 16:22:57
// Added by Administrator 2010-12-20 16:24:44
remote.sin_family := AF_INET;
remote.sin_port := htons(0);
remote.sin_addr.s_addr := inet_addr(PChar(DestIP));
//end of // Added by Administrator 2010-12-20 16:24:49
// Send the packet 我应如何填充,如何发送?????? /*
...
...
*/ //ret := SendTo(sh, Ebuf, iTotalSize, 0, Remote, SizeOf(Remote));
if ret = SOCKET_ERROR then
Memo1.Lines.Add('sendto() failed: '+IntToStr(WSAGetLastError))
else
Memo1.Lines.Add('send '+IntToStr(ret)+' bytes.'); // Close socket
CloseSocket(sh);
Result := True; except
on E: Exception do
begin
ShowMessage('数据发送出错,原因:' + e.Message);
end;
end;
finally
// Close Winsock 2
WSACleanup;
end;end;
好像Delphi不支持数据链路层的协议包,最多支持IP层的。
等待高手回答。