通过JNI结合插座

发布于 2025-02-08 10:15:45 字数 2877 浏览 1 评论 0原文

我尝试通过JNI在Linux计算机上打开插座连接。 如果我将java_socket_socket和java_socket_bind组合在同一C函数中,则JNI调用可以很好地工作,但是当我顺序运行方法时,它不起作用。

这是我的代码

#include <jni.h>        // JNI header provided by JDK
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include "Socket.h"   // Generated

JNIEXPORT jint JNICALL Java_Socket_socket(JNIEnv *env, jobject thisObj) {
    int sockfd;

    if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        printf("socket creation failed...\n");
        return (jint)-1;
    } else {
        printf("Socket successfully created..\n");
        printf("Socket descriptor: %d\n", sockfd);
        return (jint) sockfd;
    }
}

JNIEXPORT jint JNICALL Java_Socket_bind(JNIEnv *env, jobject thisObj, jint sockfd, jint port) {
    struct sockaddr_in servaddr;
    bzero(&servaddr, sizeof(servaddr));

    int c_sockfd = (int) sockfd;
    short int c_port = (int) port;

    printf("socket binding sockfd - %d, port - %d\n", c_sockfd, c_port);

    // assign IP, PORT
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(c_port);
    printf("htons - %d\n", htons(c_port));


    int one = 1;
    int res = setsockopt(c_sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
    res = setsockopt(c_sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
    if (res < 0) {
        perror("setsockopt");
    }

    printf("sizeof - %d\n", sizeof(servaddr));

    if (fcntl(c_sockfd, F_GETFD) != -1 || errno != EBADF) {
        printf("fd is valid\n");
    } else {
        printf("fd is invalid\n");
    }

    // Binding newly created socket to given IP and verification
    if ((bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) != 0) {
        printf("socket bind failed...\n");
        printf("Error code: %d\n", errno);
        return (jint)-1;
    }
    else {
        printf("Socket successfully binded..\n");
        return (jint)0;
    }
}

Java代码

public class Socket {
    static {
        System.load(".../libsocket.so");
    }

    private native int socket();

    private native int bind(int sockFd, int port);

    public static void main(String[] args) {
        var socket = new Socket();
        int sockFd = socket.socket();
        System.out.println("sockFd " + sockFd);
        int bind = socket.bind(sockFd, 9900);
        System.out.println("Bind " + bind);
    }
}

输出:

Socket descriptor: 4
socket binding sockfd - 4, port - 9900
htons - 44070
sizeof - 16
fd is valid
socket bind failed...
Error code: 22

如果我从此代码创建C程序,则作为常规C程序,gcc ...&amp;&amp; A.Out - &gt;然后不会发生错误。有什么原因?

可以是因为文件描述符已关闭吗?

I try to open a socket connection on a Linux machine through JNI.
If I combine Java_Socket_socket and Java_Socket_bind in same C function, the JNI call works perfectly, but it doesn't work when I run methods sequentially.

This is my code

#include <jni.h>        // JNI header provided by JDK
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include "Socket.h"   // Generated

JNIEXPORT jint JNICALL Java_Socket_socket(JNIEnv *env, jobject thisObj) {
    int sockfd;

    if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        printf("socket creation failed...\n");
        return (jint)-1;
    } else {
        printf("Socket successfully created..\n");
        printf("Socket descriptor: %d\n", sockfd);
        return (jint) sockfd;
    }
}

JNIEXPORT jint JNICALL Java_Socket_bind(JNIEnv *env, jobject thisObj, jint sockfd, jint port) {
    struct sockaddr_in servaddr;
    bzero(&servaddr, sizeof(servaddr));

    int c_sockfd = (int) sockfd;
    short int c_port = (int) port;

    printf("socket binding sockfd - %d, port - %d\n", c_sockfd, c_port);

    // assign IP, PORT
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(c_port);
    printf("htons - %d\n", htons(c_port));


    int one = 1;
    int res = setsockopt(c_sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
    res = setsockopt(c_sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
    if (res < 0) {
        perror("setsockopt");
    }

    printf("sizeof - %d\n", sizeof(servaddr));

    if (fcntl(c_sockfd, F_GETFD) != -1 || errno != EBADF) {
        printf("fd is valid\n");
    } else {
        printf("fd is invalid\n");
    }

    // Binding newly created socket to given IP and verification
    if ((bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) != 0) {
        printf("socket bind failed...\n");
        printf("Error code: %d\n", errno);
        return (jint)-1;
    }
    else {
        printf("Socket successfully binded..\n");
        return (jint)0;
    }
}

Java code

public class Socket {
    static {
        System.load(".../libsocket.so");
    }

    private native int socket();

    private native int bind(int sockFd, int port);

    public static void main(String[] args) {
        var socket = new Socket();
        int sockFd = socket.socket();
        System.out.println("sockFd " + sockFd);
        int bind = socket.bind(sockFd, 9900);
        System.out.println("Bind " + bind);
    }
}

Output:

Socket descriptor: 4
socket binding sockfd - 4, port - 9900
htons - 44070
sizeof - 16
fd is valid
socket bind failed...
Error code: 22

If I create C program from this code, and as regular C program, gcc ... && a.out -> then no error occurs. What can be reason?

Can it be because file descriptor is closed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

萌化 2025-02-15 10:15:45

问题在于,您将af_unix套接字视为af_inet一个。您不能使用sockaddr_in作为af_unix套接字,也无法将其绑定到IP地址。

我认为您已经在套接字定义代码中制作了错字。而不是

if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {

它应该是

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

The issue is that you're treating AF_UNIX socket as AF_INET one. You can't use sockaddr_in for AF_UNIX socket and also you can't bind it to an IP address.

I think that you've made a typo in your socket definition code. Instead of

if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {

it should be

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文