Android 通过ndk连接套接字编程错误
实际上,我已经在android emulator中对server.c和client.c进行了测试(ps:它们都成功运行,并使用android genric交叉编译器进行了编译)。然后,我进一步通过jni重写了客户端。但是,在这种情况下,客户端无法连接到服务器端,尽管新客户端与client.c非常相似。 搜索后,有人提到权限很重要。但是,当我添加Android 通过ndk连接套接字编程错误,android,linux,android-emulator,android-ndk,Android,Linux,Android Emulator,Android Ndk,实际上,我已经在android emulator中对server.c和client.c进行了测试(ps:它们都成功运行,并使用android genric交叉编译器进行了编译)。然后,我进一步通过jni重写了客户端。但是,在这种情况下,客户端无法连接到服务器端,尽管新客户端与client.c非常相似。 搜索后,有人提到权限很重要。但是,当我添加(ps:此标记在应用程序标记之外)时,问题仍然出现。 正如logcat所示,java代码实际上包含了c方法,但是,为什么它的行为与client.c不一样呢
(ps:此标记在应用程序标记之外)时,问题仍然出现。
正如logcat所示,java代码实际上包含了c方法,但是,为什么它的行为与client.c不一样呢?
任何想法都会让我受益匪浅。提前谢谢
服务器。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);
}
}
本机代码:
/* 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);
}
/*不要编辑此文件-它是机器生成的*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义日志标签“NSocket”
#定义LOGI(…)\uuuuuAndroid\uLog\uPrint(android\uLog\uInfo、log\uTag、VA\uArgs\uuuu)
#定义日志(…)\uuuuuAndroid\uLog\uPrint(android\uLog\uError,log\uTag,\uuuU VA\uArgs\uuuuu)
JNIEXPORT void JNICALL Java_gz_kaiwii_NSocket_start
(JNIEnv*env,jobject对象){
LOGI(“调用JNICALL Java_gz_kaiwii_NSocket_start!”);
int-sockfd;
内伦;
结构sockaddr\u联合国地址;
int结果;
char ch='A';
/*为客户端创建套接字*/
LOGI(“为客户端创建套接字!”);
sockfd=socket(AF_UNIX,SOCK_流,0);
如果(sockfd==-1){
LOGE(“创建套接字错误!!!!!!!”;
}
/*按照与服务器商定的方式命名套接字*/
address.sun_family=AF_UNIX;
strcpy(address.sun_路径,“服务器插座”);
len=sizeof(地址);
/*现在将我们的套接字连接到服务器的套接字*/
结果=连接(sockfd,(结构sockaddr*)和地址,len);
LOGI(“现在将我们的套接字连接到服务器的套接字。”);
如果(结果==-1){
LOGE(“连接错误!”);
出口(1);
}
/*我们现在可以通过sockfd进行读/写*/
写入(sockfd和ch,1);
读取(sockfd和ch,1);
/*
printf(“来自服务器的字符=%c\n”,ch);
*/
LOGI(“来自服务器的字符=%c\n”,ch);
关闭(sockfd);
}
日志:
如果我使用抽象名称空间作为名称,一切都正常运行。但是,有一点应该注意的是长度 我已经用logcat.thx编辑过了!服务器正在侦听吗?连接失败时打印错误消息如何?请使用errno和strerror。@MārtiņšMožeiko,服务器提示错误,没有这样的文件或目录。客户端提示连接被拒绝。但是,如果我不使用jni调用本机代码,则所有代码都可以运行。您的问题对我很有帮助。你能告诉我们,在jni本身中,服务器和客户端是否都可以使用吗???如果是这样,我们如何同时启动服务器和客户端,分别发送和接收数据。。。
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);
}