I have successfully connected my android phone as client to a raspberry pi as server.
The next step is sending data to the raspberry pi using bytes. Am I doing it correctly for the Android in Java?
socket.getOutputStream().write(String.valueOf(progress).getBytes());
Thereafter, on my raspberry pi side, I will have to receive the bytes in C. I am facing problems in receiving data on server. Here is my code.
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(){
int welcomeSocket,clientSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
ssize_t nread;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(9999);
/* Set IP address to localhost */
serverAddr.sin_addr.s_addr = INADDR_ANY;
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Bind the address struct to the socket ----*/
bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
/*---- Listen on the socket, with 5 max connection requests queued ----*/
if(listen(welcomeSocket,5)==0){
printf("Listening\n");
}
else
printf("Error\n");
/*---- Accept call creates a new socket for the incoming connection ----*/
addr_size = sizeof serverStorage;
clientSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
printf("Successfully Connected!!!\n\r");
//Receive data from android
//recv(welcomeSocket,buffer,1024,0);
nread = recvfrom(clientSocket, buffer,1024, 0, (struct sockaddr *) &serverStorage, &addr_size);
if(nread==-1)
perror("Error!");
else
printf("Data received: %s",buffer);
return 0;
}
As from Pravin's comment, I tried using the Recvfrom and perror, it showed an error of -1.
Okay! I realised the problem. I realised I didnt use the client socket created previously. I kept on using the Server's socket lol. Didn't notice it at first. I used an example to see what was different between my server and the example server, which really helped!
http://www.binarytides.com/server-client-example-c-sockets-linux/
Related
I am trying to make Kernel (Android, kernel 4.9.59) communicate with userspace applications. I found a solution using Netlink sockets: https://stackoverflow.com/a/25071310/4190159
The first issue with the solution is that struct netlink_skb_parms used in the solution does not have a member named 'pid', instead has a member named 'portid', which I believe is not the same as pid. Anyway, to compile my kernel side code/solution I used 'portid' member of struct netlink_skb_parms instead for initialization. However, now I am getting a different error.
My Kernel side Netlink socket code as follows:
#include <linux/sched.h>
//For netlink socket -->
#include <net/sock.h>
//#include <net/netlink.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <linux/string.h>
#define MY_GROUP 1 //For netlink socket
struct sock* socket; //For netlink socket
struct sk_buff* socket_buff; //For netlink socket
static void nl_receive_callback (struct sk_buff *skb)
{
nlmsg_free(skb);
}
static void kernel_send_nl_msg(void)
{
struct nlmsghdr *nlsk_mh;
char* msg = "hello from kernel";
socket = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 1, nl_receive_callback, NULL, THIS_MODULE);
socket_buff = nlmsg_new(256, GFP_KERNEL);
nlsk_mh = nlmsg_put(socket_buff, 0, 0, NLMSG_DONE, strlen(msg), 0);
//NETLINK_CB(socket_buff).pid = 0; // kernel pid is deprecated
NETLINK_CB(socket_buff).portid = 0;
NETLINK_CB(socket_buff).dst_group = MY_GROUP;
strcpy(nlmsg_data(nlsk_mh), msg);
nlmsg_multicast(socket, socket_buff, 0, MY_GROUP, GFP_KERNEL);
pr_info("%s", msg);//Print out the message to kernel
return;
}
My userspace application side code to intercept the message from the kernel as follows:
#include <sys/socket.h>
#include <linux/netlink.h>
#define MY_GROUP 1
void user_recieve_nl_msg(void)
{
int sock_fd;
struct sockaddr_nl user_sockaddr;
struct nlmsghdr *nl_msghdr;
struct msghdr msghdr;
struct iovec iov;
char* kernel_msg;
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USERSOCK);
memset(&user_sockaddr, 0, sizeof(user_sockaddr));
user_sockaddr.nl_family = AF_NETLINK;
user_sockaddr.nl_pid = getpid();
user_sockaddr.nl_groups = MY_GROUP;
bind(sock_fd, (struct sockaddr*)&user_sockaddr, sizeof(user_sockaddr));
while (1) {
nl_msghdr = (struct nlmsghdr*) malloc(NLMSG_SPACE(256));
memset(nl_msghdr, 0, NLMSG_SPACE(256));
iov.iov_base = (void*) nl_msghdr;
iov.iov_len = NLMSG_SPACE(256);
msghdr.msg_name = (void*) &user_sockaddr;
msghdr.msg_namelen = sizeof(user_sockaddr);
msghdr.msg_iov = &iov;
msghdr.msg_iovlen = 1;
recvmsg(sock_fd, &msghdr, 0);
kernel_msg = (char*)NLMSG_DATA(nl_msghdr);
print("Kernel message: %s\n", kernel_msg); // print to android logs
}
close(sock_fd);
}
When I am trying to build the android kernel I am receiving the fllowing error:
kernel/sched/custom_code.h:34:65: error: passing argument 3 of
'netlink_kernel_create' makes pointer from integer without a cast
[-Werror]
kernel/sched/custom_code.h:34:14: error: too many arguments to
function 'netlink_kernel_create'
Note the code for the Kernel side is written in custom_code.h.
My questions are as follows:
I have checked the function 'netlink_kernel_create' and I am sending the right number of arguments then why is the aformentioned error coming up? How this error could be resolved?
What should I do to establish a valid communication between the kernel and the userspace application so that messages could be passed (to and fro) between them?
1.
Let's check netlink_kernel_create function in linux kernel:
static inline struct sock *
netlink_kernel_create(struct net *net, int unit, struct netlink_kernel_cfg *cfg)
{
return __netlink_kernel_create(net, unit, THIS_MODULE, cfg);
}
from here https://elixir.bootlin.com/linux/v4.9.59/source/include/linux/netlink.h#L60
Notice, that this function takes only 3 arguments ( instead of 6 in your code )
This function have been changed in kernel 3.6 ( from 6 parameters to 4 )
https://elixir.bootlin.com/linux/v3.6/source/include/linux/netlink.h#L185
And then renamed to __netlink_kernel_create in kernel 3.7
netlink_kernel_create function from 3.7 accepts 3 arguments
https://elixir.bootlin.com/linux/v3.7/source/include/linux/netlink.h#L48
Try change this
socket = netlink_kernel_create(&init_net, NETLINK_USERSOCK, 1, nl_receive_callback, NULL, THIS_MODULE);
to this
struct netlink_kernel_cfg cfg = {
.input = nl_receive_callback,
.groups = 1,
};
socket = netlink_kernel_create(&init_net, NETLINK_USERSOCK, &cfg);
Now you can send data in direction "kernel => application".
When you start your application, it will bind socket with user_sockaddr.nl_groups = MY_GROUP; bind(sock_fd, (struct sockaddr*)&user_sockaddr, sizeof(user_sockaddr));.
After this you can send data from kernel to application with NETLINK_CB(socket_buff).dst_group = MY_GROUP; nlmsg_multicast(socket, socket_buff, 0, MY_GROUP, GFP_KERNEL); and it will be received by application with recvmsg(sock_fd, &msghdr, 0);
How can I call kernel_send_nl_msg() function to actually communicate with the userspace?
You can call it from kernel module, which you write, compile and insmod into kernel. Or you can call it directly from kernel, but for this you will need to rebuild whole kernel.
If you want to send data in direction "application = > kernel", then you need to do things in reverse: bind new socket with another MY_GROUP2 in kernel and send data from application with nlmsg_multicast
I am attempting to use unix-domain sockets and am developing under the NDK. I am routinely receiving Operation not permitted errors for various actions related to trivial AF_UNIX/SOCK_DGRAM type IPC.
I am able to successfully bind both processes to a particular interface but am unable to either connect or send/sendto without getting the error mentioned above. The bound interfaces do appear on the file system if an appropriate ls is done in the specified directory. Also, each interface name is given explicit other-read/write access using chmod to prevent any permissions problems.
Process A (Consumer):
struct sockaddr_un local_addr;
int ctrl_fd;
/* Clean the structure and copy over our observable address */
bzero(&local_addr, sizeof(struct sockaddr_un));
strncpy(local_addr.sun_path, local_sock_name, sizeof(local_sock_name));
local_addr.sun_family = AF_UNIX;
ctrl_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
bind(ctrl_fd, (struct sockaddr *) &local_addr, sizeof(struct sockaddr_un));
/* Associate with our path */
connect(ctrl_fd, (struct sockaddr *) &local_addr, sizeof(struct sockaddr_un));
while(1){
recvLen = recv(ctrl_fd, buf, sizeof(buf), 0);
printf("Received: %s\n", buf);
}
Process B (Producer):
int sock_fd;
struct sockaddr_un dest_addr, local_addr;
/* Get our socket handle */
sock_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
/* Define where we are to connect */
bzero(&dest_addr, sizeof(struct sockaddr_un));
strncpy(dest_addr.sun_path, dest_name, sizeof(dest_name));
dest_addr.sun_family = AF_UNIX;
/* Define who we are */
bzero(&local_addr, sizeof(struct sockaddr_un));
strncpy(local_addr.sun_path, local_name, sizeof(local_name));
local_addr.sun_family = AF_UNIX;
/* Make a name for ourself */
bind(sock_fd, (struct sockaddr *) &local_addr, sizeof(struct sockaddr_un));
/* Associate fd with remote address */
connect(sock_fd, (struct sockaddr *) &dest_addr, sizeof(struct sockaddr_un));
while(1){
sleep(10);
send(sock_fd, "test", sizeof("test"), 0);
}
However, I have managed only to be denied by Operation not permitted on both connect and send. Additionally, I tried removing the connect call entirely and simply using sendto, but I get the same error.
Note: I have removed any error printing from the snippet for brevity. In the actual code I am determining these errors by checking the return values of each sys-call and doing a strerror(errno) to get the respective error message.
I have implemented a UDP client on android's native part(i.e. in C). Inorder to receive data from the server(PC) both my device and PC are connected over a wifi connection.
When the client is put on a rooted device, it is able to receive data from the server perfectly. However on a non-rooted device, although it doesnt show any error, it is not able to send/receive data form/to the server.
Below is my server code:
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/stat.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
int main()
{
int cont,create_socket,new_socket,addrlen,fd;
int bufsize = 3000;
int nameLen=0;
int client_address_size=0;
char *buffer = malloc(bufsize);
char fname[256];
struct sockaddr_in address,client;
if ((create_socket = socket(AF_INET,SOCK_DGRAM,0)) > 0)
printf("The socket was created\n");
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(15000);
if (bind(create_socket,(struct sockaddr *)&address,sizeof(address))== 0)
printf("Binding Socket\n");
nameLen=sizeof(address);
if (getsockname(create_socket,(struct sockaddr *)&address,&nameLen)<0)
{
printf("\n\ngetsockname() error\n");
exit(3);
}
printf("Port assigned is %d\n", ntohs(address.sin_port));
client_address_size=sizeof(client);
if(recvfrom(create_socket,fname, 255,0,(struct sockaddr *) &client,&client_address_size)<0)
{
printf("\n\nrecvfrom() failed\n");
exit(4);
}
printf("A request for filename %s Received..\n", fname);
if ((fd=open(fname, O_RDONLY))<0)
{
perror("File Open Failed");
exit(0);
}
while((cont=read(fd, buffer, bufsize))>0)
{
sleep(1);
sendto(create_socket,buffer,cont,0,(struct sockaddr *) &client,client_address_size);
printf("\n\nPacket sent\n");
}
sendto(create_socket,"*",1,0,(struct sockaddr *) &client,client_address_size);
printf("Request Completed\n");
return close(create_socket);
}
client code on android NDK:
JNIEXPORT void JNICALL Java_com_examplemyPlayer_startClient
(JNIEnv *env, jclass jobj, jint portNo, jstring argv1)
{
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","start client has entered....",NULL);
//int portno=portNo;
const char *servIP = (*env)->GetStringUTFChars(env, argv1, 0);
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Server IP address:%s",servIP);
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Server Port No.:%d",portno);
qBuff=(unsigned char *)malloc(sizeof(char)*Q_SIZE);//qBuff is a global pointer
int create_socket,cont;
int bytesWritten=0;
int bufsize = 3000;
int server_address_size=0;
char *buffer = malloc(bufsize);
char reqFname[8]="Bub.bin";
struct sockaddr_in address,server;
int serv_addr_size = sizeof(address);
if ((create_socket = socket(AF_INET,SOCK_DGRAM,0)) < 0)
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","The Socket was NOT created",NULL);
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","The Socket was successfully created",NULL);
address.sin_family = AF_INET;
address.sin_port = htons(15000);
address.sin_addr.s_addr=inet_addr(servIP);
if((sendto(create_socket, reqFname, sizeof(reqFname), 0,(struct sockaddr *) &address,sizeof(address)))==-1)
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Error sending filename to server",NULL);
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Request Accepted... \n\nReceiving File...",NULL);
server_address_size=sizeof(server);
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Contents of the file are:",NULL);
while((cont=recvfrom(create_socket, buffer, bufsize, 0,(struct sockaddr *) &address,&serv_addr_size))>0)
{
if(buffer[cont-1]=='*')
break;
memcpy(qBuff+r,buffer,cont);//copying received data to a circular queue
r=(r+3000)%Q_SIZE;
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","Bytes received:%d",cont);
//write(1, buffer, cont);
}
__android_log_print(ANDROID_LOG_DEBUG,"MYAPP","EOF",NULL);
free(qBuff);
close(create_socket);
}
The above code works fine for a rooted device, but not on an unrooted one. Since the application that i'm creating should be able to run on both rooted and unrooted devices, i need to make the code run on an unrooted device also.
The server was able to connect to the rooted device only after diabling the Linux firewall using /sbin/services iptable stop. So is there a firewall for unrooted device which is blocking the communication port. In the above code i'm trying port no 15000. However i have also tried for other ports also but did'nt workout.
So i kindly request the readers to provide useful answers or reference links for the same. Thanks in advance.
How can I turn on or turn off a switch using Android and a Wi-Fi connection?
I have used SparkFuns IOIO to control relays. But how do I do it wirelessly?
I have a project just like this. Mine is sending position data for a steering system, but the idea is the same. I'll finish uploading it to Google Code soon. You can check it out at PowerWheelino.
The basic structure is this:
Touch event on Android sends data (over UDP) to the server.
The UDP server (WRT54G router in this case) receives the data and forwards it over serial to the Arduino.
The Arduino decides what to do with the data from the serial connection.
Keep in mind that the Arduino automatically resets when receiving data over serial (outside of the IDE Serial interface). See my post here on this topic and ways to get around it. Knowing this previously would have saved me a lot of troubleshooting.
Disclaimer:
This code requires some minor modification to accomplish what was requested by the OP. Since you've already made a working Android program with IOIO and an Arduino sketch, I assume this is within your abilities.
Here's the Android UDP client code:
Execute UdpClient::sendData() on touch event or button press.
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import android.util.Log;
public class UdpClient {
String messageStr;
DatagramSocket s;;
int server_port;
InetAddress local;
int msg_length;
byte[] message;
public UdpClient (String ipAddress, int port){
server_port = port;
try {
local = InetAddress.getByName(ipAddress);
s = new DatagramSocket();
}
catch (Exception e) {
e.printStackTrace();
Log.d("Powerwheelino",e.getStackTrace() + "error");
}
}
public boolean sendData(byte drive, byte steering){
byte drvByte = (byte) (drive & 0xFF);
byte steerByte = (byte) (steering & 0xFF);
message = new byte[2];
message[0] = drvByte;
message[1] = steerByte;
msg_length = message.length;
//message = messageStr.getBytes();
try {
DatagramPacket p = new DatagramPacket(message, msg_length,local,server_port);
s.send(p);
}
catch (Exception e) {
// TODO Auto-generated catch block
Log.d("Powerwheelino", e.getStackTrace() +"ERROR ");
e.printStackTrace();
return false;
}
return true;
}
}
Here's the listening UDP server (C++) code
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <SerialStream.h>
using namespace std;
class udp_server {
int sock;
int bytes_read;
socklen_t addr_len;
struct sockaddr_in server_addr , client_addr;
public:
udp_server(int portNum)
{
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portNum);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),8);
if (bind(sock,(struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1)
{
perror("Bind");
exit(1);
}
addr_len = sizeof(struct sockaddr);
printf("\nUDPServer Waiting for client on port %d", portNum);
fflush(stdout);
}
int listen(char recv_data[]) {
while (1)
{
bytes_read = recvfrom(
sock,
recv_data,
1024,
0,
(struct sockaddr *)&client_addr,
&addr_len
);
recv_data[bytes_read] = '\0';
printf("\n(%s , %d) said : ",inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
printf("%s", recv_data);
string drive;
string direction;
int speed, angle;
if ((recv_data[0] & 128) > 0) {
drive = "Fwd";
}
else {
drive = "Rev";
}
if ((recv_data[1] & 128) > 0) {
direction = "Left";
}
else {
direction = "Right";
}
speed = recv_data[0] & 127;
angle = recv_data[1] & 127;
printf("\t %s # %d and %s # %d",
drive.c_str(),
speed,
direction.c_str(),
angle);
fflush(stdout);
}
return 0;
}
};
Here's a snippet of the serial communication to the Arduino using LibSerial:
LibSerial::SerialStream myss;
SerialComm(int argc, char** argv) {
myss = new LibSerial::SerialStream("/dev/ttyS0", ios_base::out);
myss.SetBaudRate(LibSerial::SerialStreamBuf::BAUD_57600);
myss.SetCharSize(LibSerial::SerialStreamBuf::CHAR_SIZE_8);
myss.SetFlowControl(LibSerial::SerialStreamBuf::FLOW_CONTROL_NONE);
myss.SetParity(LibSerial::SerialStreamBuf::PARITY_NONE);
myss.SetNumOfStopBits(1);
const int Dsize = 2;
char buffer[1];
buffer[0] = 125; //0b00000001;
buffer[1] = '\0';
bitset(buffer[0]);
//myss << buffer;
myss.write(buffer,1);
//myss.Close();
}
You could use an Arduino with an Ethernet Shield - or possibly a Netduino. Basically, any device with wireless internet capabilities, since that is the only wireless protocol Android uses - besides Bluetooth (or NFC). When the user presses a button, you could open a Socket or a BluetoothSocket to communicate to the second device that it needs to open the switch. Fairly simple - if you have a wireless home network, then your device could be plugged in to your router with a physical wire - as long as your Android device and your microprocessor are on the same network. There might be other wireless options you could use - these are just the simplest I could thing of. Hope this helps!
That's why how I did it with my iPhone (should be the same on Android):
run a TCP server on a computer connected to the same network as your phone and by USB/serial to the Arduino.
This server should forward all incoming data coming through Wi-Fi from your Android phone through USB to the Arduino.
The phone should run a TCP client which sends a simple one-byte (maybe zero and non-zero) command
The Arduino shall be programmed so it listens for incoming serial data via interrupts; if a byte arrives it decides if it should switch the I/O pin on or off.
You can also use a Rugged Circuits Yellowjacket. It has a Wifi on board and can serve simple web pages and control inputs/outputs.
When I call recvfrom using the Android NDK, I get NULL returned to my sockaddr_in from. This same exact code works fine on my desktop environment, but not on the device.
int MyClass::ReceiveData(char *buffer, int bufferLength)
{
int numBytes = 0;
struct sockaddr_in from;
socklen_t fromLength = sizeof(struct sockaddr_in);
numBytes = recvfrom(mConnectionSocket,
buffer,
bufferLength,
0,
(struct sockaddr *)&from,
&fromLength);
if (numBytes == -1)
perror("recvfrom");
int fromAddress = ntohl(from.sin_addr.s_addr);
return fromAddress;
}
Anybody have any ideas?
I get NULL returned to my sockaddr_in 'from'
That's not possible with that code. from isn't a pointer that can become NULL. More probably your sockaddr_in structure named by from is getting zeroed. Which would be caused by using this on a TCP socket. If this is TCP you should be calling getpeername() on the socket to get the peer address.