[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1151
  • Last Modified:

how to poll file descriptors in java

Hello,

My Java application needs to poll a number of file descriptors to determine which one is ready for input. I know there is Selector class in Java, but the problem is the file descriptors which needs to be polled come from JNI code (from libpcap's pcap_get_selectable_fd() in fact).

Is there any way to work with these descriptors via the standard or perhaps a customized Selector? I have looked at implementing SelectableChannel or extending AbstractSelectableChannel, but can't figure out how to implement it properly and what other classes needs to be extended.

Attached is a sample C code illustrating select() loop which I would like to implement in Java. As I have said, instead of implementing this loop as is in JNI, I would like to reuse existing Selector framework.

Thanks in advance for your feedback.
/**
 * This function initializes a live capture PCAP handle and possibly
 * grabs a selectable file handle.
 */
pcap_t*
pcap_alloc(const char *dev, int *fd) {
    pcap_t *handle;
    char errbuf[PCAP_ERRBUF_SIZE];

#ifdef USE_PCAP100
    handle = pcap_create(dev, errbuf);
    if (handle == NULL) {
        fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
        exit(EXIT_FAILURE);
    }

    if (pcap_set_promisc(handle, 1) < 0) {
        pcap_perror(handle, "pcap_set_promisc");
        exit(EXIT_FAILURE);
    }

    if (pcap_activate(handle) < 0) {
        pcap_perror(handle, "pcap_activate");
        exit(EXIT_FAILURE);
    }
#else
    handle = pcap_open_live(dev, 64 * 1024 /* snaplen */, 1 /* promisc */, 1 /* timeout */, errbuf);
    if (handle == NULL) {
        fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
        exit(EXIT_FAILURE);
    }

    /* make sure we're capturing on an Ethernet device */
    if (pcap_datalink(handle) != DLT_EN10MB) {
        fprintf(stderr, "%s is not an Ethernet\n", dev);
        exit(EXIT_FAILURE);
    }
#endif

    if (fd) {
#if USE_PCAP_SELECT
        *fd = pcap_get_selectable_fd(handle);
        if (*fd < 0) {
            fprintf(stderr, "Failed to get selectable FD for PCAP handle\n");
            exit(EXIT_FAILURE);
        }
#else
        *fd = -1;
#endif // USE_PCAP_SELECT
    }

    return handle;
}

/**
 * main() expects two parameters -- names of the network interfaces to bridge
 */
int
main(int argc, char *argv[]) {
    int f_pcap1, f_pcap2;
    pcap_t *pcap1, *pcap2;

    assert(argc == 3);
    pcap1 = pcap_alloc(argv[1], &f_pcap1);
    pcap2 = pcap_alloc(argv[2], &f_pcap2);

#if USE_PCAP_SELECT
    int fm = max(f_pcap1, f_pcap2) + 1;
#endif // USE_PCAP_SELECT

    for (;;) {
#if USE_PCAP_SELECT
        fd_set fds;

        FD_ZERO(&fds);
        FD_SET(f_pcap1, &fds);
        FD_SET(f_pcap2, &fds);

        int res = select(fm, &fds, NULL, NULL, NULL);
        if (res < 0) {
            perror("select");
            continue;
        } else if (res == 0) {
            continue;
        }

        if (FD_ISSET(f_pcap1, &fds)) {
            forward(pcap1, pcap2);
        }

        if (FD_ISSET(f_pcap2, &fds)) {
            forward(pcap2, pcap1);
        }
#else
        forward(pcap1, pcap2);
        forward(pcap2, pcap1);
#endif // USE_PCAP_SELECT
    }
}

Open in new window

0
gremwell
Asked:
gremwell
  • 4
1 Solution
 
for_yanCommented:

This looks like dealing with similar issue, but it still uses JNI:
http://www.kfu.com/~nsayer/Java/jni-filedesc.html

This code illustrates the use of Selector listening to server sockets,
rathe than files; still may happen to be of some use
http://www.javafaq.nu/java-example-code-353.html

This is I guess also relevant discussion (looks lik it still cannot be  done in pure Java):
http://stackoverflow.com/questions/3893236/java-detecting-modification-to-a-file-file-polling
0
 
for_yanCommented:
0
 
for_yanCommented:
And, finally, maybe you want to be the first to try Java 7 which has WatchService API, which would probably, do what you want:

http://java.sun.com/developer/technicalArticles/javase/nio/#6

http://dlc.sun.com.edgesuite.net/jdk7/binaries/index.html
0
 
gremwellAuthor Commented:
Thanks for your feedback! The first link you have provided -- wrapping native file descriptor into Java FileDescriptor objects -- seems to be relevant to my goal. The next question would be how to produce a selectable channel out of FileDescriptor. By looking at JDK sources I have found sun.nio.ch.SourceChannelImpl class (extending Pipe.SourceChannel, extending AbstractSelectableChannel), which I will try to repurpose.
0
 
for_yanCommented:
Great! I'm happy there was something useful. And just for my understanding when you say "to determine which one is ready for input" do you mean that your application needs to write big blocks of data to several files, and you do it in separate thread, so after you dispatched say first block of data to each of the files you want to know which one is done with writing and is now ready to accept next input - is it something like that?
0

Featured Post

Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now