D
dywapple
Unregistered / Unconfirmed
GUEST, unregistred user!
如题,代码如下:执行到Test_PPPOE函数里的recvfrom函数后,总是提示"recvfrom Error!",希望得到大家的帮助,谢谢.unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Winsock;const PPPOE_CODE_PADI = $09; PPPOE_CODE_PADO = $07; PPPOE_CODE_PADR = $19; PPPOE_CODE_PADS = $65; PPPOE_CODE_PADT = $A7; PPPOE_CODE_PADM = $D3; PPPOE_CODE_PADN = $D4; PPPOE_CODE_SESS = $00; PPPOE_TAG_END_LIST = $0000; PPPOE_TAG_SERVICE_NAME = $0101; PPPOE_TAG_AC_NAME = $0102; PPPOE_TAG_HOST_UNIQ = $0103; PPPOE_TAG_AC_COOKIE = $0104; PPPOE_TAG_VENDOR_SPES = $0105; PPPOE_TAG_RELAY_SESS = $0106; PPPOE_TAG_HOST_URL = $0111; PPPOE_TAG_MOTM = $0112; PPPOE_TAG_IP_ROUTE_ADD = $0121; PPPOE_TAG_SERVICE_ERR = $0201; PPPOE_TAG_AC_SYSTEM_ERR= $0202; PPPOE_TAG_GENERIC_ERR = $0203;type ip_mreq = record imr_multiaddr: in_addr; (* IP multicast address of group *) imr_interface: in_addr; (* local IP address of interface *) end; TIpMReq = ip_mreq; PIpMReq = ^ip_mreq; Ppppoe_Packet = ^Tpppoe_Packet; Tpppoe_Packet = record ver: BYTE; code: BYTE; session: WORD; length: WORD; TAG: WORD; TAGLen: WORD; data: Array [0..128] of char; end; TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end;var Form1: TForm1;implementation{$R *.dfm} function openudp(port: integer; broadcast: integer = 0; Handle: THandle = 0; msg: integer = 0): TSocket;type PWSAData = ^WSAData;var Len: Integer; nsize: integer; FSockAddrIn: TSockAddr; mreq: TIpMReq; arg: u_long; tmpWSA: TWSAData; tmpRes: integer;begin //ip_mreq tmpRes := WSAStartup($101, tmpWSA); result := Socket(AF_INET, SOCK_DGRAM, 0); if result <> INVALID_SOCKET then begin FSockAddrIn.sin_family := AF_INET; FSockAddrIn.sin_addr.S_addr := htonl(INADDR_ANY); FSockAddrIn.sin_port := htons(port); nsize := SizeOf(TSockAddr); if Bind(result, FSockAddrIn, nsize) <> 0 then begin closesocket(Result); Result := INVALID_SOCKET; end; if broadcast = 1 then begin if SetSockopt(result, SOL_SOCKET, SO_BROADCAST, @broadcast, sizeof(broadcast)) = SOCKET_ERROR then begin closesocket(Result); Result := INVALID_SOCKET; end; broadcast := 0; //禁止回馈 if setsockopt(result, IPPROTO_IP, IP_MULTICAST_LOOP, @broadcast, sizeof(broadcast)) = SOCKET_ERROR then begin closesocket(Result); Result := INVALID_SOCKET; end; end; arg := 1; ioctlsocket(result, FIONBIO, arg); if (Handle > 0) and (msg > 0) then begin if WSAAsyncSelect(result, Handle, Msg, FD_READ) = SOCKET_ERROR then begin closesocket(Result); Result := INVALID_SOCKET; end; end; end;end;function Test_PPPOE: Boolean;var Pkg: Tpppoe_Packet; socket: TSocket; ToAddr: TSockAddr; Len, Revlen, Ret: Integer;begin Result := False; Fillchar(Pkg, sizeof(Tpppoe_Packet), 0); Pkg.ver := 33; Pkg.Code := PPPOE_CODE_PADI; Pkg.session := 0; pkg.length := 4; pkg.TAGLen := 0; pkg.Tag := PPPOE_TAG_SERVICE_NAME; socket := openudp(0, 1); if socket <> INVALID_SOCKET then begin ToAddr.sin_family := AF_INET; ToAddr.sin_addr.S_addr := htonl(INADDR_BROADCAST); sendto(socket, pkg, 10, 0, ToAddr, sizeof(ToAddr)); sleep(500); Len := sizeof(ToAddr); //此步接收不到返回,Ret总是-1 Ret := recvfrom(socket, pkg, 2, 0, ToAddr, Len); if Ret = SOCKET_ERROR then begin ShowMessage('recvfrom Error!'); end; if Ret >= 0 then Revlen := Ret else Revlen := 0; If Revlen < 2 then begin sleep(500); Ret := recvfrom(socket, pkg, 2, 0, ToAddr, Len); if Ret >= 0 then Revlen := Revlen + Ret; end; if Revlen >= 2 then Result := pkg.code = PPPOE_CODE_PADO; end;end;