How to set android tcp buffer size - android

I have written a socket program in c. This program will send data from my android phone to my PC. Here what i need that i want to increase my data buffer size to a larger one so that i could send a large data. I used setsockopt() system call to increase the tcp buffer size. But my android not allowing me to increase the size beyond 4096 bytes. Following i pasted my Server side code. Need help
int listenfd = 0;
//Create a socket
if((listenfd = socket(AF_INET, SOCK_STREAM, 0))==-1)
{
printf("\n Could not create socket..");
return -1;
}
sock_buf_size=8192;
setsockopt( listenfd, SOL_SOCKET, SO_SNDBUF,(char *)&sock_buf_size , sizeof(sock_buf_size));
setsockopt( listenfd, SOL_SOCKET, SO_RCVBUF,(char *)&sock_buf_size , sizeof(sock_buf_size));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(8888);
// sock_buf_size = SOCKET_BUFF_SZ;
//Binding the socket
if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1 )
printf("\nBind failed ");
else puts("\nBind done");
//Listen to incoming connections
listen(listenfd, 5);
//Accept an incoming connection
puts("\nWaiting for incoming connections...");
c = sizeof(struct sockaddr_in);
connfd = accept(listenfd, (struct sockaddr*)&client, &c);
if((RcvdByteCnt = recv(connfd ,pSendBuff , BuffLength, 0)) != -1)
{
printf("\n Revived Byte->%d",RcvdByteCnt );
}

Related

How to connect android application to local domun

I am using esp32 to bring up a tcp server. In order not to access this server by ip, I use mDNS on the esp32 side. I can successfully contact the tcp server from the PC at esp32.local. Now I want to do the same from android application. I wrote a little c ++ code which I run on android.
int sockfd, connfd;
struct sockaddr_in servaddr, cli;
// socket create and varification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
hello ="socket creation failed...";
return env->NewStringUTF(hello.c_str());
}
else
hello="Socket successfully created..\n";
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
std::string url = "esp32.local";
servaddr.sin_addr.s_addr = inet_addr(url.c_str());
servaddr.sin_port = htons(1234);
struct hostent *result;
result = gethostbyname(url.c_str());
// destAddr.sin_addr.s_addr = ((in_addr*)hosten->h_addr_list[0])->s_addr;
if (!result)
{
hello ="gethostbyname...";
return env->NewStringUTF(hello.c_str());
}
// puts(result->h_name);
memmove(&(servaddr.sin_addr.s_addr), result->h_addr, result->h_length);
// connect the client socket to server socket
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) {
hello="connection with the server failed..";
return env->NewStringUTF(hello.c_str());
}
else
printf("connected to the server..\n");
// function for chat
char buff = 0xA;
write(sockfd, &buff, sizeof(buff));
// close the socket
close(sockfd);
When trying to connect from android application, I get an error in function gethostbyname. . What do I need to do to access the .local domain?
std::string url = "esp32.local";
servaddr.sin_addr.s_addr = inet_addr(url.c_str());
inet_addr() does not support parsing hostnames like "sp32.local", only IP addresses. You need to use gethostbyname() or better getaddrinfo() instead.
struct hostent *result;
result = gethostbyname(url.c_str());
...
memmove(&(servaddr.sin_addr.s_addr), result->h_addr, result->h_length);
You are not copying the result of gethostbyname() into the sin_addr.s_addr correctly. Your commented-out code was doing it correctly:
servaddr.sin_addr.s_addr = ((in_addr*)(hosten->h_addr_list[0]))->s_addr;
Which can be simplified to:
servaddr.sin_addr = *(in_addr*)(hosten->h_addr_list[0]);
Or just:
servaddr.sin_addr = *(in_addr*)(hosten->h_addr);
But, getaddrinfo() would be easier to use than populating a sockaddr_in manually. And it supports IPv6, whereas gethostbyname() only supports IPv4:
std::string url = "esp32.local";
int sockfd = -1;
addrinfo hints = {};
addrinfo *result;
hints.ai_family = AF_INET; // AF_UNSPEC
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// assign IP, PORT
int res = getaddrinfo(url.c_str(), "1234", &hints, &result);
if (res != 0) {
return env->NewStringUTF("getaddrinfo failed...");
}
for(addrinfo *addr = result; addr; addr = addr->ai_next) {
// socket create and varification
sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (sockfd == -1) {
continue;
}
// connect the client socket to server socket
if (connect(sockfd, addr->ai_addr, addr->ai_addrlen) != 0) {
close(sockfd);
sockfd = -1;
continue;
}
break;
}
if (sockfd == -1) {
freeaddrinfo(result);
return env->NewStringUTF("socket creation/connect failed...");
}
freeaddrinfo(result);
printf("Connected to the server..\n");
// function for chat
char buff = 0xA;
write(sockfd, &buff, sizeof(buff));
// close the socket
close(sockfd);

