Community
cancel
Showing results for 
Search instead for 
Did you mean: 
SoniaG
Beginner
216 Views

Check internet connection from Fortran program

Jump to solution

I want my Fortran program to check for internet connection and warn the user if not connected.  I think I need to use the method GetConnectivity but can't find an example of this for use in Fortran. Apparently the API, InternetGetConnectedState is no longer recommended.

Any help or advice would be appreciated - manys thanks in advance.

0 Kudos

Accepted Solutions
FortranFan
Honored Contributor I
101 Views

@SoniaG ,

Re: ".. I think I need to use the method GetConnectivity but can't find an example of this for use in Fortran. ..," you may have seen this at the Microsoft site:

https://docs.microsoft.com/en-us/windows/win32/api/netlistmgr/nf-netlistmgr-inetworklistmanager-getc...

You'll notice the GetConnectivity - which is indeed Microsoft's recommended method in their so-called unmanaged programs (and which is what all Fortran apps are) on Windows - is a C++ class method of INetworkListManager that is invokable via COM.  As such, you would either need to use Intel Fortran's COM interoperability module(s) or setup something yourself using C-Fortran interoperability.  Both are a little more effort than I would be willing to undertake, so I would instead write a small extern "C" wrapper function in C++ like so: it's a one-time effort easier to manage I feel:

 

#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <Netlistmgr.h>
#include <atlbase.h>

extern "C" int IsConnected(char *msg, size_t lenmsg) 
{ 

  int irc = 0;
  CoInitialize(NULL);
  {
    CComPtr<INetworkListManager> pNLM;
    HRESULT hr = CoCreateInstance(CLSID_NetworkListManager, NULL, 
      CLSCTX_ALL, __uuidof(INetworkListManager), (LPVOID*)&pNLM);
    if (SUCCEEDED(hr))
    {
      NLM_CONNECTIVITY con = NLM_CONNECTIVITY_DISCONNECTED;
      hr = pNLM->GetConnectivity(&con);
      if SUCCEEDED(hr)
      {
        if (con & NLM_CONNECTIVITY_DISCONNECTED)
          snprintf(msg, lenmsg, "%s\n", "Disconnected");
        if (con & NLM_CONNECTIVITY_IPV4_NOTRAFFIC)
          snprintf(msg, lenmsg, "%s\n", "IP4: No Traffic");
        if (con & NLM_CONNECTIVITY_IPV6_NOTRAFFIC)
          snprintf(msg, lenmsg, "%s\n", "IP6: No Traffic");
        if (con & NLM_CONNECTIVITY_IPV4_INTERNET)
          snprintf(msg, lenmsg, "%s\n", "IP4: Internet");
        if (con & NLM_CONNECTIVITY_IPV4_LOCALNETWORK)
          snprintf(msg, lenmsg, "%s\n", "IP4: Local");
        if (con & NLM_CONNECTIVITY_IPV4_SUBNET)
          snprintf(msg, lenmsg, "%s\n", "IP4: Subnet");
        if (con & NLM_CONNECTIVITY_IPV6_INTERNET)
          snprintf(msg, lenmsg, "%s\n", "IP6: Internet");
        if (con & NLM_CONNECTIVITY_IPV6_LOCALNETWORK)
          snprintf(msg, lenmsg, "%s\n", "IP6: Local");
        if (con & NLM_CONNECTIVITY_IPV6_SUBNET)
          snprintf(msg, lenmsg, "%s\n", "IP6: Subnet");
      }
    }
    irc = (int)hr;
  }
  CoUninitialize();
  return irc; 
} 

 

And setup an interface to it in Fortran like so, again a one-time effort:

 

module NetListMgr_m

   use, intrinsic :: iso_c_binding, only : c_char, c_int, c_size_t

   interface
      function IsConnected( Msg, LenMsg ) result(r) bind(C, name="IsConnected" )

      ! int IsConnected(char *msg, size_t lenmsg);

         import :: c_char, c_int, c_size_t

         ! Argument list
         character(kind=c_char, len=1), intent(in) :: Msg(*)
         integer(c_size_t), intent(in), value      :: LenMsg
         ! Function result
         integer(c_int) :: r

      end function 
   end interface

end module

 

Then the following Fortran test program can make use of it:

 

program TestConnection

   use, intrinsic :: iso_c_binding, only : c_char, c_size_t, c_int
   use NetListMgr_m, only : IsConnected
   
   character(kind=c_char, len=256) :: ConnectionState
   integer(c_size_t) :: lens
   integer(c_int) :: cstat

   lens = int( len(ConnectionState), kind=kind(lens) )
   cstat = IsConnected( ConnectionState, lens )
   print *, "ctsat: ", cstat
   print *, trim(ConnectionState)
   
