?
Solved

IP MultiCasting & Interface selection problem...

Posted on 2003-03-05
17
Medium Priority
?
501 Views
Last Modified: 2010-04-04
Let's say I have 4 ethernet cards installed and I am using IP MultiCasting. When I receive data there's no problem. But if I try to send data using sendto() I am getting problem. Is there a way to select interface to send data? Is it possible to do that with setsockopts() or using iphlpapi (routing) ? Can someone please send me a sample?

Regards,
0
Comment
Question by:Dumani
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
17 Comments
 
LVL 2

Expert Comment

by:steve_hsk
ID: 8079010
Hi Dumani ...

This is something I overcome on a monthly basis, and is a very common problem. There are different ways from which to approach this, my favourite being by IP Address.

If you have 4 different Ethernet cards, you must be connected to 4 different networks, each with a different (list of) IP address(es).

When you create the socket, you must bind it before you can communicate. If you select the IP address you want to bind to, this represents the network card and attached subnet.

If you want the user to be able to select at run-time which network to communicate with (like a network monitor), then you can use the IP Helper API (IPHlpAPI) to produce a network card list. You can retrive the IP addr from that card, and then perform your bind operation.

I can provide examples of a simple bind, or an IPHlpAPI example (IP Addr ADD, Retrive, remove)(route add, retrieve, remove)(network interface list).

Need to know a little more about what you're trying to acheieve, as each example can be quite lengthy ???

PS ... It can get more conveinient sometimes, by adding multiple alias IP addresses to a single network interface, which depending on your network, can provide you with some better design options.

Hope this helps,
Steve
0
 
LVL 1

Author Comment

by:Dumani
ID: 8079113
Thanks for your comment but I have bind my ethernet ip which did not work. I can get ethernet list using iphlpapi. I don't have any problems with it. However i can not seelct the ethernet i want to use during runtime. If you please give me an example on how to select it would be perfect.
0
 
LVL 2

Expert Comment

by:steve_hsk
ID: 8079364
Hi Dumani ...

If your bind did not work, then I would have thought that the problem would be with the bind statement and the necessary parameters. Eg you may have an incorrect IP address, or you may not have any IP address, or Winsock may not have been initialised, etcetc...

I Can check this code if you wish. Otherwise the IPHlpAPI example to provide a list of network cards and their details, including IP addresses :-

This just a button and a memopad on a form :-

uses
  IPExport,
  IPHlpApi,
  Iprtrmib,
  IpTypes,
  Winsock;


procedure VVGetNetworkParams(var p: PfixedInfo; var OutBufLen: Cardinal);
var
  Res: DWORD;
