请教关于组播在多IP主机中无法接收的问题,紧急!!! ( 积分: 200 )

  • 主题发起人 主题发起人 lxggc
  • 开始时间 开始时间
L

lxggc

Unregistered / Unconfirmed
GUEST, unregistred user!
本人用 Indy 的组播控件做了一个软件, 在同一台机器上同时运行服务端和客户端用于发送和接收, 在主机只有一个IP地址的情况下运行很正常, 但如果主机有 2 个IP地址, 客户端就无法收到数据, 通过查阅相关文档, 问题可能出在客户端绑定问题上, 请高手解释一下, 先谢了!!!
 
本人用 Indy 的组播控件做了一个软件, 在同一台机器上同时运行服务端和客户端用于发送和接收, 在主机只有一个IP地址的情况下运行很正常, 但如果主机有 2 个IP地址, 客户端就无法收到数据, 通过查阅相关文档, 问题可能出在客户端绑定问题上, 请高手解释一下, 先谢了!!!
 
请高手赐教,分不够可以加
 
我也是认为是绑定的问题,如果两个网卡的IP不在同一网段,可以增加路由来解决这个问题。
 
还有哪位兄弟碰到过这个问题,大家可以交流一下啊
 
我是在一个上网的机器上测试的, 未上网之前,机器有 IP地址 192.168.0.73 ,测试没有
问题, 上网之后,机器增加了一个 222.241.*.* 的地址, 再测试时 发送没有错误提示,但
接收不到任何数据.
 
等待高手....
 
我测试了一下,好像不是Indy的问题, 用 Socket Api 也有这个问题
 
绑定一个ip之后还有问题么?你用Socket Api事怎么写的
 
绑定一个ip好象没有问题,我的机器也是两个IP,我是直接使用Socket Api,好象没有问题
 
感觉是个有意义的问题,留名,关注
 
有问题啊,我也是绑定了的,用 SockApi 写很简单 ,无非是先创建 udp socket, 然后设置多播选项,再绑定,最后发送、接收。可是还是不行啊, 那位大侠能给出你们的源码吗?
 
unit UdpSocet;

interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,WinSock;


const WM_UdpSocked=wm_user+255;
default_GroupIP='224.0.0.2'; //默认组播地址
type


TIp_Mreq= record
Imr_MultiAddr:in_addr;
Imr_InterFace:in_addr;
end;

TUdpType=(utSingle,utBroadcast,utMulticast);

TUdpClientRead=procedure (Buf:PChar;const BufSize:Integer;fromIp:string;fromPort:word) of object;
TUdpClientWrite=procedure (Sender:TObject) of object;
TUDPOnRecv = procedure (buffer: Pointer; len: integer; fromIP: string; fromPort: Word) of Object;


TUDPRecvThread = class(TThread)
private
fSocks : TSocket;
fBufSize : integer;
fOnRecv : TUDPOnRecv;
protected
procedure Execute;override;
public
constructor Create(AUdpSock:TSocket;AUdpOnRecv:TUDPOnRecv;BufSize:Integer);
end;

TUdpSocket=class(TComponent)
private
FUdpSocket:TSocket;
FActive:Boolean;
FHost:String;
FPort:Word;
FByteSize:integer;
FBuffer:array[0..10000] of char;
FClientRead:TUdpClientRead;
FClientWrite:TUdpClientWrite;
FWndHandle:HWND; //窗口句柄
FUdpType:TUdpType; //类型,单,广,组
FSendBufSize: integer; {发送缓冲区大小}
FRecvBufSize: integer; {接收缓冲区大小}
FGroupIp:String; {组播地址}
FSockAddrRemote:TSockAddr; {组播地址结构}
FLeavGroup:Boolean; //离开组
FIpmr:TIp_Mreq; {组播}
FUDPRecvThread:TUDPRecvThread;
FUDPOnRecv:TUDPOnRecv;
procedure SetActive(AActive:Boolean);
procedure UdpWndMethod(var Message: TMessage);
procedure SetSendBufSize(ASendBufSize:Integer);
procedure SetRecvBufSize(ARecvBufSize:Integer);
procedure SetGroupIP(AGroupIp:string);
procedure SetLeav_Group(ALeavGroup:Boolean);


