项目代码:https://github.com/VincentWei95/ndk
Android JNI开发系列:第一章 JNIEnv接口指针
Android JNI开发系列:第三章 对引用数据类型的操作
Android JNI开发系列:第八章 POSIX Socket API 面向连接的通信
Android JNI开发系列:第九章 POSIX Socket API 无连接的通信
Android JNI开发系列:第十章 POSIX Socket API 本地通信
1 实现原生UDP Server
1.1 创建一个Socket
socket用一个名为 socket
描述符的整数表示。除了创建socket的函数外,Socket API函数需要有效的socket描述符才能正常工作。可以用 socket
函数来创建socket。
// 创建socket成功会返回相关socket描述符,否则返回-1且全局变量errno被相应地设置成错误值
int socket(int domain, int type, int protocol);
参数说明:
-
int domain:指定将会产生通信的socket域,并且选择将用到的协议族。Android支持以下协议族:
-
PF_LOCAL:主机内部通信协议族,该协议族使物理上运行在同一台设备上的应用程序可以用Socket APIs彼此通信
-
PF_INET:Internet第4版协议族,该协议族使应用程序可以与网络上其他地方运行的应用程序进行通信
-
-
int type:指定通信的语义。支持以下几种主要的socket类型:
-
SOCK_STREAM:提供使用TCP协议的、面向连接的通信Stream socket类型
-
SOCK_DGRAM:提供使用UDP协议的、无连接的通信的Datagram socket类型
-
-
int protocol:指定将会用到的协议。对于大多数协议族和类型来说,只能使用一个协议。为了选择默认协议,该参数可以设为0
1.2 从Socket接收数据报
用 recvfrom
函数而不是之前用过的 recv
函数实现从UDP socket中接收数据。
recvfrom
函数是一个阻塞函数,如果没从给定的socket接收到数据,它会使调用进程进入挂起状态,直到接收到可用数据。
// 如果成功返回从socket处接收到的字节数,否则返回-1且全局变量errno将被设置为相应的错误值
ssize_t recvfrom(int socketDescriptor, void* buffer, size_t bufferLength, int flags, struct sockaddr* address, socklen_t* addressLength);
参数说明:
-
int socketDescriptor:指定应用程序想要从中接收数据的socket实例
-
void* buffer:指向内存地址的指针,该内存用来保存从socket接收的数据
-
size_t bufferLength:指定缓冲区的大小,
recvfrom
函数只会向缓冲区写入该参数指定大小的内容然后返回 -
int flags:指定接收所需要的额外标志
-
struct sockaddr* address:指定一个地址结构,用于保存客户端发送包的协议地址。如果应用程序不需要该信息,将该信息置为NULL
-
socklen_t* addressLength:指定客户端要写入的协议地址的内存空间大小,如果应用程序不需要该信息,将该参数置为NULL
1.3 向Socket发送数据报
给UDP socket发送数据也是通过 sendto
函数而不是 send
函数实现。
sendto
函数是一个阻塞函数,如果socket在忙着发送数据,它会使调用进程进入挂起状态直到socket可以传输数据。
// 如果成功返回传送的字节数,否则返回-1且全局变量errno将被设置为相应的错误
ssize_t sendto(int socketDescriptor, const void* buffer, size_t bufferSize, int flags, const struct sockaddr* address, socklen_t addressLength);
参数说明:
-
int socketDescriptor:指定应用程序想要向其发送数据的socket实例
-
const void* buffer:指向内存是给定的socket发送数据的目的地
-
size_t bufferSize:指定缓冲区大小。
sendto
函数只会向缓冲区传输该参数所指定大小的数据然后返回 -
int flags:指定发送所需要的额外标志
-
const struct sockaddr* address:指定目标服务器的协议地址
-
socklen_t addressLength:传递给函数的协议地址结构的大小