NDK 开发之 Socket 编程

前言

socket 作为开发人员必须掌握的一个技能,今天我在Android中使用到了.并且写出了一个小例子,本片文章作为一个记录

Tcp连接

实现流程盗用一张图:
这里写图片描述
流程中名称都是每一个步骤需要调用的函数名称

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <stdlib.h>
#include <stdio.h>
#include <android/log.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <stddef.h>
#include <arpa/inet.h>
#include <unistd.h>
/* Header for class com_move_ndk1_NativeClass1 */

#ifndef _Included_com_move_ndk1_NativeClass1
#define _Included_com_move_ndk1_NativeClass1
#ifdef __cplusplus
extern "C" {
#endif

static int serverSocket;
static int clientSocket;

/*
 * Class:     com_move_ndk1_NativeClass1
 * Method:    test
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_move_ndksocket_MainAct_server
        (JNIEnv *env, jclass jc) {

    int tcpSocket = socket(PF_INET, SOCK_STREAM, 0);

    if (tcpSocket == -1) {
        return (*env)->NewStringUTF(env, "socket失败");
    }

    struct sockaddr_in address;

    memset(&address, 0, sizeof(address));
    address.sin_family = PF_INET;

    address.sin_addr.s_addr = htonl(INADDR_ANY);
    address.sin_port = htons(12345);

    int bindState = bind(tcpSocket, (struct sockaddr_in *) &address, sizeof(address));

    if (bindState == -1) {
        return (*env)->NewStringUTF(env, "bind失败");
    }

    int listenState = listen(tcpSocket, 1);
    if (listenState == -1) {
        return (*env)->NewStringUTF(env, "listen失败");
    }

    struct sockaddr_in accept_address;
    socklen_t addressLength = sizeof(address);

    int acceptState = accept(tcpSocket, &accept_address, &addressLength);
    if (acceptState == -1) {
        return (*env)->NewStringUTF(env, "accept失败");
    }

    __android_log_print(ANDROID_LOG_ERROR, "accept", "accept");

    serverSocket = acceptState;

    char arr[10];

    int recvSize = recv(serverSocket, arr, 10, 0);

    if (recvSize <= 0) {
        return (*env)->NewStringUTF(env, "recv失败");
    }

    int lastOne = arr[recvSize - 1];

    __android_log_print(ANDROID_LOG_ERROR, "socket", "lastOne = %d\n", lastOne);
    __android_log_print(ANDROID_LOG_ERROR, "socket", "recvSize = %d\n", recvSize);

    return (*env)->NewStringUTF(env, arr);

}

JNIEXPORT jstring JNICALL Java_com_move_ndksocket_MainAct_client
        (JNIEnv *env, jclass jc) {

    int tcpSocket = socket(PF_INET, SOCK_STREAM, 0);

    if (tcpSocket == -1) {
        return (*env)->NewStringUTF(env, "socket失败");
    }

    struct sockaddr_in address;

    memset(&address, 0, sizeof(address));
    address.sin_family = PF_INET;

    int inet_atonSstate = inet_aton("127.0.0.1", &address.sin_addr.s_addr);
    if (inet_atonSstate == -1) {
        return (*env)->NewStringUTF(env, "inet_aton失败");
    }

    address.sin_port = htons(12345);

    int connectState = connect(tcpSocket, &address, sizeof(address));
    if (connectState == -1) {
        return (*env)->NewStringUTF(env, "connect失败");
    }

    clientSocket = tcpSocket;

    return (*env)->NewStringUTF(env, "成功");

}

JNIEXPORT jint JNICALL Java_com_move_ndksocket_MainAct_send
        (JNIEnv *env, jclass jc) {

    char charData[] = "hello";

    send(clientSocket, charData, sizeof(charData) / sizeof(char), 0);

    close(clientSocket);

    return sizeof(charData) / sizeof(char);

}

#ifdef __cplusplus
}
#endif
#endif

上述写了三个方法,第一个方法监听了12345端口等待客户端连接,accept方法用于阻塞并且等待用户连接,第二个方法用于连接,并且第一个方法中接受连接,第三个方法发送了一定的数据,第一个方法的recv阻塞方法中获取到数据

Udp连接

JNIEXPORT jstring JNICALL Java_com_move_ndksocket_MainAct_udpServer
        (JNIEnv *env, jclass jc) {


    int udpSocket = socket(PF_INET, SOCK_DGRAM, 0);

    if (udpSocket == -1) {
        return (*env)->NewStringUTF(env, "udp:socket失败");
    }

    __android_log_print(ANDROID_LOG_ERROR, "socket", "udpSocket\n");

    struct sockaddr_in address;

    memset(&address, 0, sizeof(address));
    address.sin_family = PF_INET;

    address.sin_addr.s_addr = htonl(INADDR_ANY);
    address.sin_port = htons(12346);

    int bindState = bind(udpSocket, &address, sizeof(address));

    if (bindState == -1) {
        return (*env)->NewStringUTF(env, "bind失败");
    }

    char cc[100];

    struct sockaddr_in recvfromAddress;
    memset(&recvfromAddress, 0, sizeof(recvfromAddress));
    socklen_t l = sizeof(struct sockaddr_in);

    ssize_t recvSize = recvfrom(udpSocket, cc, 8, 0, &recvfromAddress, &l);

    __android_log_print(ANDROID_LOG_ERROR, "socket", "recvSize\n");
    if (recvSize == -1) {
        return (*env)->NewStringUTF(env, "udp接受失败");
    }

    return (*env)->NewStringUTF(env, cc);

}

JNIEXPORT jstring JNICALL Java_com_move_ndksocket_MainAct_udpSend
        (JNIEnv *env, jclass jc) {

    int udpSocket = socket(PF_INET, SOCK_DGRAM, 0);

    if (udpSocket == -1) {
        return (*env)->NewStringUTF(env, "udp:socket失败");
    }

    struct sockaddr_in address;
    memset(&address, 0, sizeof(address));

    inet_aton("127.0.0.1", &(address.sin_addr));

    address.sin_port = htons(12346);

    sendto(udpSocket, "udpHello", 9, 0, &address, sizeof(address));

    return (*env)->NewStringUTF(env, "udp:发送成功");

}

源码在我的github上存放着,有需要的可以下载一下

ndkSocket下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值