Grab live up/down speeds to use in an app

Discussion in 'Mac Programming' started by patent10021, Dec 15, 2015.

  1. patent10021 macrumors 68020

    patent10021

    Joined:
    Apr 23, 2004
    #1
    I use and app that displays the live down/up speed on the dock icon.

    I would actually like to view and retrieve the live up/down speeds so I can use it in an app I'm making. I looked in Activity Monitor and Network Utility. Activity Monitor displays the PID and received/sent packets which is good for what I want to do but that's only half the data I need. Where can I find the live streaming up/down speeds?

    Ultimately what I need is to know how to request/parse that live data so I can use it in an app.
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    Exactly what app is it that's displaying the speeds?
     
  3. patent10021 thread starter macrumors 68020

    patent10021

    Joined:
    Apr 23, 2004
    #3
    It's just a networking app. I cannot nor do I want to use that app in anyway. I know the PID so do you know any course of action?
     
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    The reason I asked "which app" is to discover whether it's scriptable or not. If it's not scriptable in some way, then it's very unlikely you'll be able to get it to cough up its data. Knowing its PID counts for nothing if it's not scriptable.

    If you don't intend to use this networking app, what were you intending to use?

    I don't know of any simple readable number or system property that contains the up/down speed. That means the app in question is reading other data and calculating the speed. I don't know what that data would be, or where to get it directly. I'd probably email the developer of the "networking app" and ask what he's doing.
     
  5. patent10021 thread starter macrumors 68020

    patent10021

    Joined:
    Apr 23, 2004
    #5
    Thanks. I'm experimenting with network data from various P2P apps like Vuze, Transmission. I just thought it would be straight forward to retrieve live in/out data since it's being displayed on the dock. How is it possible that it can be displayed on the dock but a developer can't find out what data is going in/out. I know they're sandboxed but I thought you could get the data via Unix or something.
     
  6. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #6
    It's displayed on the Dock because the developer wrote the app to do that. It's not available to other apps, because displaying something on the app's Dock tile isn't a service that other apps can access, and it has nothing at all to do with Unix.
     
  7. patent10021 thread starter macrumors 68020

    patent10021

    Joined:
    Apr 23, 2004
    #7
    Yeah I know his app has nothing to do with Unix. But Terminal can often parse info like that. Obviously other apps can't access that because as I said above they're sandboxed. I could access it if I clutch/class_dump etc but I thought maybe there was an easier way.
     
  8. cruisin macrumors 6502a

    cruisin

    Joined:
    Apr 1, 2014
    Location:
    Canada
    #8
    Terminal can parse things that are specifically set up to do so. If the app has no command line interface, then Terminal cannot magically create one. You might be able to write something to get the data out, but you might as well write your own speed monitor at this point.

    Maybe start with nettop in Terminal and calculate the changes in traffic every second.
     
  9. mfram macrumors 65816

    Joined:
    Jan 23, 2010
    Location:
    San Diego, CA USA
    #9
    There is an API to get network traffic statistics on a per-interface basis using the sysctl() API. That's how the command-line utilities in Terminal get them. There are several network interfaces on your Mac though. So you'd have to get the data from each interfaces and look at the differences. The idea is to periodically get the stats for all of the interfaces, wait a bit of time, then look at the stats again. For each interface compute the delta over the time frame. Add all the deltas together. That's your final answer.

    There may be complications. Looks like there are bridge interfaces defined, so you might have to filter those numbers out. The following C program demonstrates the API. The program is a command-line program. If you give an interface name as a parameter, it will print the stats for that interface. With no parameter, the stats for all interfaces are displayed. I got the information how to call the API from looking at the source code for the command-line utilities Apple supplies in the shell. It's all open-source.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/sysctl.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <net/if.h>
    #include <net/if_var.h>
    #include <net/if_dl.h>
    #include <net/if_types.h>
    #include <net/if_mib.h>
    #include <net/route.h>
    
    #include <netinet/in.h>
    #include <netinet/in_var.h>
    #include <unistd.h>
    
    static u_int64_t opackets = 0;
    static u_int64_t ipackets = 0;
    static u_int64_t obytes = 0;
    static u_int64_t ibytes = 0;
    
    int get_stats(char *interface)
    {
        int ret = 0;
        char name[32];
        int mib[6];
        char *buf = NULL, *lim, *next;
        size_t len;
        struct if_msghdr *ifm;
        unsigned int ifindex = 0;
    
        if (interface != 0)
            ifindex = if_nametoindex(interface);
    
        mib[0] = CTL_NET;
        mib[1] = PF_ROUTE;
        mib[2] = 0;
        mib[3] = 0;
        mib[4] = NET_RT_IFLIST2;
        mib[5] = 0;
    
        if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
            return ret;
        if ((buf = malloc(len)) == NULL)
        {
            printf("malloc failed\n");
            exit(1);
        }
        if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
        {
            if (buf)
                free(buf);
            return ret;
        }
        lim = buf + len;
        for (next = buf; next < lim;)
        {
            ifm = (struct if_msghdr *)next;
            next += ifm->ifm_msglen;
    
            if (ifm->ifm_type == RTM_IFINFO2)
            {
                struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
                struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1);
    
                strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
                name[sdl->sdl_nlen] = 0;
                if (interface != 0 && if2m->ifm_index != ifindex)
                    continue;
    
                /* Get the interface stats.  These may get overriden below on a
                * per-interface basis. */
                opackets = if2m->ifm_data.ifi_opackets;
                ipackets = if2m->ifm_data.ifi_ipackets;
                obytes = if2m->ifm_data.ifi_obytes;
                ibytes = if2m->ifm_data.ifi_ibytes;
                if (ret == 0)
                {
                    printf("%-5.5s %8.8s %10.10s ",
                          "Name", "Ipkts", "IBytes");
                    printf("%8.8s %10.10s\n", "Opkts", "Obytes");
                    ret = 1;
                }
                printf("%-5.5s %-8.8llu ", name, ipackets);
                printf("%10.10llu ", ibytes);
                printf("%-8.8llu ", opackets);
                printf("%10.10llu\n", obytes);
            }
        }
    
        free(buf);
    
        return ret;
    }
    
    int main(int argc, char *argv[])
    {
        char *ifname;
        int r;
        int sleeptime = 2;
    
        if (argc > 1)
        {
            ifname = argv[1];
        }
        else
        {
            ifname = NULL;
        }
    
        r = get_stats(ifname);
        if (r)
        {
            u_int64_t ib = ibytes;
            u_int64_t ob = obytes;
    
            sleep(sleeptime);
            get_stats(ifname);
            printf("%llu %llu\n", (ibytes - ib) / sleeptime, (obytes - ob) / sleeptime);
        }
        else
        {
            printf("No interface %s\n", ifname);
        }
    }
    
    Output on my Mac. The numbers are high because it was doing Time Machine backups.

    You probably only care about the "en*" interfaces for your computations.

    Code:
    Name     Ipkts     IBytes    Opkts     Obytes
    lo0   07514701 0837525720 07514701 0837525720
    gif0  00000000 0000000000 00000000 0000000000
    stf0  00000000 0000000000 00000000 0000000000
    en0   22939150 12779688691 310084487 425409620722
    en1   00000000 0000000000 00000000 0000000000
    en2   00000000 0000000000 00000000 0000000000
    p2p0  00000000 0000000000 00000000 0000000000
    awdl0 00000026 0000009682 00000466 0000128978
    bridg 00000000 0000000000 00000001 0000000342
    utun0 00000021 0000004154 00000024 0000003770
    utun1 00000021 0000003461 00000024 0000003686
    en4   00110874 0141280827 00073781 0022160605
    
     

Share This Page