`
hellbaby666
  • 浏览: 12073 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

JNI入门教程之HelloWorld篇

 
阅读更多

资料引用:http://www.knowsky.com/363050.html

本文讲述如何使用JNI技术实现HelloWorld,目的是让读者熟悉JNI的机制并编写第一个HelloWorld程序。

JavaNativeInterfaceJNI)是Java语言的本地编程接口,是J2SDK的一部分。在java程序中,我们可以通过JNI实现一些用java语言不便实现的功能。通常有以下几种情况我们需要使用JNI来实现。

标准的java类库没有提供你的应用程序所需要的功能,通常这些功能是平台相关的

你希望使用一些已经有的类库或者应用程序,而他们并非用java语言编写的

程序的某些部分对速度要求比较苛刻,你选择用汇编或者c语言来实现并在java语言中调用他们

在《java核心技术》中,作者提到JNI的时候,建议不到万不得已不要使用JNI技术,一方面它需要你把握更多的知识才可以驾驭,一方面使用了JNI你的程序就会丧失可移植性。在本文我们跳过JNI的底层机制,读者最好先把它想象为本地代码和java代码的粘合剂。关系如下图所示:

下面我们开始编写HelloWorld程序,由于涉及到要编写c/c++代码因此我们会在开发中使用MicrosoftVC++工具。

编写java代码

我们在硬盘上建立一个hello目录作为我们的工作目录,首先我们需要编写自己的java代码,在java代码中我们会声明native方法,代码非常简单。如下所示

classHelloWorld

{

publicnativevoiddisplayHelloWorld();

static{

System.loadLibrary("hello");

}

publicstaticvoidmain(String[]args){

newHelloWorld().displayHelloWorld();

}

}

注重我们的displayHelloWorld()方法的声明,它有一个要害字native,表明这个方法使用java以外的语言实现。方法不包括实现,因为我们要用c/c++语言实现它。注重System.loadLibrary("hello")这句代码,它是在静态初始化块中定义的,系统用来装载hello共享库,这就是我们在后面生成的hello.dll(假如在其他的操作系统可能是其他的形式,比如hello.so

编译java代码

javacHelloWorld.java生成HelloWorld.class文件

创建.h文件

这一步中我们要使用javah命令生成.h文件,这个文件要在后面的c/c++代码中用到,我们运行

javahHelloWorld。这样我们可以看到在相同目录下生成了一个HelloWorld.h文件,文件内容如下

在此我们不对他进行太多的解释。

/*DONOTEDITTHISFILE-itismachinegenerated*/

#include<jni.h>

/*HeaderforclassHelloWorld*/

#ifndef_Included_HelloWorld

#define_Included_HelloWorld

#ifdef__cplusplus

extern"C"{

#endif

/*

*Class:HelloWorld

*Method:displayHelloWorld

*Signature:()V

*/

JNIEXPORTvoidJNICALLJava_HelloWorld_displayHelloWorld

(JNIEnv*,jobject);

#ifdef__cplusplus

}

#endif

#endif

编写本地实现代码

在这部分我们要用C/C++语言实现java中定义的方法,我们在VC++中新建一个Project,然后创建一个HelloWorldImp.cpp文件,内容如下

#include<jni.h>

#include"HelloWorld.h"

#include<stdio.h>

JNIEXPORTvoidJNICALL

Java_HelloWorld_displayHelloWorld(JNIEnv*env,jobjectobj)

{

printf("Helloworld!\n");

return;

}

注重我们这里includejni.h和刚才得到的HelloWorld.h文件。因此你要在VC++里面设置好,jni.hJAVA_HOME/include里面。编译通过后再生成hello.dll文件。

运行java程序

把上面生成的hello.dll文件复制到我们的工作目录,这时候我们的目录中包括HelloWorld.javaHelloWorld.classhello.dll文件。运行javaHelloWorld命令,则可在控制台看到Helloworld

的输出了。

-

资料引用:http://www.knowsky.com/363050.html

Java:JNI完全手册时间:2007-02-1000:00:00来源:作者:

最近在公司里做了一个手机的项目,需要JAVA程序在发送短信的时候和第三方的短信服务器连接。短信接口是用C++写的。琢磨了三天,大致搞懂了JNI的主体部分。先将心得整理,希望各位朋友少走弯路。

首先引用一篇文章,介绍一个简单的JNI的调用的过程。

JAVA以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI

JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。

简单介绍及应用如下:

一、JAVA中所需要做的工作

JAVA程序中,首先需要在类中声明所调用的库名称,如下:

static{

System.loadLibrary(“goodluck”);

}

在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。

还需对将要调用的方法做本地声明,关键字为native。且只需要声明,而不需要具体实现。如下:

publicnativestaticvoidset(inti);

publicnativestaticintget();

然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件。

例如程序testdll.java,内容为:

publicclasstestdll

{

static

{

System.loadLibrary(\"goodluck\");

}

publicnativestaticintget();

publicnativestaticvoidset(inti);

publicstaticvoidmain(String[]args)

{

testdlltest=newtestdll();

test.set(10);

System.out.println(test.get());

}

}

用javactestdll.java编译它,会生成testdll.class。

再用javahtestdll则会在当前目录下生成testdll.h文件,这个文件需要被C/C++程序调用来生成所需的库文件。

二、C/C++中所需要做的工作

对于已生成的.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即可。再把库文件拷贝到JAVA程序的路径下面,就可以用JAVA调用C/C++所实现的功能了。

接上例子。我们先看一下testdll.h文件的内容:

/*DONOTEDITTHISFILE-itismachinegenerated*/

#include

/*Headerforclasstestdll*/

#ifndef_Included_testdll

#define_Included_testdll

#ifdef__cplusplus

extern\"C\"{

#endif

/*

*Class:testdll

*Method:get

*Signature:()I

*/

JNIEXPORTjintJNICALLJava_testdll_get(JNIEnv*,jclass);

/*

*Class:testdll

*Method:set

*Signature:(I)V

*/

JNIEXPORTvoidJNICALLJava_testdll_set(JNIEnv*,jclass,jint);

#ifdef__cplusplus

}

#endif

#endif

在具体实现的时候,我们只关心两个函数原型

JNIEXPORTjintJNICALLJava_testdll_get(JNIEnv*,jclass);

JNIEXPORTvoidJNICALLJava_testdll_set(JNIEnv*,jclass,jint);

这里JNIEXPORTJNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使JAVAint类型与本地的int沟通的一种类型,我们可以视而不见,就当做int使用。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*jclass我们一般没有必要去碰它。

好,下面我们用testdll.cpp文件具体实现这两个函数:

#include\"testdll.h\"

inti=0;

JNIEXPORTjintJNICALLJava_testdll_get(JNIEnv*,jclass)

{

returni;

}

JNIEXPORTvoidJNICALLJava_testdll_set(JNIEnv*,jclass,jintj)

{

i=j;

}

编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与JAVA中需要调用的一致,这里就是goodluck.dll。把goodluck.dll拷贝到testdll.class的目录下,javatestdll运行它,就可以观察到结果了。

我的项目比较复杂,需要调用动态链接库,这样在JNI传送参数到C程序时,需要对参数进行处理转换。才可以被C程序识别。

大体程序如下:

publicclassSendSMS{

static

{

System.out.println(System.getProperty(\"java.library.path\"));

System.loadLibrary(\"sms\");

}

publicnativestaticintSmsInit();

publicnativestaticintSmsSend(byte[]mobileNo,byte[]smContent);

}

在这里要注意的是,path里一定要包含类库的路径,否则在程序运行时会抛出异常:

java.lang.UnsatisfiedLinkError:nosmsinjava.library.path

atjava.lang.ClassLoader.loadLibrary(ClassLoader.java:1491)

atjava.lang.Runtime.loadLibrary0(Runtime.java:788)

atjava.lang.System.loadLibrary(System.java:834)

atcom.mobilesoft.sms.mobilesoftinfo.SendSMS.(SendSMS.java:14)

atcom.mobilesoft.sms.mobilesoftinfo.test.main(test.java:18)

Exceptioninthread\"main\"

指引的路径应该到.dll文件的上一级,如果指到.dll,则会报:

java.lang.UnsatisfiedLinkError:C:\sms.dll:Can'tfinddependentlibraries

atjava.lang.ClassLoader$NativeLibrary.load(NativeMethod)

atjava.lang.ClassLoader.loadLibrary0(ClassLoader.java:1560)

atjava.lang.ClassLoader.loadLibrary(ClassLoader.java:1485)

atjava.lang.Runtime.loadLibrary0(Runtime.java:788)

本篇教程来源于完全教程网原文链接:http://www.pcstu.com/program/Java/jc/20070210/19659.html

JNI完全手册

作者:dankes…日期:2005-11-1510:49:09来源:不详点击:评论

  最近在公司里做了一个手机的项目,需要JAVA程序在发送短信的时候和第三方的短信服务器连接。短信接口是用C++写的。琢磨了三天,大致搞懂了JNI的主体部分。先将心得整理,希望各位朋友少走弯路。
  首先引用一篇文章,介绍一个简单的JNI的调用的过程。
  JAVA以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI
  JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。
  简单介绍及应用如下:
  一、JAVA中所需要做的工作
  在JAVA程序中,首先需要在类中声明所调用的库名称,如下:
  static{
  System.loadLibrary(“goodluck”);
  }

  在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。
  还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具体实现。如下:
  publicnativestaticvoidset(inti);
  publicnativestaticintget();
  然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件。
  例如程序testdll.java,内容为:
  publicclasstestdll
  {
  static
  {
  System.loadLibrary("goodluck");
  }
  publicnativestaticintget();
  publicnativestaticvoidset(inti);
  publicstaticvoidmain(String[]args)
  {
  testdlltest=newtestdll();
  test.set(10);
  System.out.println(test.get());
  }
  }

  用javactestdll.java编译它,会生成testdll.class
  再用javahtestdll,则会在当前目录下生成testdll.h文件,这个文件需要被C/C++程序调用来生成所需的库文件。
  二、C/C++中所需要做的工作
  对于已生成的.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即可。再把库文件拷贝到JAVA程序的路径下面,就可以用JAVA调用C/C++所实现的功能了。
  接上例子。我们先看一下testdll.h文件的内容:
  /*DONOTEDITTHISFILE-itismachinegenerated*/
  #include
  /*Headerforclasstestdll*/
  #ifndef_Included_testdll
  #define_Included_testdll
  #ifdef__cplusplus
  extern"C"{
  #endif
  /*
  *Class:testdll
  *Method:get
  *Signature:()I
  */
  JNIEXPORTjintJNICALLJava_testdll_get(JNIEnv*,jclass);
  /*
  *Class:testdll
  *Method:set
  *Signature:(I)V
  */
  JNIEXPORTvoidJNICALLJava_testdll_set(JNIEnv*,jclass,jint);
  #ifdef__cplusplus
  }
  #endif
  #endif
  在具体实现的时候,我们只关心两个函数原型
  JNIEXPORTjintJNICALLJava_testdll_get(JNIEnv*,jclass);
  JNIEXPORTvoidJNICALLJava_testdll_set(JNIEnv*,jclass,jint);
  这里JNIEXPORTJNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使JAVAint类型与本地的int沟通的一种类型,我们可以视而不见,就当做int使用。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*jclass我们一般没有必要去碰它。
  好,下面我们用testdll.cpp文件具体实现这两个函数:
  #include"testdll.h"
  inti=0;
  JNIEXPORTjintJNICALLJava_testdll_get(JNIEnv*,jclass)
  {
  returni;
  }
  JNIEXPORTvoidJNICALLJava_testdll_set(JNIEnv*,jclass,jintj)
  {
  i=j;
  }
  编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与JAVA中需要调用的一致,这里就是goodluck.dll。把goodluck.dll拷贝到testdll.class的目录下,javatestdll运行它,就可以观察到结果了。
  我的项目比较复杂,需要调用动态链接库,这样在JNI传送参数到C程序时,需要对参数进行处理转换。才可以被C程序识别。
  大体程序如下:
  publicclassSendSMS{
  static
  {
  System.out.println(System.getProperty("java.library.path"));
  System.loadLibrary("sms");
  }
  publicnativestaticintSmsInit();
  publicnativestaticintSmsSend(byte[]mobileNo,byte[]smContent);
  }
  在这里要注意的是,path里一定要包含类库的路径,否则在程序运行时会抛出异常:
  java.lang.UnsatisfiedLinkError:nosmsinjava.library.path
  atjava.lang.ClassLoader.loadLibrary(ClassLoader.java:1491)
  atjava.lang.Runtime.loadLibrary0(Runtime.java:788)
  atjava.lang.System.loadLibrary(System.java:834)
  atcom.mobilesoft.sms.mobilesoftinfo.SendSMS.(SendSMS.java:14)
  atcom.mobilesoft.sms.mobilesoftinfo.test.main(test.java:18)
  Exceptioninthread"main"
  指引的路径应该到.dll文件的上一级,如果指到.dll,则会报:
  java.lang.UnsatisfiedLinkError:C:\sms.dll:Can'tfinddependentlibraries
  atjava.lang.ClassLoader$NativeLibrary.load(NativeMethod)
  atjava.lang.ClassLoader.loadLibrary0(ClassLoader.java:1560)
  atjava.lang.ClassLoader.loadLibrary(ClassLoader.java:1485)
  atjava.lang.Runtime.loadLibrary0(Runtime.java:788)
  atjava.lang.System.loadLibrary(System.java:834)
  atcom.mobilesoft.sms.mobilesoftinfo.SendSMS.(SendSMS.java:14)
  atcom.mobilesoft.sms.mobilesoftinfo.test.main(test.java:18)
  Exceptioninthread"main"


  通过编译,生成com_mobilesoft_sms_mobilesoftinfo_SendSMS.h头文件。(建议使用Jbuilder进行编译,操作比较简单!)这个头文件就是JavaC之间的纽带。要特别注意的是方法中传递的参数jbyteArray,这在接下来的过程中会重点介绍。
  /*DONOTEDITTHISFILE-itismachinegenerated*/
  #include
  /*Headerforclasscom_mobilesoft_sms_mobilesoftinfo_SendSMS*/
  #ifndef_Included_com_mobilesoft_sms_mobilesoftinfo_SendSMS
  #define_Included_com_mobilesoft_sms_mobilesoftinfo_SendSMS
  #ifdef__cplusplus
  extern"C"{
  #endif
  /*
  *Class:com_mobilesoft_sms_mobilesoftinfo_SendSMS
  *Method:SmsInit
  *Signature:()I
  */
  JNIEXPORTjintJNICALLJava_com_mobilesoft_sms_mobilesoftinfo_SendSMS_SmsInit
  (JNIEnv*,jclass);
  /*
  *Class:com_mobilesoft_sms_mobilesoftinfo_SendSMS
  *Method:SmsSend
  *Signature:([B[B)I
  */
  JNIEXPORTjintJNICALLJava_com_mobilesoft_sms_mobilesoftinfo_SendSMS_SmsSend
  (JNIEnv*,jclass,jbyteArray,jbyteArray);
  #ifdef__cplusplus
  }
  #endif
  #endif

  对于我要调用的C程序的动态链接库,C程序也要提供一个头文件,sms.h。这个文件将要调用的方法罗列了出来。
  /*
  *SMSAPI
  *Author:yippit
  *Date:2004.6.8
  */
  #ifndefMCS_SMS_H
  #defineMCS_SMS_H
  #defineDLLEXPORT__declspec(dllexport)
  /*smsstorage*/
  #defineSMS_SIM0
  #defineSMS_MT1
  /*smsstates*/
  #defineSMS_UNREAD0
  #defineSMS_READ1
  /*smstype*/
  #defineSMS_NOPARSE-1
  #defineSMS_NORMAL0
  #defineSMS_FLASH1
  #defineSMS_MMSNOTI2
  typedefstructtagSmsEntry{
  intindex;/*index,startfrom1*/
  intstatus;/*read,unread*/
  inttype;/*-1-can'tparser0-normal,1-flash,2-mms*/
  intstorage;/*SMS_SIM,SMS_MT*/
  chardate[24];
  charnumber[32];
  chartext[144];
  }SmsEntry;
  DLLEXPORTintSmsInit(void);
  DLLEXPORTintSmsSend(char*phonenum,char*content);
  DLLEXPORTintSmsSetSCA(char*sca);
  DLLEXPORTintSmsGetSCA(char*sca);
  DLLEXPORTintSmsSetInd(intind);
  DLLEXPORTintSmsGetInd(void);
  DLLEXPORTintSmsGetInfo(intstorage,int*max,int*used);
  DLLEXPORTintSmsSaveFlash(intflag);
  DLLEXPORTintSmsRead(SmsEntry*entry,intstorage,intindex);
  DLLEXPORTintSmsDelete(intstorage,intindex);
  DLLEXPORTintSmsModifyStatus(intstorage,intindex);/*unread->read*/
  #endif

  在有了这两个头文件之后,就可以进行C程序的编写了。也就是实现对JNI调用的两个方法。在网上的资料中,由于调用的方法实现的都比较简单,(大多是打印字符串等)所以避开了JNI中最麻烦的部分,也是最关键的部分,参数的传递。由于JavaC的编码是不同的,所以传递的参数是要进行再处理,否则C程序是会对参数在编译过程中提出警告,例如;warningC4024:'SmsSend':differenttypesforformalandactualparameter2等。
  Sms.c的程序如下:
  #include"sms.h"
  #include"com_mobilesoft_sms_mobilesoftinfo_SendSMS.h"
  JNIEXPORTjintJNICALLJava_com_mobilesoft_sms_mobilesoftinfo_SendSMS_SmsInit(JNIEnv*env,jclassjobject)
  {
  returnSmsInit();
  }

  JNIEXPORTjintJNICALLJava_com_mobilesoft_sms_mobilesoftinfo_SendSMS_SmsSend(JNIEnv*env,jclassjobject,jbyteArraymobileno,jbyteArraysmscontent)
  {
  char*pSmscontent;
  //jsizetheArrayLengthJ=(*env)->GetArrayLength(env,mobileno);
  jbyte*arrayBody=(*env)->GetByteArrayElements(env,mobileno,0);
  char*pMobileNo=(char*)arrayBody;
  printf("[%s]\n",pMobileNo);
  //jsizesize=(*env)->GetArrayLength(env,smscontent);
  arrayBody=(*env)->GetByteArrayElements(env,smscontent,0);
  pSmscontent=(char*)arrayBody;
  printf("

分享到:
评论

相关推荐

    JNI入门教程之HelloWorld篇(详细版).doc

    JNI入门教程之HelloWorld篇(详细版).

    JNI入门教程之HelloWorld篇.doc

    JNI入门教程之HelloWorld篇 对于学习JNI入门很有帮助

    JNI入门之HelloWorld(一)

    JNI入门学习第一篇:HelloWorld,主要是介绍操作步骤。

    jni-helloWorld

    参考百度百科的入门demo,并对本机运行时出现的错误进行描述,相关的解决办法也注明了出外。下载后请先行阅读readme.txt

    JNI完全技术手册 带完整书签

    Chap19:JNI编程系列之基础篇... 148 System.loadLibrary("HelloWorld"); 149 JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *, jobject); 150 Chap20:JNI编程系列之中级篇(上)... 151 1. Java基本...

    JNI_HelloWorld.rar_android开发_Java_

    关于安卓的jni的入门例子,简单介绍了Java和C接口的相互调用 普通数据传输和对象传输

    JNI技术手册 c/c++调用java

    1) 编写java程序:这里以HelloWorld为例。 54 2) 编译 55 3) 生成扩展名为h的头文件 55 4) 编写本地方法实现和由javah命令生成的头文件里面声明的方法名相同的方法。 56 5) 生成动态库 56 6) 运行程序 java Hello...

    JAVA基础之理解JNI原理

    JNI是JAVA标准平台中的一个重要功能,它弥补了JAVA的与平台无关这一重大优点的不足...  程序清单1:src/com/magc/jni/HelloWorld.java 1 /** 2 * 3 */ 4 package com.magc.jni; 5 6 /** 7 * @author magc

    ScratchJavaJNI:一个演示Java JNI API示例,可用作Java Native Interface项目的起点

    Java JNI入门模板一个演示 API示例,用作Java本机接口项目的起点。 对于那些不了解它的人,JNI是JVM和本机代码指令之间的桥梁(此ScratchJNI使用C二进制文件)。 要在Linux上编译并运行(您需要正确安装gcc和JDK),...

    Android代码-各种实例库

    博客:NDK-JNI实战教程(三) 从比Hello World稍复杂点儿的NDK例子说说模板 博客文章链接---------实例代码工程 博客:facebook Fresco框架库源使用基础 博客文章链接---------实例代码工程 博客:浅谈MVP实现...

    新版Android开发教程.rar

    ----------------------------------- Android 编程基础 1 封面----------------------------------- Android 编程基础 2 开放手机联盟 --Open --Open --Open --Open Handset Handset Handset Handset Alliance ...

    Android博客来源:博客演示存储

    我的博客实例库( ##示例索引###博客:NDK-JNI实战教程(三)从比Hello World稍复杂点儿的NDK例子说说模板---------###博客:facebook Fresco框架库源使用基础---------###博客:浅谈MVP实现Android应用层开发------...

    Android 4游戏编程入门经典

     10.5.1 立方体:3d中的“helloworld”  10.5.2 一个示例  10.6 矩阵和变换  10.6.1 矩阵堆栈  10.6.2 用矩阵堆栈实现分层系统  10.6.3 木箱太阳系的简单实例  10.7 小结 第11章 3d编程技巧  11.1 准备工作 ...

    android游戏编程入门

     2.2 Android环境下的Hello World 25  2.2.1 创建项目 25  2.2.2 进一步分析项目 26  2.2.3 编写应用程序代码 27  2.3 运行和调试Android应用  程序 29  2.3.1 连接设备 29  2.3.2 创建一个Android虚拟  ...

    eclipse找不到java源码-EclipseAndroid_NDK_SDK:该存储库包含一个代表AndroidNDK+SDK混合项目的坚实

    ADT插件您应该能够编译并运行eclipse的hello-world项目 已安装Eclipse C ++插件“ CDT” [安装新软件-&gt;编程语言] 如何建造 修复项目根目录(ANDROID_SDK / ANDROID_NDK)中的符号链接以指向您自己的路径 该项目应...

    JAVA上百实例源码以及开源项目

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...

    JAVA上百实例源码以及开源项目源代码

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...

Global site tag (gtag.js) - Google Analytics