Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
UDP broadcast message fails
#1
Dear All; here's another easy one. I'm trying to send out a udp broadcast msg like this:

Code:
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 254
  ClientWidth = 535
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Memo1: TMemo
    Left = 8
    Top = 40
    Width = 293
    Height = 206
    Lines.Strings = (
      'Memo1')
    TabOrder = 0
  end
  object Button1: TButton
    Left = 12
    Top = 8
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 1
    OnClick = Button1Click
  end
  object IdUDPClient1: TIdUDPClient
    BroadcastEnabled = True
    Port = 0
    Left = 364
    Top = 28
  end
end

Code:
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdUDPBase.hpp>
#include <IdUDPClient.hpp>
class TForm1 : public TForm{
__published: // IDE-managed Components
  TMemo *Memo1;
  TButton *Button1;
  TIdUDPClient *IdUDPClient1;
  void __fastcall Button1Click(TObject *Sender);
private: // User declarations
public: // User declarations
  __fastcall TForm1(TComponent* Owner);
};
extern PACKAGE TForm1 *Form1;
#endif

Code:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner){}
void __fastcall TForm1::Button1Click(TObject *Sender){
  try{
    IdUDPClient1->Broadcast( "This is a test. Ignore it.", 45242 );
  }catch( EIdException &e ){
    Memo1->Lines->Add( e.Message );
  }
}
//---------------------------------------------------------------------------

When the Button1 is clicked - nothing visible happens, so I look at the WireShark dump but I have no idea what is going on (see attached). Please help. TIA.
Reply
#2
is my attachment there? can't see it. where is it?
Reply
#3
(07-18-2019, 03:49 AM)Boba TC Wrote: IdUDPClient1->Broadcast( "This is a test. Ignore it.", 45242 );

When the Button1 is clicked - nothing visible happens.

You are not specifying an IP address to broadcast to, so it will default to "255.255.255.255", which is not really a good choice to broadcast to, as some routers/firewalls block it.  You really should be broadcasting to an actual subnet broadcast IP instead.

For instance, if your computer is assigned an IP of 192.168.0.5 with a subnet mask of 255.2255.255.0, then the subnet broadcast IP is 192.168.0.255.

If you look at the source code for TIdSocketHandle.Broadcast() in IdSocketHandle.pas, there is the following TODO comment:

Code:
if LIP = '' then begin
  if IPVersion = Id_IPv4 then begin
    // TODO: on Windows, use WSAIoctl(SIO_GET_BROADCAST_ADDRESS) instead.
    // On other platforms, use getifaddrs() or other suitable API to retreive
    // the broadcast IP if possible, or else the local IP/Subnet and then
    // calculate the broadcast IP manually...
    LIP := '255.255.255.255'; {Do not Localize}

If you don't use a platform-specific API to get the subnet broadcast IP, you can calculate it manually by getting the local IPv4 address and subnet mask (such as via GStack.GetLocalAddressList()), and then AND the IP with the mask, and then OR the result with the inverse of the mask.  The TIdIPAddress class can be used to parse the IP and mask strings into binary integers, and then to convert the result of the calculation back into an IP string.

(07-18-2019, 03:49 AM)Boba TC Wrote: I look at the WireShark dump but I have no idea what is going on (see attached).

There is no attachment present.

(07-18-2019, 05:51 PM)Boba TC Wrote: is my attachment there? can't see it. where is it?

Looks like you did not actually attach it.

Reply
#4
(07-18-2019, 10:22 PM)rlebeau Wrote: tried 2 times - no complains from the browser, but no attachment either...
Quote:You are not specifying an IP address to broadcast to...
this is it: I should not have made that assumption regarding default broadcast address, will look through the source before posting next time.
I was puzzled by the WireShark response (attaching again by different browser).
Reply
#5
(07-19-2019, 02:26 AM)Boba TC Wrote: I was puzzled by the WireShark response (attaching again by different browser).

Still no attachment. Either you are not attaching it correctly, or the server is blocking it (unsupported file type? too large in size?), etc.

Reply
#6
(07-19-2019, 09:55 PM)rlebeau Wrote:
(07-19-2019, 02:26 AM)Boba TC Wrote: I was puzzled by the WireShark response (attaching again by different browser).

Still no attachment.  Either you are not attaching it correctly, or the server is blocking it (unsupported file type? too large in size?), etc.
what types of attachments are allowed? an image? (saved as PNG instead BMP)
Reply
#7
I guess no attachments are allowed. Basically, wire shark was reporting an exception due to a malformed packet: the second frame had unacceptably high length.
Now, with explicit binding to the default broadcast address, the shark is happy and I can see the message text on the wire. So, here comes PART II:
how do I catch this message on my LAN? I create another application (would be called a server side) with TIdUDPServer component and I bind it to that same
address and port. The applications reports an exception on start-up saying 'Could not bind socket. Address and port are already in use'. With 'netstat -q'
I do not see any UDP sockets bound/listening to/on that particular address:port combination. Please advise. Many thanks in advance. Boba TC.
Reply
#8
(07-20-2019, 08:09 PM)Boba TC Wrote: I guess no attachments are allowed.

