讲比较重要的代码放到native层是比较好的做法。如果你有需求需要把socket通信的部分封装的jni中实现,那么本文可做参考。
代码思路
1.总共实现三个native方法:
public native void initSocket(String ip,int port);
public native void closeSocket();
public native void sendData(byte[] buffer);
2.initSocket中创建套接字,并连接指定ip和端口的服务器,连接成功后创建线程,由于总是客户端发起请求,因此,当有数据发送给服务断后,唤醒该线程,阻塞读取来自服务端的消息。然后将读到的消息发送到java层,这里只需从native调用java的方法,并把读到的数据传入即可。
3.sendData送来发送数据,它不在本地另开辟线程,需要在java层中开辟线程后调用它向服务器发送请求。
需要注意的点
1.c++中,子线需要首先调用javavm->AttachCurrentThread(&SocketDataDealThread::env,NULL);来获得JNIEnv *的变量,然后使用该变量做进一步操作。
2.c++中跨线程使用JNI创建的变量时,要将其创建为全局引用:
gObj = env->NewGlobalRef(thiz);
mSTh = new SocketDataDealThread(socketFd,gObj);
创建工程
android studio2.2版本开始完善了对C/C++ ,请参考开发者文档:向您的项目添加 C 和 C++ 代码。文档是中文的。
本文的工程如图所示:
若感兴趣,本文的源码请从这里下载:(免积分的)AndoridJniSocket.zip
本文运行结果展示:
操作方式
1.输入Ip和端口号
2.点INIT CLIENT按钮,连接服务器成功后,INIT CLIENT会变成CONNECTED字样,并且按钮无法点击,背景编程深灰色。
3.输入发送内容并点击发送按钮,会看到read:后面出现了你发送的内容。这是因为服务器目前只会将它收到的数据原样返回。
4.点击CLOSE按钮断开连接。
服务器代码
服务器端的代码比较简单,线贴出来:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class SockeTest {
public static void main(String[] args) {
boolean isgo=true;
int len;
// TODO Auto-generated method stub
/**
* 基于TCP协议的Socket通信,实现用户登录,服务端
*/
System.out.println("start ...");
//1、创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(10010);
//2、调用accept()方法开始监听,等待客户端的连接
Socket socket = null;
InputStream is = null;
InputStreamReader isr = null;
OutputStream os = null;
BufferedReader br = null;
while(isgo){
System.out.println("start accept");
socket = serverSocket.accept();
System.out.println("after accept");
//3、获取输入流,并读取客户端信息
is = socket.getInputStream();
os = socket.getOutputStream();
isr =new InputStreamReader(is);
br =new BufferedReader(isr);
String info =null;
System.out.println("before read");
byte[] bbbb = new byte[100];
while((len = is.read(bbbb))>0){
System.out.println(String.valueOf(bbbb));
byte[] bbbbb = new byte[len];
System.arraycopy(bbbb, 0,bbbbb, 0, len);
os.write(bbbbb);
os.flush();
}
System.out.println("someone connect me");
}
//5、关闭资源
br.close();
isr.close();
is.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户端
MainActivity.java
import android.graphics.Color;
import android.os.Handler;
import android.os.Message;