end program 

 

You can tuck away the above C function and the Fortran module code in a library (static or DLL) and use it in your Fortran programs - Visual Studio projects can make this easy as you may know.

From the command-line, for illustration purposes, you can expect the following behavior:

 

C:\Temp>cl /c /EHsc /W3 IsConnected.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.26.28806 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

IsConnected.cpp

C:\Temp>ifort /c /standard-semantics /warn:all /stand:f18 NetListMgr.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.1.2 Build 20201208_000000
Copyright (C) 1985-2020 Intel Corporation.  All rights reserved.


C:\Temp>ifort /c /standard-semantics /warn:all /stand:f18 TestConnection.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.1.2 Build 20201208_000000
Copyright (C) 1985-2020 Intel Corporation.  All rights reserved.


C:\Temp>link TestConnection.obj NetListMgr.obj IsConnected.obj /subsystem:console /out:TestConnection.exe
Microsoft (R) Incremental Linker Version 14.26.28806.0
Copyright (C) Microsoft Corporation.  All rights reserved.


C:\Temp>TestConnection.exe
 ctsat:  0
 IP4: Internet



C:\Temp>

 

P.S.> Some of the above code is a bit more verbose than otherwise, but it's for the benefit of other readers also.  Also, it's possible Intel Fortran provides some module procedures for this - I've not checked - but that will be compiler-specific.  The above should work with any Fortran standard supporting compiler.

 

View solution in original post

7 Replies
andrew_4619
Valued Contributor III
191 Views

Not quite the same thing but I use URLDownloadToFile to download a page from the web to a local file. A failure to get something that is known to exist could be indicative of no connection.  

jimdempseyatthecove
Black Belt
180 Views

Experiment with EXECUTE_COMMAND_LINE with "ping -w 500 -n 1 yahoo.com>check.txt"

You should test to see if exitstat returns error code when ping fails, and in which case you need not check the check.txt for ping error.

Jim Dempsey

JohnNichols
Valued Contributor I
172 Views

https://community.intel.com/t5/Intel-Fortran-Compiler/Checking-internet-connection-from-fortran/td-p... 

There is a rather interesting answer here from 2011 -- it should still work 

SoniaG
Beginner
141 Views

Thanks @jimdempseyatthecove 

