I am creating a Java class using JNI that allows various IPC mechanisms between separate Java programs.
I've created a class called WindowsIPC that contains a native method that can access Windows' named pipes. I have a native function called createNamedPipeServer() that calls CreateNamedPipe. It appears to have created the pipe correctly as I can view it using a tool such as Process Explorer.
My problem is that when I make use of this in a separate Java program and making use of a separate thread to read and write data using Java's standard Input and output streams, it fails. I can write data to the pipe successfully but cannot read the contents; it returns with a FileNotFoundException (All pipe instances are busy).
I am struggling to wrap my head around this as I cannot figure out what other process is using the pipe as well as the fact that I've specified PIPE_UNLIMITED_INSTANCES when the pipe was created.
I have read up extensively on how reads work and my hunch is that input/output streams in Java handle it due to the fact that it is returning the error mentioned above.
Any insights would be greatly appreciated.
Here is the code:
WindowIPC.java
public class WindowsIPC {
public native int createNamedPipeServer(String pipeName);
static {
System.loadLibrary("WindowsIPC");
}
public static void main(String[] args) {
// some testing..
}
}
WindowsIPC.c
const jbyte *nameOfPipe; // global variable representing the named pipe
HANDLE pipeHandle; // global handle..
JNIEXPORT jint JNICALL Java_WindowsIPC_createNamedPipeServer
(JNIEnv * env, jobject obj, jstring pipeName) {
jint retval = 0;
char buffer[1024]; // data buffer of 1K
DWORD cbBytes;
// Get the name of the pipe
nameOfPipe = (*env)->GetStringUTFChars(env, pipeName, NULL);
pipeHandle = CreateNamedPipe (
nameOfPipe, // name of the pipe
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE |
PIPE_READMODE_BYTE |
PIPE_NOWAIT, // forces a return, so thread doesn't block
PIPE_UNLIMITED_INSTANCES,
1024,
1024,
0,
NULL
);
// error creating server
if (pipeHandle == INVALID_HANDLE_VALUE) retval = -1;
else printf("Server created successfully: name:%sn", nameOfPipe);
// waits for a client -- currently in ASYC mode so returns immediately
jboolean clientConnected = ConnectNamedPipe(pipeHandle, NULL);
(*env)->ReleaseStringUTFChars(env, pipeName, nameOfPipe);
return retval;
}
And finally TestWinIPC.java
import java.io.*;
import java.util.Scanner;
public class TestWinIPC {
public static void main (String[] args)
{
WindowsIPC winIPC = new WindowsIPC();
// TEST NAMED PIPES
final String pipeName = "\\.\Pipe\JavaPipe";
if (winIPC.createNamedPipeServer(pipeName) == 0) {
System.out.println("named pipe creation succeeded");
Thread t = new Thread(new NamedPipeThread(pipeName));
t.start();
try {
System.out.println("opening pipe for input");
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(pipeName)));
System.out.println("waiting to read");
String line = br.readLine();
System.out.println("Read from pipe OK: " + line);
br.close();
}
catch (IOException exc) {
System.err.println("I/O Error: " + exc);
exc.printStackTrace();
}
}
} //main
private static class NamedPipeThread implements Runnable {
private String pipeName;
public NamedPipeThread (String pipeName) {
this.pipeName = pipeName;
} // constructor
public void run () {
try {
PrintWriter pw = new PrintWriter(new FileOutputStream(pipeName));
pw.println("Hello Pipe");
System.out.println("Wrote to named pipe OK");
pw.close();
}
catch (IOException exc) {
System.err.println("I/O Error: " + exc);
exc.printStackTrace();
}
} // run
}
}
Aucun commentaire:
Enregistrer un commentaire