Android NDK non-deterministic Socket connect() time out - android

I have problems with client/server application that is part of a bigger system for distributed computing. The clients are Android devices that run a native Android NDK application written in C. At some point the clients send registration messages to the server application, which is also written in C and runs on a windows machine.
The weird thing is, right after installing the Android application on the device everything works fine. However, after a while the Socket problem starts. All connect() function calls end with a time out on the client side. The error is not deterministic and occurs at different points in time. To make it work again, I have to uninstall the application in Android manually and reinstall it. After that I works for some time and then the error starts again. The same C code is used on clients that run on normal windows PCs and there the problem does not occur.
The network connection is fine and I checked, if the server ports are open and reachable with the Simple Socket Tester app from the client device. I also gave Android the permission for Internet use and the parameters of the connect() call are correct.
EDIT:
Sorry for the missing code. I thought the error is obvious and based on the different platforms, since it works on windows and I am not that experienced in Android NDK. Here is the code:
int pi_connect(SOCKET s, const SOCKADDR *name, int namelen)
{
int result = connect(s, name, namelen);
if (result < 0) {
ALOG("Socket connecting error!");
return -1;
}
return result;
}
SOCKET pi_socket(int af, int type, int protocol) {
SOCKET returnSocket = socket(af, type, protocol);
int yes = 1;
if (setsockopt(returnSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("Server-setsockopt() error!");
exit(1);
}
if (returnSocket < 0) {
ALOG("Socket creation error!");
return -1;
}
return returnSocket;
}
SOCKET setupSendSocket(u_long host, int hostPort) {
SOCKET sendingSocket;
SOCKADDR_IN addr;
sendingSocket = pi_socket(AF_INET, SOCK_STREAM, 0);
memset(&addr, 0, sizeof(SOCKADDR_IN));
addr.sin_family = AF_INET;
addr.sin_port = htons(hostPort);
addr.sin_addr.s_addr = host;
long rc = pi_connect(sendingSocket, (SOCKADDR*) &addr, sizeof(SOCKADDR));
if (rc < 0) {
return 0;
}
return sendingSocket;
}
void requestOwnIP() {
SOCKET connectedIPSocket = setupSendSocket(inet_addr(brokerIP), 34123);
if(connectedIPSocket==0)
return;
sendBHeartbeatMessage(connectedIPSocket);
myIP = receiveBIPMessage(connectedIPSocket);
pi_closesocket(connectedIPSocket);
}
The requestOwnIP() function is called in the main function of the NDK application.
EDIT 2 (some new remarks): After rebooting the device, the connect() is successful again and the system works for some time. Is there something stored in the process table of the operating system, that can cause this problem? I first though that it could be a high amount of sockets that are in the time_wait state, but I added SO_REUSEADDR and the problem is still occurring.
I would really appreciate some help. Thank you in advance!
Regards
Dominik

Related

recv() always returns -1 in android

I need to send few strings on localhost via socket on android using native code (in C particularity) but I've faced weird problem - recv() function always returns -1 and eerno tells "Try again!"
Here is code responsible for initialization of socket and receiving response
void request() {
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
//need to send string to localhost
inet_aton("127.0.0.1", &(sa.sin_addr));
int sock;
char res[7];
sock = socket(AF_INET, SOCK_STREAM, 0);
sa.sin_port = htons(27042);
int connection = connect(sock, (struct sockaddr *) &sa, sizeof sa);
if (connection != -1) { //connection >= 0
memset(res, 0, 7);
send(sock, "\x00", 1, NULL);
send(sock, "AUTH\r\n", 6, NULL);
usleep(100); // Give it some time to answer
int rec = recv(sock, res, 7, MSG_DONTWAIT);
// rec is always -1 and errno says "Try again!"
}
close(sock);
}
There is an INTERNET permission in Manifest file.
I've tried to put recv(sock, res, 7, MSG_DONTWAIT) part in while loop to wait maybe it would return some data but no success. Maybe I need to call something like flush() after send()?
Does any one know where could be trouble?
UPD. This code runs in one android app (client) and tries to send string to other android app that runs on the same device (server).
Solution became pretty obvious - current "server" version can't process "AUTH" message that is why "client" app receive -1 response. I've tried older version and everything worked fine.

Communicating between C & Arduino

I have battled this issue for a while now and it is driving me nuts:
I am trying to communicate very simply with an Arduino Mega 2560 (via USB as a serial device) from pc running Linux (Knoppix on a usb-dok) when all I am trying to accomplish at this stage is that for each number sent by the laptop to the Arduino, a 'stobe' signal will switch for High to Low or the other way around, and i use this strobe to light turn an LED on and off.
pc side C code:
#include <stdio.h>
int main ()
{
FILE * Device = NULL;
int counter = 0;
Device = fopen("/dev/ttyACM0", "w+");
if(Device == NULL)
{
printf("could not open Device\n");
return -1;
}
while (counter < 10)
{
fprintf(Device, "%d\n", counter);
printf("Sent to Device: %d\n", counter);
counter++;
sleep(2);
}
fclose(Device);
return 0;
}
Arduino code:
int cnt = 0;
int strobe = 0;
int num;
int ValidInput = 0;
char intBuffer[12];
String intData = "";
int delimiter = (int) '\n';
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(3, OUTPUT);
}
int input;
void loop()
{
while(num = Serial.available())
{
delay(5);
// Serial.println(num);
int ch = Serial.read();
if(ch == delimiter)
{
ValidInput = 1;
break;
}
else
{
intData += (char) ch;
}
}
int intLen = intData.length() + 1;
intData.toCharArray(intBuffer, intLen);
intData = "";
int i = atoi(intBuffer);
if(ValidInput)
{
if(i == 0)
{
strobe = 0;
Serial.print("Initializing strobe");
}
else
{
strobe = !strobe;
}
digitalWrite(3, (strobe) ? HIGH : LOW);
Serial.println(i);
ValidInput = 0;
}
}
The problems I am having:
Not sure if fopen is the correct way to communicate with a serial device in Linux, and if so in which mode?
This is the main issue - I am experiencing non-deterministic behavior:
if i run this code right before opening the Arduino editor's 'Serial monitor' it doesn't work as I explained above, instead - it will turn the LED on and then off right away, for each incoming new number.
but once I open the 'Serial monitor' it would act as I want it to - changing the LED's state for each new incoming number.
I am thinking this has something to do with the Arduino's reset or something of that sort.
I looked in many threads here and other forums and couldn't find any solution to this problem.
I'd really appreciate your insight.
First of all, the arduino side looks ok. On the Linux side you need to do some reasearch since the serial communication on posix systems is a little bit more complicated than only opening a file and writing to it. Please use the linux man pages for termios where you can find information on how to setup the communication port parameters and use this document http://tldp.org/HOWTO/Serial-Programming-HOWTO/ for actually learning how to put everything altogether. The serial programming howto will guide you through the process of setting up a port, learning how to control it and learn how to accept input from multiple sources. Also in order to access successfully the serial port from an unprivileged account, you might need to add that user (your user) to a specific group (dialout group in Ubuntu and Fedora). You can search on Google about serial port access under linux and you can fine a lot of code samples ready for you to integrate in your application. You can find an excellent reference and a full documented implementation at the bottom of this thread , also on SO How do I read data from serial port in Linux using C?
A simple fopen doesn't setup any of the serial ports communication parameters. You need to set the baud rate, number of bits, parity, and number of stop bits. And, if you want to use the linux line discipline or not. The termio structure is used to do this.
There are a couple good tutorial on how to use serial between linux and arduinos.
http://chrisheydrick.com/2012/06/12/how-to-read-serial-data-from-an-arduino-in-linux-with-c-part-1/
http://todbot.com/blog/2006/12/06/arduino-serial-c-code-to-talk-to-arduino/

