Sending text over local TCP connection succeeds! Sending text from Ubuntu to AOSP over local ip address. For some reason it works to accept text with a third-party apk app. But it does not work in C++ environment inside the service. I've tried different variations of the code. I can't accept the text. Error: "Connection refused" OR "Failed recv: Transport endpoint is not connected".
The service is successfully allowed to use the internet. Checked with.
static const String16 sAccessWifiStatePermission("android.permission.ACCESS_WIFI_STATE");
static const String16 sInternetPermission("android.permission.INTERNET");
static const String16 sAccessNetworkStatePermission("android.permission.ACCESS_NETWORK_STATE");
...
bool checksAccessNetworkStatePermission = permissionChecker.checkPermissionForPreflight(
sAccessNetworkStatePermission, attributionSource, String16(), AppOpsManager::OP_NONE)!= permission::PermissionChecker::PERMISSION_HARD_DENIED;
...
I use different ports, for example, 5030..5033. And use local ip address of smartphone: 192.168.2.110. I specify this address in c++ code in AOSP or use INADDR_ANY. Why can't I accept the text ?
One of the code variants that can't accept text:
std::string receiveTextTcp(int port) {
struct sockaddr_in serv_addr;
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
ALOGI("Failed socket: %s", strerror(errno));
return "";
}
ALOGI("fd : %d, port:%d", fd, port);
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port);
int reuse_flag = 1;
int result = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_flag, sizeof(reuse_flag));
if (result < 0) {
ALOGI("Failed setsockopt: %s, port:%d", strerror(errno), port);
}
int bind_result = bind(fd, reinterpret_cast<sockaddr*>(&serv_addr), sizeof(serv_addr));
if (bind_result < 0) {
ALOGI("Failed bind: %s, port:%d", strerror(errno), port);
}
result = listen(fd, 1);
if (result < 0) {
ALOGI("Failed listen: %s, port:%d", strerror(errno), port);
}
char buffer[1024];
int bytes_received = recv(fd, buffer, sizeof(buffer), 0);
if (bytes_received < 0) {
ALOGI("Failed recv: %s, port:%d", strerror(errno), port);
}
ALOGI("Failed buffer: %s, port:%d", buffer, port);
close(fd);
return "";
}
A successful code variant that successfully sends text to a PC:
bool SendData(const std::string& ip, int port, const std::string& text) {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
ALOGI("Failed to create socket: %s, sockfd:%d", strerror(errno), sockfd);
return false;
}
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
// Use inet_pton instead of inet_addr
if (inet_pton(AF_INET, ip.c_str(), &servaddr.sin_addr) <= 0) {
ALOGI("Invalid IP address: %s", ip.c_str() );
close(sockfd);
return false;
}
if (connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
ALOGI("Failed to connect to server: %s", strerror(errno) );
close(sockfd);
return false;
}
const char* message = text.c_str();
size_t message_len = strlen(message);
if (send(sockfd, message, message_len, 0) < 0) {
ALOGI("Failed send, err: %s . message:%s", strerror(errno), message );
close(sockfd);
return false;
} else{
ALOGI("send ok. message:%s", message );
}
close(sockfd);
return true;
}
A "Transport endpoint is not connected" error is errno
107, aka ENOTCONN
. Android runs on top of Linux, and the Linux recv()
documentation says:
ENOTCONN
The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).
You cannot use recv()
(or send()
) on a TCP socket that you are listen()
'ing on. Instead, you must first accept()
a client that is connect()
'ing to you, to establish a connection between them. Then you can use recv()
(and send()
) on the new socket descriptor that accept()
returns to you, eg:
...
result = listen(fd, 1);
if (result < 0) {
ALOGI("Failed listen: %s, port:%d", strerror(errno), port);
}
// ADD THIS!!!
int clientfd = accept(fd, NULL, NULL);
if (clientfd < 0) {
ALOGI("Failed accept: %s, port:%d", strerror(errno), port);
}
// use client fd not listening fd!!!
char buffer[1024];
int bytes_received = recv(/*fd*/clientfd, buffer, sizeof(buffer), 0);
...
// don't forget to close the client when finished...
close(clientfd);
...