They should be.  Images and such have been posted in this forum before.  I don't have admin access to the forum settings, so I don't know if there are any restrictions set, though.

(07-20-2019, 08:09 PM)Boba TC Wrote: Basically, wire shark was reporting an exception due to a malformed packet: the second frame had unacceptably high length.
Now, with explicit binding to the default broadcast address, the shark is happy and I can see the message text on the wire.

You can't bind a socket to a broadcast IP, since that IP does not belong to the local machine.  You can only bind to a local IP for the network adapter that is connected to the subnet which the broadcast IP belongs to.

(07-20-2019, 08:09 PM)Boba TC Wrote: how do I catch this message on my LAN? I create another application (would be called a server side) with TIdUDPServer component and I bind it to that same address and port.

Again, you can only bind to a local IP, not to a broadcast IP.  However, if the TIdUDPServer is bound to a network adapter that is connected to the subnet being broadcasted to, then it should receive the broadcast messages just fine, you don't need to do anything extra for that.

Also, if the broadcasting client and receiving server are running on the same machine, do not bind them to the same local IP : Port.  In faact, you should not be binding the client's Port at all, unless your network router requires broadcasts to come from a specific port.

(07-20-2019, 08:09 PM)Boba TC Wrote: The applications reports an exception on start-up saying 'Could not bind socket. Address and port are already in use'.

Then you are trying to bind your server to something you can't bind it to.

Reply
#9
(07-18-2019, 10:22 PM)rlebeau Wrote: For instance, if your computer is assigned an IP of 192.168.0.5 with a subnet mask of 255.2255.255.0, then the subnet broadcast IP is 192.168.0.255.

If you look at the source code for TIdSocketHandle.Broadcast() in IdSocketHandle.pas, there is the following TODO comment:

Code:
if LIP = '' then begin
  if IPVersion = Id_IPv4 then begin
    // TODO: on Windows, use WSAIoctl(SIO_GET_BROADCAST_ADDRESS) instead.
    // On other platforms, use getifaddrs() or other suitable API to retreive
    // the broadcast IP if possible, or else the local IP/Subnet and then
    // calculate the broadcast IP manually...
    LIP := '255.255.255.255'; {Do not Localize}

Thank you, Gambit. Now I am frustrated with my last compiler from Borland (ver.6) - the 32-bit code it creates does not run as expected:

Code:
#include <winsock2.h>

WSADATA wsaData;
SOCKET sktUDP;
BOOL b;
BYTE buff[0x8000];
sockaddr_in sabrdcst;
int iWSAerr;
DWORD dw;
//error checking is omitted for a well known reason
  ::ZeroMemory(&wsaData, sizeof(wsaData));
  WSAStartup(0x0202, &wsaData);
  sktUDP = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  b = TRUE;
  setsockopt(sktUDP, SOL_SOCKET, SO_BROADCAST, (char*)&b, sizeof(b));
  ::ZeroMemory(&sabrdcst, sizeof(sabrdcst));
  iWSAerr = WSAIoctl(sktUDP, SIO_GET_BROADCAST_ADDRESS, NULL, 0, &sabrdcst, sizeof(sabrdcst), &dw, NULL, NULL);

The last line (WSAIoctl() call) causes an AV no matter what. Note: both pointers in the call are 16-byte aligned otherwise the return is error 10014.

This happens on win10-64 regardless of compatibility settings. Neither MS compilers nor 3rd party ones exhibit this problem.

Tried BCC32.exe v.5 & v.6, but v.4 is ok. I do need the code above to be used with BCC32 vers.5 & 6. What are my options?

Thanks in advance.
Reply
#10
(08-17-2019, 04:35 AM)Boba TC Wrote: The last line (WSAIoctl() call) causes an AV no matter what. Note: both pointers in the call are 16-byte aligned otherwise the return is error 10014.

See https://stackoverflow.com/questions/861154/. Apparently Windows 10 has a known issue where sometimes Winsock does not like using buffers on the stack even if they are aligned properly. Try dynamically allocating them on the heap instead.

Also, why are you allocating a 32K buffer on the stack? The code you showed does not use or need it. You are just wasting the stack.

(08-17-2019, 04:35 AM)Boba TC Wrote: This happens on win10-64 regardless of compatibility settings. Neither MS compilers nor 3rd party ones exhibit this problem.

Have you compared the codegen between the various compilers for the same code to see what is different between them?

Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)