通过ndk连接套接字编程的错误

Posted

技术标签:

【中文标题】通过ndk连接套接字编程的错误【英文标题】:connect error of socket programming via ndk 【发布时间】:2012-06-24 12:02:07 【问题描述】:

实际上,我已经在 android 模拟器中使用 server.c 和 client.c 进行了测试(ps:它们都成功运行并使用 android 通用交叉编译器进行编译)。然后我走得更远,我通过jni重写客户端。但是,在这种情况下,客户端无法连接到服务器端,尽管新客户端与client.c非常相似。 经过搜索,有人提到权限很重要。但是,当我添加<uses-permission android:name="android.permission.INTERNET" />(ps:此标签在应用程序标签之外)时,问题仍然存在。 正如 logcat 所显示的,java 代码实际上调用了 c 方法,但是,为什么它的行为与 client.c 不同呢? 任何想法都会让我受益匪浅。提前致谢!

server.c:

/*  Make the necessary includes and set up the variables.  */

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>

int main()

    int server_sockfd, client_sockfd;
    int server_len, client_len;
    struct sockaddr_un server_address;
    struct sockaddr_un client_address;

/*  Remove any old socket and create an unnamed socket for the server.  */

    unlink("server_socket");
    server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

/*  Name the socket.  */

    server_address.sun_family = AF_UNIX;
    strcpy(server_address.sun_path, "server_socket");
    server_len = sizeof(server_address);
    bind(server_sockfd, (struct sockaddr *)&server_address, server_len);

/*  Create a connection queue and wait for clients.  */

    listen(server_sockfd, 5);
    while(1) 
        char ch;

        printf("server waiting\n");

/*  Accept a connection.  */

        client_len = sizeof(client_address);
        client_sockfd = accept(server_sockfd, 
            (struct sockaddr *)&client_address, &client_len);

/*  We can now read/write to client on client_sockfd.  */

        read(client_sockfd, &ch, 1);
        ch++;
        write(client_sockfd, &ch, 1);
        close(client_sockfd);
    

client.c:

/*  Make the necessary includes and set up the variables.  */

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>

int main()

    int sockfd;
    int len;
    struct sockaddr_un address;
    int result;
    char ch = 'A';

/*  Create a socket for the client.  */

    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

/*  Name the socket, as agreed with the server.  */

    address.sun_family = AF_UNIX;
    strcpy(address.sun_path, "server_socket");
    len = sizeof(address);

/*  Now connect our socket to the server's socket.  */

    result = connect(sockfd, (struct sockaddr *)&address, len);

    if(result == -1) 
        perror("oops: client1");
        exit(1);
    

/*  We can now read/write via sockfd.  */

    write(sockfd, &ch, 1);
    read(sockfd, &ch, 1);
    printf("char from server = %c\n", ch);
    close(sockfd);
    exit(0);

java代码: 打包gz.kaiwii;

public class NSocket 
    static
        System.loadLibrary("NSocket");
    
    public native void start();

本机代码:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <android/log.h>
#include <android/bitmap.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>

#define  LOG_TAG    "NSocket"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)



JNIEXPORT void JNICALL Java_gz_kaiwii_NSocket_start
  (JNIEnv * env, jobject object)
    LOGI("JNICALL Java_gz_kaiwii_NSocket_start is called!");

    int sockfd;
    int len;
    struct sockaddr_un address;
    int result;
    char ch = 'A';

/*  Create a socket for the client.  */

    LOGI(" Create a socket for the client!");

    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if(sockfd==-1)
    LOGE("create socket error!!!!!");


/*  Name the socket, as agreed with the server.  */

    address.sun_family = AF_UNIX;
    strcpy(address.sun_path, "server_socket");
    len = sizeof(address);

/*  Now connect our socket to the server's socket.  */

    result = connect(sockfd, (struct sockaddr *)&address, len);

    LOGI("  Now connect our socket to the server's socket.");

    if(result == -1) 
        LOGE("connect error!");
        exit(1);
    


/*  We can now read/write via sockfd.  */

    write(sockfd, &ch, 1);
    read(sockfd, &ch, 1);
    /*
    printf("char from server = %c\n", ch);
    */
    LOGI("char from server = %c\n", ch);
    close(sockfd);

日志猫:

【问题讨论】:

我已经用 logcat.thx 对其进行了编辑! 服务器在监听吗?如何在连接失败时打印错误消息?为此使用 errno 和 strerror。 @Mārtiņš Možeiko,服务器提示错误,没有这样的文件或目录。并且客户端提示连接被拒绝。但是,如果我不使用jni调用本机代码,一切运行正常. 【参考方案1】:

如果我使用抽象命名空间作为名称,一切运行正常。但是,需要注意的一点是长度!

【讨论】:

你的问题对我很有帮助。你能告诉我们是否可以在 jni 本身中同时拥有服务器和客户端吗???如果是这样,我们如何同时启动服务器和客户端分别发送和接收数据...

以上是关于通过ndk连接套接字编程的错误的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中的 UDP 套接字编程中获取“传输端点未连接”

套接字编程:'接受:错误的文件描述符'

TCP下的套接字编程

通过python实现TCP编程

Java-UDP Socket编程

Python网络编程利用Python进行TCPUDP套接字编程