hid_get_feature_report analog in Android USB Library

What would be analog to hid_get_feature_report in Android USB Library?
I need to get relays state from usb relays device on Android.
I found example on C (for Linux/Windows): https://github.com/darrylb123/usbrelay/blob/master/libusbrelay.c
static int get_board_features(relay_board *board, hid_device *handle)
{
unsigned char buf[9];
//Get the features of the device
buf[0] = 0x01;
int ret = hid_get_feature_report(handle, buf, sizeof(buf));
if (ret == -1)
{
perror("hid_get_feature_report\n");
}
//Set the serial number (0x0 for termination)
memset(board->serial, 0x0, sizeof(board->serial));
memcpy(board->serial, buf, Serial_Length);
//Byte 7 in the response contains the target_state of the relays
board->state = buf[7];
return ret;
}
On Android it returns only one end point Log.i(TAG, "endpointCount ${usbInterface.endpointCount}

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

Is it possible to use write c code access rild socket in Android

like the Title. I write the code like this:
printf("create socket\r\n");
fd = socket_local_client(SOCKET_NAME_RIL,
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_STREAM);
if (fd < 0) {
perror ("opening radio socket error");
exit(-1);
}
printf("fd = %d\r\n",fd);
int length = 12;
char datalength[5]={0};
datalength[0] = 0;
datalength[1] = 0;
datalength[2] = (length >>8) & 0xff;
datalength[3] = (length & 0xff);
int ret = send(fd, datalength, 4, 0);
if(ret != sizeof(int)) {
perror ("Socket write error when sending length");
close(fd);
exit(-1);
}
i can get fd value successfully, and send data successfully.
but from "logcat -b radio" there is nothing information can be displayed.
it seems that rild has prevent socket connection.
is there any resolutions? Thanks
The rild socket is "owned" by the Phone app, so you won't be able to connect to it as long as that is running. You might try connecting to the rild-debug socket.

getpeername can not recognize connection established

there's simple socket program (server / client) i made.
server is working on windows and client is android app which contains shared library made of c socket.
in client side, to avoid freeze i changed socket to NON_BLOCK than rollback to BLOCK socket after passing connect() function. after that, i search connection is available using getpeername().
as below...
flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags|O_NONBLOCK);
nRet = connect(sock, (struct sockaddr*)&addr, sizeof(addr));
if (nRet < 0)
if (errno != EINPROGRESS && errno != EWOULDBLOCK)
return ERR_CONN;
...
...
nRet = select(sock+1, &readset, &writeset, NULL, &tv);
if (nRet == 0)
if (errno != EINPROGRESS && errno != EWOULDBLOCK)
return ERR_SELECT;
nRet = getpeername(sock, (struct sockaddr*)&addr, &len);
if (nRet != 0)
return ERR_GETPEER;
fcntl(sock, F_SETFL, flags);
everything's working well. except working on 3G mode.
sometimes even if Server got connection, client side return errors in getpeername().
error code is ENOTCONN.
what should i implement to avoid this? any suggestion would be appreciate.
thx in advance.
i found what's wrong.
first, i should roll back to BLOCK socket after passing connect() not before return.
second, it seems that select() doesn't guarantee to hold for timeval, so i made function like GetTickCount() than counted time to break loop.
here's my solution.
fcntl(O_NONBLOCK);
connect();
fcntl(BLOCK);
while (true)
{
fd_set rdfs, wdfs;
FD_ZERO(&rdfs); FD_ZERO(&wdfs);
FD_SET(sock, &rdfs); FD_SET(sock, &wdfs);
tv.tv_sec = 0; tv.tv_usec = 100;
nRet = select(sock + 1, &rdfs, &wdfs, NULL, &tv);
if (nRet == -1) return -1;
else if (nRet)
{
nRet = getpeername();
if (!nRet)
break;
}
if (get_tick_count() - delay > timeout)
return -2;
}
thx! sarnold, caf :)
To determine if the socket is connected, it is more usual to use getsockopt() rather than getpeername():
int so_error;
socklen_t len = sizeof so_error;
getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len);
if (so_error == 0) {
/* socket is connected */
}

Categories

Resources