android ad-hoc udp broadcast hangs on send(ndk)

I'm trying to send a broadcast message in my ad-hoc network - 192.168.2.x, using native c code.
But the app hangs on sendto(). btw the hang is not connected to the while, that wraps it, as I can see in debug, it only tries sendto() ones and hangs.
Is there something wrong with my code?
int broadcast(char* msg){
int bcast_sock;
struct sockaddr_in their_addr; // connector's address information
if((bcast_sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
LOGE("ERROR BROADCASTING , socket wasn't created");
}
int broadcastEnable=1;
int ret=setsockopt(bcast_sock, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));
if(ret < 0)
{
LOGE("ERROR BROADCASTING, Coulnt set broadcast enable through socket options");
}
their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(BROADCAST_PORT); // short, network byte order
their_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct
while(-1 == (int)sendto(bcast_sock, msg, strlen(msg), 0,
(struct sockaddr *)&their_addr, sizeof(struct sockaddr)));
return 0;
}
A couple of notes:
This of course are rooted phones.
If I broadcast using java broadcast, it works fine, I'm able to receive the broadcast ie:
datagramSocket.setBroadcast(true);
int receiverPort = 4949;
sendPacket = new DatagramPacket(data, data.length, IPAddress, receiverPort);
Non broadcast messages are also being sent and received using native code.
The CPU usage becomes ~ 95% .
I've also tried simply sending to 192.168.2.255.
any ideas?
I solved it by changing address conversion from:
their_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
to
inet_aton(IP,&their_addr.sin_addr);
where IP = "192.168.2.1"
Thanks for the help epx

