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: %dn", 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 - %dn", 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 - %dn", 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 - %dn", sizeof(servaddr)); if (fcntl(c_sockfd, F_GETFD) != -1 || errno != EBADF) { printf("fd is validn"); } else { printf("fd is invalidn"); } // 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: %dn", 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?
Advertisement
Answer
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) {