public
constructor Create(AOwner:TComponent);
destructor Destroy;override;
procedure InitSocked;
Function UdpSendTo(var buf; bufsize: Integer; ToAddr: TSockAddr; flags: Integer=0):Integer;overload;
Function UdpSendTo(var buf; bufsize: Integer; AHost:String;APort:Word): Integer;overload;
Function UdpSendTo(var bufStr:String; AHost:String;APort:Word): Integer;overload;

Function UdpBroadcastSendTo(var buf; bufsize: Integer; ToAddr: TSockAddr; flags: Integer=0):Integer;overload;
Function UdpBroadcastSendTo(var buf; bufsize:Integer): Integer;overload;
Function UdpBroadcastSendTo(var bufStr:String): Integer;overload;


Function UdpMulticastSendTo(var buf; bufsize:Integer): Integer;overload;
Function UdpMulticastSendTo(bufStr:String): Integer;overload;



published
property LocaPort:Word read FPort write FPort;
Property Active:Boolean read FActive write SetActive;
property OnDateRead:TUdpClientRead read FClientRead write FClientRead;
property UdpType:TUdpType read FUdpType write FUdpType;
property SendBufSize:Integer read FSendBufSize write SetSendBufSize;
property RecvBufSize:Integer read FRecvBufSize write SetRecvBufSize;
property GroupIp:string read FGroupIp write SetGroupIP;
property LeavGroup:Boolean read FLeavGroup write SetLeav_Group;
property UDPOnRecv:TUDPOnRecv read FUDPOnRecv write FUDPOnRecv;

end;
implementation

{ TUdpSocket }



constructor TUdpSocket.Create(AOwner: TComponent);
var Wsd:TWSAData;
begin
inherited Create(AOwner);
FUdpSocket:=INVALID_SOCKET;
FWndHandle:=0;
FUdpType:=utSingle;
FSendBufSize:=8024;
FRecvBufSize:=8024;
FGroupIp:=default_GroupIP;
if WSAStartup(MakeWord(2,2),Wsd)<>0 then
begin
raise Exception.Create('Init WsaStartup');
Exit;
end;
end;

destructor TUdpSocket.Destroy;
begin
WSACleanup;
if FWndHandle>0 then
DeallocateHWnd(FWndHandle);
if FUdpSocket<>INVALID_SOCKET then
closesocket(FUdpSocket);
inherited Destroy;
end;

procedure TUdpSocket.InitSocked;
var Wsd:TWSAData;
Local:sockaddr_in;
BBroadCast:Integer;
optval:Integer;
begin
if FWndHandle<=0 then
begin
FWndHandle:=AllocateHWnd(UdpWndMethod);
if FWndHandle<=0 then
raise Exception.Create('AllocateHWnd error');
end
else
DeallocateHWnd(FWndHandle);

FUdpSocket:=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if FUdpSocket=INVALID_SOCKET then
begin
raise Exception.Create('INVALID_SOCKET');
Exit;
end;
if FUdpType=utBroadcast then
begin
BBroadCast:=1;
if setsockopt(FUdpSocket,SOL_SOCKET,SO_BROADCAST,PChar(@BBroadCast),sizeof(integer))=SOCKET_ERROR then
raise Exception.Create('setsockopt SO_BROADCAST Error');
end;

if setsockopt(FUdpSocket,SOL_SOCKET, SO_RCVBUF, @fRecvBufSize, SizeOf(integer))=SOCKET_ERROR then
begin
closesocket(FUdpSocket);
raise Exception.Create('setsockopt SO_RCVBUF Error');
end;
if setsockopt(FUdpSocket,SOL_SOCKET,SO_SNDBUF,PChar(@FSendBufSize),sizeof(integer))=SOCKET_ERROR then
begin
closesocket(FUdpSocket);
raise Exception.Create('setsockopt SO_SNDBUF Error');
end;

Local.sin_family:=AF_INET;
Local.sin_port:=FPort;
Local.sin_addr.S_addr:=htonl(INADDR_ANY);

if bind(FUdpSocket,Local,SizeOf(Local))=SOCKET_ERROR then
begin
raise Exception.Create('Bind Sock Error');
Exit;
end;