android ndk sockets Network Unreachable

I don't know if this is in the way I'm handling Android, or a problem with my native code, or both.
I am setting up a udp socket in C++ (wrappers generated by swig):
udpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (udpSocket < 0)
{
pthread_mutex_unlock(&csOpenCloseUdp);
throw IOException("Failed to open socket");
}
char bAllowMultiple = true;
setsockopt(udpSocket, SOL_SOCKET, SO_REUSEADDR, &bAllowMultiple, sizeof(bAllowMultiple));
setsockopt(udpSocket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&hopLimit, sizeof(hopLimit));
setsockopt(udpSocket, IPPROTO_IP, IP_MULTICAST_IF, (char *)&localAddr, sizeof(localAddr));
// Set to non-blocking mode
unsigned long bMode = 1;
ioctl( udpSocket, FIONBIO, &bMode );
// Create the local endpoint
sockaddr_in localEndPoint;
localEndPoint.sin_family = AF_INET;
localEndPoint.sin_addr.s_addr = localAddr.s_addr;
localEndPoint.sin_port = groupEndPoint.sin_port;
// Bind the socket to the port
int r = bind(udpSocket, (sockaddr*)&localEndPoint, sizeof(localEndPoint));
if (r == SOCKET_ERROR)
{
//LeaveCriticalSection(&csOpenCloseUdp);
pthread_mutex_unlock(&csOpenCloseUdp);
close();
throw IOException("Failed to bind port");
}
// Join the multicast group
struct ip_mreq imr;
imr.imr_multiaddr = groupEndPoint.sin_addr;
imr.imr_interface.s_addr = localAddr.s_addr;
setsockopt(udpSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&imr, sizeof(imr));
The socket is not throwing any exceptions, and after this it has some value not INVALID_SOCKET.
When I try to send a packet though,
int r = sendto(udpSocket, (char*)dataToSend, (size_t)length, 0, (sockaddr*)&groupEndPoint, (socklen_t)sizeof(groupEndPoint));
I get errno 101: Network is unreachable.
I'm quite new to socket programming, and I know sockets in Android is a bad way to start, but the fact is I have to get this done and have very little time. Does anyone here know of a likely reason to get Network Unreachable? Has anyone tried playing with UDP on Android and can shed some light?
Is there a requirement to use C++ sockets? If possible, in the interests of time, and pretty much
in the interests of everything, I'd recommend the Java API instead. Here is an example of how to use it: http://android-er.blogspot.com/2011/01/simple-communication-using.html . I like C, but I would recommend against using it here.
SOLVED:
I just had to monkey with the ethernet settings on the device to get it to talk to my laptop. for some reason it didn't like using the dedicated link, so I'm going through the local network router and it's working. now getting different issues, but this one's done