I have written the following code but, although the command execution runs, I almost always get an estat of 1.  My program is running in Windows and I am connected to the internet (it's a strong signal and not intermittant).  I get similar results whether running in debug (Visual Studio) or in production.

If the code below looks ok, I assume there must be something else at play?

call execute_command_line("ping -w 500 -n 1 yahoo.com>check.txt",exitstat=estat,cmdstat=cstat,cmdmsg=cmsg)
if(cstat > 0) then
  iret = messagebox(ghwndmain,'Command execution failed with error'//trim(cmsg)//char(0),'Check for                    internet connection'//char(0),mb_ok)
else if(cstat < 0) then
  iret = messagebox(ghwndmain,'Command execution not supported'//trim(cmsg)//char(0),'Check for                      internet connection'//char(0),mb_ok)
 else
    write(cestat,'(I4)')estat
    if(estat==0)then
      iret = messagebox(ghwndmain,'Internet connection ok, estat ='//trim(cestat)//char(0),'Check for                                internet connection'//char(0),mb_ok)
    else
      iret = messagebox(ghwndmain,'No internet connection found, estat ='//trim(cestat)//char(0),'Check                        for internet connection'//char(0),mb_ok)
     end if
end if

jimdempseyatthecove
Black Belt
121 Views

What happens if you set the timeout to -w 5000?

Jim Dempsey

FortranFan
Honored Contributor I
102 Views

@SoniaG ,

Re: ".. I think I need to use the method GetConnectivity but can't find an example of this for use in Fortran. ..," you may have seen this at the Microsoft site:

https://docs.microsoft.com/en-us/windows/win32/api/netlistmgr/nf-netlistmgr-inetworklistmanager-getc...

You'll notice the GetConnectivity - which is indeed Microsoft's recommended method in their so-called unmanaged programs (and which is what all Fortran apps are) on Windows - is a C++ class method of INetworkListManager that is invokable via COM.  As such, you would either need to use Intel Fortran's COM interoperability module(s) or setup something yourself using C-Fortran interoperability.  Both are a little more effort than I would be willing to undertake, so I would instead write a small extern "C" wrapper function in C++ like so: it's a one-time effort easier to manage I feel:

 

#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <Netlistmgr.h>
#include <atlbase.h>

extern "C" int IsConnected(char *msg, size_t lenmsg) 
{ 

  int irc = 0;
  CoInitialize(NULL);
  {
    CComPtr<INetworkListManager> pNLM;
    HRESULT hr = CoCreateInstance(CLSID_NetworkListManager, NULL, 
      CLSCTX_ALL, __uuidof(INetworkListManager), (LPVOID*)&pNLM);
    if (SUCCEEDED(hr))
    {
      NLM_CONNECTIVITY con = NLM_CONNECTIVITY_DISCONNECTED;
      hr = pNLM->GetConnectivity(&con);
      if SUCCEEDED(hr)
      {
        if (con & NLM_CONNECTIVITY_DISCONNECTED)
          snprintf(msg, lenmsg, "%s\n", "Disconnected");
        if (con & NLM_CONNECTIVITY_IPV4_NOTRAFFIC)
          snprintf(msg, lenmsg, "%s\n", "IP4: No Traffic");
        if (con & NLM_CONNECTIVITY_IPV6_NOTRAFFIC)
          snprintf(msg, lenmsg, "%s\n", "IP6: No Traffic");
        if (con & NLM_CONNECTIVITY_IPV4_INTERNET)
          snprintf(msg, lenmsg, "%s\n", "IP4: Internet");
        if (con & NLM_CONNECTIVITY_IPV4_LOCALNETWORK)
          snprintf(msg, lenmsg, "%s\n", "IP4: Local");
        if (con & NLM_CONNECTIVITY_IPV4_SUBNET)
          snprintf(msg, lenmsg, "%s\n", "IP4: Subnet");
        if (con & NLM_CONNECTIVITY_IPV6_INTERNET)
          snprintf(msg, lenmsg, "%s\n", "IP6: Internet");
        if (con & NLM_CONNECTIVITY_IPV6_LOCALNETWORK)
          snprintf(msg, lenmsg, "%s\n", "IP6: Local");
        if (con & NLM_CONNECTIVITY_IPV6_SUBNET)
          snprintf(msg, lenmsg, "%s\n", "IP6: Subnet");
      }
    }
    irc = (int)hr;
  }
  CoUninitialize();
  return irc; 
} 

 

And setup an interface to it in Fortran like so, again a one-time effort:

 

module NetListMgr_m

   use, intrinsic :: iso_c_binding, only : c_char, c_int, c_size_t

   interface
      function IsConnected( Msg, LenMsg ) result(r) bind(C, name="IsConnected" )

      ! int IsConnected(char *msg, size_t lenmsg);

         import :: c_char, c_int, c_size_t

         ! Argument list
         character(kind=c_char, len=1), intent(in) :: Msg(*)
         integer(c_size_t), intent(in), value      :: LenMsg
         ! Function result
         integer(c_int) :: r

      end function 
   end interface

end module

 

Then the following Fortran test program can make use of it:

 

program TestConnection

   use, intrinsic :: iso_c_binding, only : c_char, c_size_t, c_int
   use NetListMgr_m, only : IsConnected
   
   character(kind=c_char, len=256) :: ConnectionState
   integer(c_size_t) :: lens
   integer(c_int) :: cstat

   lens = int( len(ConnectionState), kind=kind(lens) )
   cstat = IsConnected( ConnectionState, lens )
   print *, "ctsat: ", cstat
   print *, trim(ConnectionState)
   
end program 

 

You can tuck away the above C function and the Fortran module code in a library (static or DLL) and use it in your Fortran programs - Visual Studio projects can make this easy as you may know.

From the command-line, for illustration purposes, you can expect the following behavior:

 

C:\Temp>cl /c /EHsc /W3 IsConnected.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.26.28806 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

IsConnected.cpp

C:\Temp>ifort /c /standard-semantics /warn:all /stand:f18 NetListMgr.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.1.2 Build 20201208_000000
Copyright (C) 1985-2020 Intel Corporation.  All rights reserved.


C:\Temp>ifort /c /standard-semantics /warn:all /stand:f18 TestConnection.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.1.2 Build 20201208_000000
Copyright (C) 1985-2020 Intel Corporation.  All rights reserved.


C:\Temp>link TestConnection.obj NetListMgr.obj IsConnected.obj /subsystem:console /out:TestConnection.exe
Microsoft (R) Incremental Linker Version 14.26.28806.0
Copyright (C) Microsoft Corporation.  All rights reserved.


C:\Temp>TestConnection.exe
 ctsat:  0
 IP4: Internet



C:\Temp>

 

P.S.> Some of the above code is a bit more verbose than otherwise, but it's for the benefit of other readers also.  Also, it's possible Intel Fortran provides some module procedures for this - I've not checked - but that will be compiler-specific.  The above should work with any Fortran standard supporting compiler.

 

View solution in original post

JohnNichols
Valued Contributor I
94 Views

Sonia:

FortranFan's method is as good as it gets, I would adopt this one and stop searching.  

Tags (1)