begin
  p := Nil;
  OutBufLen := 0;
  if @GetNetworkParams = Nil then
    raise EIpHlpError.CreateFmt(sNotImplemented, ['GetNetworkParams']);
  Res := GetNetworkParams(p, OutBufLen);
  if Res = ERROR_BUFFER_OVERFLOW then
  begin
    Getmem(p, OutBufLen);
    FillChar(p^, OutBufLen, #0);
    Res := GetNetworkParams(p, OutBufLen);
  end;
  if Res <> 0 then
    IpHlpError('GetNetworkParams', Res);
end;

procedure VVGetPerAdapterInfo(IfIndex: Cardinal; var p: PIpPerAdapterInfo;
  var OutBufLen: Cardinal);
var
  Res: DWORD;
begin
  p := Nil;
  OutBufLen := 0;
  if @GetPerAdapterInfo = Nil then
    raise EIpHlpError.CreateFmt(sNotImplemented, ['GetPerAdapterInfo']);
  Res := GetPerAdapterInfo(IfIndex,p, OutBufLen);
  if Res = ERROR_BUFFER_OVERFLOW then
  begin
    Getmem(p, OutBufLen);
    FillChar(p^, OutBufLen, #0);
    Res := GetPerAdapterInfo(IfIndex,p, OutBufLen);
  end;
  if Res <> 0 then
    IpHlpError('GetPerAdapterInfo', Res);
end;

procedure TFmIpTest.BtGetAdaptersInfoClick(Sender: TObject);
var
  PAdapter, PMem: PipAdapterInfo;
  pPerAdapter: PIpPerAdapterInfo;
  PIPAddr: PIpAddrString;
  OutBufLen, OutBufLen2: ULONG;
  s: string;
  i: integer;
begin
  Memo1.Lines.Add('GetAdaptersInfo');
  VVGetAdaptersInfo(PAdapter, OutBufLen);
  PMem := PAdapter;
  try
    while PAdapter <> nil do
      with Memo1.Lines do
      begin
        Add('AdapterName: ' + PAdapter.AdapterName);
        Add('Description: ' + PAdapter.Description);
        s := '';
        for i := 0 to PAdapter.AddressLength do
          s := s + Format('%1d', [PAdapter.Address[i]]);
        Add('Index: ' + IntToStr(PAdapter.Index));
        Add('Type: ' + IntToStr(PAdapter.Type_));
        Add('DhcpEnabled: ' + IntToStr(PAdapter.DhcpEnabled));
        if PAdapter.CurrentIpAddress <> nil then
        begin
          Add('CurrentIpAddress.IpAddress:' + PAdapter.CurrentIpAddress.IpAddress.S);
          Add('CurrentIpAddress.IpMask:' + PAdapter.CurrentIpAddress.IpMask.S);
        end
        else
          Add('CurrentIpAddress: nil');
        PIPAddr := @PAdapter.IpAddressList;
        repeat
          Add('-----------');
          Add('IpAddressList.IpAddress ' + PIPAddr.IpAddress.S);
          Add('IpAddressList.IpMask ' + PIPAddr.IpMask.S);
          PIPAddr := PIPAddr.Next;
        until PIPAddr = nil;
        Add('-----------');
        try
          Memo1.Lines.Add('GetPerAdapterInfo');
          VVGetPerAdapterInfo(PAdapter.Index, pPerAdapter,OutBufLen2);
          if pPerAdapter <> nil then
            try
              Add('AutoconfigEnabled: ' + IntToStr(pPerAdapter.AutoconfigEnabled));
              Add('AutoconfigActive: ' + IntToStr(pPerAdapter.AutoconfigActive));
              PIPAddr := pPerAdapter.CurrentDnsServer;
              if not Assigned(PIPAddr) then
                Add('CurrentDnsServer: nil');
              while Assigned(PIPAddr) do
              begin
                Add('CurrentDnsServer.IpAddress: ' + PIPAddr^.IpAddress.S);
                Add('CurrentDnsServer.IpMask: ' + PIPAddr^.IpMask.S);
                PIPAddr := PIPAddr.Next;
              end;
              PIPAddr := @pPerAdapter.DnsServerList;
              while Assigned(PIPAddr) do
              begin
                Add('DnsServerList.IpAddress: ' + pPerAdapter.DnsServerList.IpAddress.S);
                Add('DnsServerList.IpMask: ' + pPerAdapter.DnsServerList.IpMask.S);
                PIPAddr := PIPAddr.Next;
              end;
            finally
              Freemem(pPerAdapter,OutBufLen2);
            end;
        except
          on E:EIpHlpError do
            ShowMessage(E.Message);
        end;
        PAdapter := PAdapter.Next;
      end;
  finally
    if PAdapter <> nil then
      Freemem(PMem, OutBufLen);
  end;
end;

This code should be downloaded form :-
http://delphi-jedi.org 
http://voldemarv.virtualave.net 

Portions created by Vladimir Vassiliev are
Copyright (C) 2000 Vladimir Vassiliev. All Rights Reserved. The original file is: IpUnit1.pas, released  December 2000. The initial developer of the Pascal code is Vladimir Vassiliev voldemarv@hotpop.com                  

Contributor(s): Marcel van Brakel (brakelm@bart.nl)
                John Penman (jcp@craiglockhart.com)

I can also provide C++Builder and VC++ and other delphi examples I've written ... I think this is the easiest to understand.

Hope this helps ?!? :-)
Steve


0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 1

Author Comment

by:Dumani
ID: 8079430
Thanks but i don't have any problem with getting ethernet information. I need to USE selected interface to send data. That's the problem
0
 
LVL 2

Expert Comment

by:steve_hsk
ID: 8079495
That's what I've been trying to say Dumani ...

After you've decided on which interface from the list you want to use, simply pass the IP address to your bind statement, and you will then have a socket bound to that network card via the IP address.

I'm 110% sure this works.

Using the above example, take the following variable for your chosen card :-

PAdapter.CurrentIpAddress.IpAddress.S

and use it in your bind code :-

m_tpAddress   : tSockAddrIn;
m_tUDPSock    : TSocket;

m_tpAddress.sin_family      := AF_INET;
m_tpAddress.sin_port        := htons(8601);
m_tpAddress.sin_addr.S_addr := PAdapter.CurrentIpAddress.IpAddress.S;

IF (bind (m_tUDPSock, @m_tpAddress,sizeof(tSockAddrIn)) = SOCKET_ERROR) THEN
BEGIN
      // Analyse the Error if it occurs to find out why your bind fails
      Result := WSAGetLastError;
END;


Any better ;-) ?

Steve
0
 
LVL 1

Author Comment

by:Dumani
ID: 8079661
I am sorry but that does not work. Please try that. I have tried that millions time.
Even i try to enter manualy it did not work.
adrinfo.sin_addr.S_addr := inet_addr('192.168.0.1');
0
 
LVL 2

Expert Comment

by:steve_hsk
ID: 8079693
That's what I've been trying to say Dumani ...

