JNI 和 socket api

时间:2021-09-12 08:38:15

1、JavaVM 和 JNIEnv
JNIEnv是一个与线程相关的变量,不同线程的JNIEnv彼此独立。
JavaVM是虚拟机在JNI层的代表,在一个虚拟机进程中只有一个JavaVM,因此该进程的所有线程都可以使用这个JavaVM。
当后台线程需要调用JNI native时,在native库中使用全局变量保存JavaVM尤为重要,这样使得后台线程能通过JavaVM获得JNIEnv。

// e.g
JNIEnv *env = NULL;
if(0 == gVm-> AttachCurrentThread(&env, NULL)){}

2、Socket API: 面向连接的通信
int socket(int domain, int type, int protocol);
创建一个socket
domain: 指定将会产生通信的socket域,并选择将要用到的协议簇:
PF_LOCAL:主机内部通信协议簇,该协议簇使物理上运行的同一台设备上的应用程序可以用Socket APIs彼此通信;
PF_INET: Internet第4版协议簇,该协议簇使应用程序可以与网络上的其他地方运行的应用程序进行通信;

type:指定通信的语义,支持一下几种主要的socket类型。
SOCKET_STREAM: 通过使用TCP协议的、面向面向连接的通信Stream Socket类型;
SOCKET_DGRAM:提供使用UDP协议的,无连接的通信Datagram Socket类型。

protocol: 指定将会用到的协议;

int bind(int socketDescriptor, const struct sockaddr *address, socklen_t addressLength);
将socket与一个地址绑定
socket描述符:指定将绑定到指定地址的socket实例;
address:指定socket被绑定的协议地址;
address length:指定传递给函数的协议地址结构的大小;

int listen(int socketDescriptor, int backlog);
监听socket
socket 描述符,
backlog:指定保存挂起的输入连接的队列大小。

int accept(int socketDescriptor, struct sockaddr *address, socklen_t * addressLength);
用来显示的将输入连接从监听队列取出并接受它;
socket描述符;
address:一个指向客户协议地址的指针,可以为NULL;
addressLength: 客户协议大小,可以为NULL;

ssize_t recv(int socketDescriptor, void *buffer, size_t bufferLength, int flags);
从socket 接收数据
socket描述符;
buffer: 指向内存地址,用来保存从socket接收数据;
bufferLength:缓冲区大小;
flags:接收所需要的额外标志;

ssize_t recvfrom(int socketDescriptor, void *buffer, size_t bufferLength, int flags, struct sockaddr *address, socklen_t *addressLength);
使用recvfrom从udp socket中接收数据;
socketDescriptor;
buffer: 指向内存地址的指针;
bufferLength: 缓存区大小
flags: 额外标记
address:用于保存客户端发送的协议地址,可以为NULL
addressLength: 指定客户端要写入的协议地址的内存大小,可以为NULL;

ssize_t send(int socketDescriptor, void *buffer, size_t bufferLength, int flags);
想socket发送数据
socket描述符;
buffer: 指向内存地址;
bufferLength:长度;
flags:发送所需要的额外标志;

ssize_t sendto(int socketDescriptor, const void *buffer, size_t bufferSize, int flags, const struct sockaddr *address, socklen_t, addressLength);‘’
udp发送函数
socketDescriptor;
buffer: 缓冲区指针
bufferLength:缓冲区大小;
flags: 额外标记
address:协议地址
addressLength:协议地址大小

int connect(int socketDescriptor, const struct sockaddr *addr, socklen_t addressLength);
通过提供协议地址来连接socket和server socket,
socket描述符;
address: socket要连接的协议地址;
addressLength: 所提供的地址结构的长度;

异步IO
sys/select.h
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
nfds:为最高编号的描述符+1,select函数将监控nfds指定数量的描述符。
readfds:设置将被监控可读性的描述符列表集;
writefs:设置将被监控可写性的描述符列表集;
exceptfds:设置将被监控任何类型错误的描述符列表集;
timeout: 指定为了完成选择而阻塞当前进程的最大时间间隔,可以为NULL;

参考:《Android C++高级编程》 8/9/10章