JNI实现命名管道服务器(二)——实现

原理在上一篇已经说好了,在这就不再赘述了,直接上代码,代码只是实现了一个基本框架,需要完善的东西大家可以自己加:

NamedPipe.java

 

public class NamedPipe implements Pipe {
	
	static{
		System.loadLibrary("NPJNI");
	}
	
	NamedPipeInputStream is;
	NamedPipeOutputStream os;
	
	int handle = -1;
	private String name;
	
	public String getName() {
		return name;
	}



	public NamedPipe(String name){
		this.name = name;
		this.handle = this.create(name);
		if(handle == -1){
			throw new NamedPipeCreateException(name);
		}
	}
	
	
	/**
	 * 等待接受一个客户端连接(堵塞)
	 * @return
	 */
	public boolean accept(){
		return this.connect(this.handle);
	}
	
	/**
	 * 得到一个PipeInputStream以读入数据
	 */
	public PipeInputStream getInputStream() {
		if(is == null){
			is = new NamedPipeInputStream(this);
		}
		return is;
	}

	/**
	 * 得到一个PipeOutputStream以写入数据
	 */
	public PipeOutputStream getOutputStream() {
		if(os == null){
			os = new NamedPipeOutputStream(this);
		}
		return os;
	}

	/**
	 * 关闭此NamedPipe
	 */
	public void close() {
		if(this.handle != -1){
			this.close(this.handle);
		}
	}
	
	/**
	 * 断开当前的客户端连接
	 */
	public void disconnect(){
		disconnect(handle);
	}

	private native void disconnect(int handle);
	
	private native void close(int handle);
	
	private native int create(String name);
	
	private native boolean connect(int handle);
}

 

 

 

 

NamedPipeInputStream:

 

 

public class NamedPipeInputStream extends PipeInputStream {

	NamedPipe pipe;
	
	static{
		System.loadLibrary("NPJNI");
	}
	
	NamedPipeInputStream(NamedPipe pipe){
		this.pipe = pipe;
	}
	
    private native int readBytes(int handle, byte b[], int len) throws IOException;

    /**
     * 读入数据到一个beye数组(堵塞)
     * @return 实际读取的字节数
     */
    public int read(byte b[]) throws IOException {
    	return readBytes(pipe.handle, b,  b.length);
    }
    
    /**
     * 读入数据到一个beye数组(堵塞)
     * @param b
     * @return 读取信息
     */
    public ReadPipeInfo readPipe(byte b[]){
    	return this.readPipe(pipe.handle,b,b.length);
    }
	
    public native ReadPipeInfo readPipe(int handle, byte b[], int len);
}
 

 

 

NamedPipeOutputStream.java:

 

public class NamedPipeOutputStream extends PipeOutputStream {
	
	NamedPipe pipe;
	ByteArrayOutputStream buffer = new ByteArrayOutputStream();
	
	static{
		System.loadLibrary("NPJNI");
	}
	
	NamedPipeOutputStream(NamedPipe pipe){
		this.pipe = pipe;
	}
	
	/*public final NamedPipe getPipe(){
		return pipe;
	}*/
	
	private native void writeBytes(int handle, byte b[], int len)
			throws IOException;
	
	

	private native void writeBytesOff(int handle, byte b[], int offset, int len)
			throws IOException;

	/**
	 * 将一个byte数组写入管道
	 */
	public void write(byte b[]) throws IOException {
		buffer.write(b);
	}
	
	/**
	 * 将字符串s写入管道
	 * @throws IOException 
	 */
	public void write(String s) throws IOException{
		buffer.write(s.getBytes());
	}
	
	/**
	 * 将byte数组写入管道。off指定了写入的偏移值,len指定写入的长度
	 */
	@Override
	public void write(byte[] b, int off, int len) throws IOException {
		this.writeBytesOff(pipe.handle,b,off,len);
	}

	/**
	 * flush此NamedPipeOutputStream,将所有数据写入管道
	 */
	public void flush() {
		byte[] bytes = buffer.toByteArray();
		if(bytes.length > 0){
			try {
				writeBytes(pipe.handle, bytes, bytes.length);
			} catch (IOException e) {
				e.printStackTrace();
			}
			buffer = new ByteArrayOutputStream();
			flush(pipe.handle);
		}
	}
	
	private native void flush(int handle);

}
 

 

ReadPipeInfo.java:

 

public class ReadPipeInfo {

	boolean more = false;
	int count = -1;
	
	public boolean hasMoreData(){
		return this.more;
	}
	
	public int readCount(){
		return count;
	}
	
}
 

 

C++代码:

 

#define BUFSIZE 4096*500
 

JNIEXPORT jint JNICALL Java_pipe_NamedPipe_create
  (JNIEnv *env, jobject obj, jstring name)
{
	const wchar_t *str = (const wchar_t *)env->GetStringChars(name,NULL);
	if(str == NULL)
	{
		return -1;
	}
	HANDLE hPipe;
	hPipe = CreateNamedPipe( 
		str,             // pipe name 
		PIPE_ACCESS_DUPLEX,       // read/write access 
		PIPE_TYPE_MESSAGE |       // message type pipe 
		PIPE_READMODE_MESSAGE |   // message-read mode 
		PIPE_WAIT,                // blocking mode 
		PIPE_UNLIMITED_INSTANCES, // max. instances  
		BUFSIZE,                  // output buffer size 
		BUFSIZE,                  // input buffer size 
		0,                        // client time-out 
		NULL);                    // default security attribute 

	if (hPipe == INVALID_HANDLE_VALUE) 
	{
		env->ReleaseStringChars(name, (const jchar *)str);
		printf("CreatePipe failed"); 
		return -1;
	}
	env->ReleaseStringChars(name, (const jchar *)str);
	return (long)hPipe;
}