if FUdpType=utMulticast then
begin
optval:=30;
FIpmr.Imr_MultiAddr.S_addr:=inet_addr(PChar(FGroupIp));
FIpmr.Imr_InterFace.S_addr:=htonl(INADDR_ANY);
if setsockopt(FUdpSocket,IPPROTO_IP,IP_ADD_MEMBERSHIP,PChar(@FIpmr),SizeOf(FIpmr))=SOCKET_ERROR then
begin
raise Exception.Create('setsockopt IP_ADD_MEMBERSHIP Error');
SetActive(False);
Exit;
end;
if setsockopt(FUdpSocket,IPPROTO_IP,IP_MULTICAST_TTL,PChar(@optval),SizeOf(optval))=SOCKET_ERROR then
begin
raise Exception.Create('setsockopt IP_MULTICAST_TTL Error');
SetActive(False);
Exit;
end;

optval:=0;
if setsockopt(FUdpSocket,IPPROTO_IP,IP_MULTICAST_LOOP,PChar(@optval),SizeOf(optval))=SOCKET_ERROR then
begin
raise Exception.Create('setsockopt IP_MULTICAST_LOOP Error');
SetActive(False);
Exit;
end;
FSockAddrRemote.sin_family:=AF_INET;
FSockAddrRemote.sin_port:=FPort;
FSockAddrRemote.sin_addr.S_addr:=inet_addr(PChar(FGroupIp));
end;
// FUDPRecvThread:=TUDPRecvThread.Create(FUdpSocket,FUDPOnRecv,5000);
WSAAsyncSelect(FUdpSocket,FWndHandle,WM_UdpSocked,FD_READ or FD_CONNECT or FD_WRITE);
end;



function TUdpSocket.UdpSendTo(var buf; bufsize: Integer; ToAddr: TSockAddr;
flags: Integer): Integer;
begin
Result:=0;
if (FUdpType in[utSingle,utBroadcast]) and FActive then
Result:=sendto(FUdpSocket,buf,bufsize,flags,ToAddr,SizeOf(ToAddr));
end;





function TUdpSocket.UdpSendTo(var buf; bufsize: Integer; AHost: String;
APort: Word): Integer;
var ToAddr: TSockAddr ;
begin
Result:=0;
if (FUdpType in[utSingle,utBroadcast]) and FActive then
begin
ToAddr.sin_family:=AF_INET;
ToAddr.sin_port:=APort;
ToAddr.sin_addr.S_addr:=inet_addr(PChar(AHost));
if FUdpSocket<>INVALID_SOCKET then
Result:=sendto(FUdpSocket,buf,bufsize,0,ToAddr,SizeOf(ToAddr));
end;
end;

function TUdpSocket.UdpSendTo(var bufStr: String; AHost: String;
APort: Word): Integer;
begin
Result:=UdpSendTo(bufStr[1],length(bufStr),AHost,APort);
end;