After you've decided on which interface from the list you want to use, simply pass the IP address to your bind statement, and you will then have a socket bound to that network card via the IP address.

I'm 110% sure this works.

Using the above example, take the following variable for your chosen card :-

PAdapter.CurrentIpAddress.IpAddress.S

and use it in your bind code :-

m_tpAddress   : tSockAddrIn;
m_tUDPSock    : TSocket;

m_tpAddress.sin_family      := AF_INET;
m_tpAddress.sin_port        := htons(8601);
m_tpAddress.sin_addr.S_addr := PAdapter.CurrentIpAddress.IpAddress.S;

IF (bind (m_tUDPSock, @m_tpAddress,sizeof(tSockAddrIn)) = SOCKET_ERROR) THEN
BEGIN
      // Analyse the Error if it occurs to find out why your bind fails
      Result := WSAGetLastError;
END;


Any better ;-) ?

Steve
0
 
LVL 2

Expert Comment

by:steve_hsk
ID: 8079937
Oops, sorry - posted again by mistake !

what is the bind error you get from (what is result?):

IF (bind (m_tUDPSock, @m_tpAddress,sizeof(tSockAddrIn)) = SOCKET_ERROR) THEN
BEGIN
     // Analyse the Error if it occurs to find out why your bind fails
     Result := WSAGetLastError; // <<<< ?
END;

maybe this will provide a clue ?

Steve
0
 
LVL 1

Author Comment

by:Dumani
ID: 8080017
Steve, I don't have any error. I can bind without any problem. But that does not work. I can multicast also without any problems. I can receive data however i can not send data with specified adapter.
0
 
LVL 2

Expert Comment

by:steve_hsk
ID: 8080137
ok, now we're getting there :-) slowly ...

>> "i can not send data with specified adapter."

Well you're sending via the IP addr you're bound to, so concentrate there, not on the adapter. I don't think the IPHlpAPI has anything to do with you're problem, nor the bind nor the receive procedure obviously !!!

So lets concentrate on the sendto !

1. What error do you get when you send ?
again using sendto () = SOCKET_ERROR and then WSAGetLastError = what ? ie : what does winsock think is wrong ?

2. Can you send data to a unicast addr ... maybe to your own IP addr successfully, or is it throwing errors no matter what ?

Steve

0
 
LVL 1

Author Comment

by:Dumani
ID: 8080197
Data goes from other ethernet card without any problems. So data arrives because connection is not required i don't get any problems. NO SOCKET_ERROR :)
0
 
LVL 2

Expert Comment

by:steve_hsk
ID: 8080334
ok, so winsock thinks everything is peachy with Unicast and MCast IP addresses and sends the packet successfully !

So the problem is it doesn't arrive successfully ?

If so, to check : just before you send do a :
OutputDebugString(sIpAddress), and check the event log to ensure that the IP address you're using is correct.

If you have a network monitor/sniffer, you should be able to validate the packet leaving the machine.

Finally, check the routes in your routing table to ensure this packet has a path : md dos prompt :  route print.

If this is all ok, then the sending machine seems to be operating successully. It would appear the receiver is not operating as it should ?

Steve
0
 
LVL 2

Expert Comment

by:steve_hsk
ID: 8081291
ps ... just a quick thought :

If you are joining MCast groups, I'm assuming you've set the correct socket options wspjoinleaf, and created the socket with wsPsocket ?

Steve
0
 
LVL 1

Author Comment

by:Dumani
ID: 8106859
Steve thanks for your replies but they don't work. I found what i need and i am writing it down. Regards,

var
  localif: integer;
begin
  localif := inet_addr(PChar('192.168.0.1'));
  setsockopt(FSocket, IPPROTO_IP, IP_MULTICAST_IF, @localif, sizeof(localif));
end;
0
 

Expert Comment

by:CleanupPing
ID: 9316911
Dumani:
This old question needs to be finalized -- accept an answer, split points, or get a refund.  For information on your options, please click here-> http:/help/closing.jsp#1 
EXPERTS:
Post your closing recommendations!  No comment means you don't care.
0
 
LVL 5

Expert Comment

by:snehanshu
ID: 10044824
Hi!
No comment has been added lately and this question is therefore classified abandoned.

If asker wishes to close the question, then refer to
http://www.experts-exchange.com/help/closing.jsp

Otherwise, I will leave a recommendation in the Cleanup topic area that this question is:

AQ'd and pts refunded

Please leave any comments here within the next seven days. It is assumed that any participant not responding to this request is no longer interested in its final disposition.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

...Snehanshu
EE Cleanup Volunteer
0
 

Accepted Solution

by:
modulo earned 0 total points
ID: 10113855
PAQed, with points refunded (150)

modulo
Community Support Moderator
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
Suggested Courses
Course of the Month11 days, 20 hours left to enroll

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question