Android NDK Networking problems: TCP Connection fails

I'm having some troubles with the Android NDK.
My project requires software components written in C that can receive data over TCP to be executed on the Android OS.
To that end, I've made a simple server and client in C using BSD sockets and can send messages back and forth successfully across the connection on PCs. Now I've moved the clientside code into the NDK, and can't connect to my server from the emulator or from an actual android device. NDK compiles without warnings or errors, the emulator/phone are on wifi and have internet permissions enabled in the manifest. What gives?
All it does is make a socket, fill in host/port info and attempt to connect: If it does connect, send a message, else return an error. Android always returns a negative value for connect
This client code, compiled/executed on Mac/Windows/Linux, works:
PC Client code:
int tcp_socket = socket(AF_INET, SOCK_STREAM,0);
if(tcp_socket< 0 ) {
cerr << "Failed to create TCP socket." << endl;
return 2;
}
sockaddr_in server_tcp_add;
server_tcp_add.sin_family = AF_INET;
server_tcp_add.sin_port = htons(tcp_port); //set via command line: Yes, they are the same for the android
hostent *hostp = gethostbyname(server_host);
memcpy(&server_tcp_add.sin_addr, hostp->h_addr, hostp->h_length);
socklen_t slen = sizeof(server_tcp_add);
if(connect(tcp_socket,(sockaddr*)&server_tcp_add, slen) <0 ){
cerr<< "Failed to connect to server with TCP. " << endl;
close(tcp_socket);
return 3;
}
char* myString = "This is my message";
send(tcp_socket, myString, strlen(myString), 0);
close(tcp_socket);
This code, executed on the Android NDK, does not
Code: NDK Client
jstring Java_networking_client_activate_initiateTcpConnection(JNIEnv* env, jobject javaThis){
int tcp_socket = socket(AF_INET, SOCK_STREAM,0);
if(tcp_socket < 0){
return (*env)->NewStringUTF(env, "ERROR CREATING SOCKET");
}
const char* server_host = "some.numbers.that.work"; //It's a valid IP I don't feel like sharing
unsigned short server_port = 43000;
struct sockaddr_in server_tcp_addr;
server_tcp_addr.sin_family = AF_INET;
server_tcp_addr.sin_port = htons(server_port);
struct hostent *hostp = gethostbyname(server_host);
memcpy(&server_tcp_addr, hostp->h_addr, hostp->h_length);
socklen_t slen = sizeof(server_tcp_addr);
if(connect(tcp_socket,(struct sockaddr*)&server_tcp_addr, slen) < 0){ //fails here
close(tcp_socket);
return (*env)->NewStringUTF(env, "ERROR CONNECTING TO SERVER");
}
char* message = "hello from android!";
send(tcp_socket, &message, sizeof(message),0);
return (*env)->NewStringUTF(env, "TCP message sent!");
}
Largely identical; required to put struct in front of everything for NDK to compile.
--edit--I should also mention, I have been able to send data over sockets in Java with this app. Just the C sockets that's really screwing stuff up. Even a sample of someone else that has C sockets working via NDK would be tremendously appreciated.
This is a very late answer, however it might still be useful...
I changed this line:
memcpy(&server_tcp_addr, hostp->h_addr, hostp->h_length);
to this:
memcpy(&server_tcp_addr.sin_addr.s_addr, hostp->h_addr, hostp->h_length);
and that did the trick for me.

Categories

Resources