JNIEXPORT jboolean JNICALL Java_pipe_NamedPipe_connect
  (JNIEnv *env, jobject obj, jint handle)
{
	HANDLE hPipe = (void *)((int)handle);
	BOOL fConnected = ConnectNamedPipe(hPipe, NULL) ? 
         TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); 
	return fConnected;
}


JNIEXPORT void JNICALL Java_pipe_NamedPipe_close
  (JNIEnv *env, jobject obj, jint handle)
{
	CloseHandle((void *)((int)handle));
}


JNIEXPORT void JNICALL Java_pipe_NamedPipe_disconnect
  (JNIEnv *env, jobject obj, jint handle)
{
	HANDLE hPipe = (void *)((int)handle);
	DisconnectNamedPipe(hPipe); 
}


JNIEXPORT jint JNICALL Java_pipe_NamedPipeInputStream_readBytes
  (JNIEnv *env, jobject obj, jint handle, jbyteArray buffer, jint len)
{
	//jbyte *jBuffer = env->GetByteArrayElements(buffer,NULL);
	char *cBuffer = new char[len+1];

	DWORD cbBytesRead;

	HANDLE hPipe = (void *)((int)handle);
	BOOL fSuccess = ReadFile( 
		hPipe,        // handle to pipe 
		cBuffer,    // buffer to receive data 
		len, // size of buffer 
		&cbBytesRead, // number of bytes read 
		NULL);        // not overlapped I/O 
	if (! fSuccess && GetLastError() != ERROR_MORE_DATA)
	{
		delete cBuffer;
		return -1;
	}
	env->SetByteArrayRegion(buffer,0,cbBytesRead,(const jbyte *)cBuffer);
	delete cBuffer;
	return cbBytesRead;
}


JNIEXPORT jobject JNICALL Java_pipe_NamedPipeInputStream_readPipe
  (JNIEnv *env, jobject obj, jint handle, jbyteArray buffer, jint len)
{
	//jbyte *jBuffer = env->GetByteArrayElements(buffer,NULL);
	char *cBuffer = new char[len+1];

	DWORD cbBytesRead;

	HANDLE hPipe = (void *)((int)handle);
	BOOL fSuccess = ReadFile( 
		hPipe,        // handle to pipe 
		cBuffer,    // buffer to receive data 
		len, // size of buffer 
		&cbBytesRead, // number of bytes read 
		NULL);        // not overlapped I/O 

	DWORD le = GetLastError();

	if (! fSuccess && le != ERROR_MORE_DATA)
	{
		jclass jclass = env->FindClass("pipe/ReadPipeInfo");   
		jfieldID moreData = env->GetFieldID(jclass,"more","Z");   
		jfieldID count = env->GetFieldID(jclass,"count","I");  

		jmethodID mID = env->GetMethodID(jclass, "<init>", "()V");
		jobject info = env->NewObject(jclass,mID); 
		delete cBuffer;
		env->SetBooleanField(info,moreData,false);
		env->SetIntField(info,count,-1);
		env->DeleteLocalRef(jclass);
		return info;
	}

	jclass jclass = env->FindClass("pipe/ReadPipeInfo");   
    jfieldID moreData = env->GetFieldID(jclass,"more","Z");   
    jfieldID count = env->GetFieldID(jclass,"count","I");  
  
	jmethodID mID = env->GetMethodID(jclass, "<init>", "()V");
	jobject info = env->NewObject(jclass,mID); 

	
	env->SetByteArrayRegion(buffer,0,cbBytesRead,(const jbyte *)cBuffer);
	delete cBuffer;
	    
	if(le == ERROR_MORE_DATA){
		env->SetBooleanField(info,moreData,true);
	}else{
		env->SetBooleanField(info,moreData,false);
	}
	
	env->SetIntField(info,count,cbBytesRead);
    //env->SetShortField(info,count,10);  
	env->DeleteLocalRef(jclass);
      
    return info;   
}


JNIEXPORT void JNICALL Java_pipe_NamedPipeOutputStream_writeBytes
  (JNIEnv *env, jobject obj, jint handle, jbyteArray buffer, jint len)
{
	jbyte *jBuffer = env->GetByteArrayElements(buffer,NULL);
	
	DWORD cbWritten;
	HANDLE hPipe = (void *)((int)handle);
	// Write to the pipe. 
	BOOL fSuccess = WriteFile( 
		hPipe,        // handle to pipe 
		jBuffer,      // buffer to write from 
		len, // number of bytes to write 
		&cbWritten,   // number of bytes written 
		NULL);        // not overlapped I/O
}


JNIEXPORT void JNICALL Java_pipe_NamedPipeOutputStream_writeBytesOff
  (JNIEnv *env, jobject obj, jint handle, jbyteArray buffer, jint off, jint len)
{
	jbyte *jBuffer = env->GetByteArrayElements(buffer,NULL);
	
	DWORD cbWritten;
	HANDLE hPipe = (void *)((int)handle);
	// Write to the pipe. 
	BOOL fSuccess = WriteFile( 
		hPipe,        // handle to pipe 
		jBuffer+off,      // buffer to write from 
		len, // number of bytes to write 
		&cbWritten,   // number of bytes written 
		NULL);        // not overlapped I/O
}


JNIEXPORT void JNICALL Java_pipe_NamedPipeOutputStream_flush
  (JNIEnv *env, jobject obj, jint handle)
{
	HANDLE hPipe = (void *)((int)handle);
	BOOL flag = FlushFileBuffers(hPipe);
}
 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值