procedure TUdpSocket.UdpWndMethod(var Message: TMessage);
var RecvSockedIn:TSockAddrIn;
SockedInSize:Integer;
begin
if Message.Msg=WM_UdpSocked then
begin
if WSAGetSelectError(Message.LParam)>0 then
begin
closesocket(Message.WParam);
end;
case WSAGetSelectEvent(Message.LParam) of
FD_READ:
begin
SockedInSize:=sizeof(RecvSockedIn);
FByteSize:=recvfrom(FUdpSocket,FBuffer,sizeof(FBuffer),0,RecvSockedIn,SockedInSize);
if (FByteSize>0) and (Assigned(FClientRead)) then
begin
FClientRead(FBuffer,FByteSize,inet_ntoa(RecvSockedIn.sin_addr),RecvSockedIn.sin_port);
FillChar(FBuffer,FByteSize,#0);
end;
end;

FD_WRITE:
begin
if Assigned(FClientWrite) then
FClientWrite(nil);
end;
end;
end;
end;

procedure TUdpSocket.SetActive(AActive: Boolean);
begin
if FActive<>AActive then
begin
FActive:=AActive;
if FUdpSocket<>INVALID_SOCKET then
begin
if not FActive then
begin
// SetLeav_Group(true);
// FUDPRecvThread.Terminate;
CloseHandle(FUdpSocket);
FUdpSocket:=INVALID_SOCKET;
end;
end
else
if FActive then
InitSocked;
end;
end;



function TUdpSocket.UdpBroadcastSendTo(var bufStr: String ): Integer;
begin
Result:=0;
if (FUdpType=utBroadcast) and FActive then
Result:=UdpSendTo(bufStr,'255.255.255.255',FPort);
end;

function TUdpSocket.UdpBroadcastSendTo(var buf; bufsize: Integer): Integer;
begin
Result:=0;
if (FUdpType=utBroadcast) and FActive then
Result:= UdpSendTo(buf,bufsize,'255.255.255.255',FPort);
end;

function TUdpSocket.UdpBroadcastSendTo(var buf; bufsize: Integer;
ToAddr: TSockAddr; flags: Integer): Integer;
begin
Result:=0;
if (FUdpType=utBroadcast) and FActive then
begin
ToAddr.sin_addr.S_addr:=inet_addr(PChar(INADDR_BROADCAST));
Result:= UdpSendTo(buf,bufsize,ToAddr,flags);
end;
end;



procedure TUdpSocket.SetRecvBufSize(ARecvBufSize: Integer);
begin
if FActive then
exit;
if (ARecvBufSize>=0) and (FRecvBufSize<>ARecvBufSize) then
FRecvBufSize:=ARecvBufSize;
end;

procedure TUdpSocket.SetSendBufSize(ASendBufSize: Integer);
begin
if FActive then
exit;
if (ASendBufSize>=0) and (FSendBufSize<>ASendBufSize) then
FSendBufSize:=ASendBufSize;
end;




procedure TUdpSocket.SetGroupIP(AGroupIp: string);
begin
if FGroupIp<>AGroupIp then
FGroupIp:=AGroupIp;
end;


function TUdpSocket.UdpMulticastSendTo(bufStr: String): Integer;
begin
Result:= UdpMulticastSendTo(bufStr[1],Length(bufStr) );
end;

function TUdpSocket.UdpMulticastSendTo(var buf; bufsize: Integer): Integer;
begin
Result:=0;
if (FUdpType=utMulticast) and FActive then
Result:=sendto(FUdpSocket,buf,bufsize,0,FSockAddrRemote,sizeof(FSockAddrRemote));

end;






procedure TUdpSocket.SetLeav_Group(ALeavGroup: Boolean);
begin
if FLeavGroup<>ALeavGroup then
FLeavGroup:=ALeavGroup;
if FActive and (FUdpType=utMulticast) and FLeavGroup then
if SetSockOpt(FUdpSocket, IPPROTO_IP, IP_DROP_MEMBERSHIP, @FIpmr, SizeOf(FIpmr))=SOCKET_ERROR THEN
begin
raise Exception.Create('setsockopt IP_DROP_MEMBERSHIP Error');
SetActive(False);
Exit;
end;
end;

{ TUDPRecvThd }

constructor TUDPRecvThread.Create(AUdpSock: TSocket; AUdpOnRecv: TUDPOnRecv;
BufSize: Integer);
begin
FreeOnTerminate:=true;
fSocks:=AUdpSock;
fOnRecv:=AUdpOnRecv;
fBufSize:=AUdpSock;
inherited Create(false);
end;

procedure TUDPRecvThread.Execute;
const MAXBUFFERSIZE=15000;
var
readFDs : TFDSet;
nRecved, nAddrLen: integer;
buf : array [0..MAXBUFFERSIZE] of Byte;
SockFrom : TSockAddr;

begin
Priority:=tpHigher;
while not Terminated do
begin
nAddrLen:=sizeof(SockFrom);
FD_ZERO(readFDs);
FD_SET(fSocks,readFDs);
select(0,@readFDs,nil,nil,nil);
if FD_ISSET(fSocks,readFDs) then
begin
nRecved:=recvfrom(fSocks,buf,fBufSize,0,SockFrom,nAddrLen);
if Assigned(fOnRecv) then
fOnRecv(@buf,nRecved,string(inet_ntoa(SockFrom.sin_addr)),dword(SockFrom.sin_port));
end;
end;
end;

end.
 
这是一段测试代码,不是很规范
 
组波是在同段ip 内进行的
多个ip的主机有分割网段的功能
你可以获得主机的ip列表
在决定帮顶哪个ip
 
后退
顶部