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);
Related
I have been trying to check if a NodeJs Server is up from C code in Android JNI, but my attempt never returns true even when the server is up, even when I can connect to the server from the app.
Here's my approach in C :
const char *myIpAddress = "192.168.0.13";
int count = 10;
struct in_addr ip_bin;
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
return my_call_back_func("0");;
}
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
q server_addr.sin_port = htons(PORT_NO);
server_addr.sin_addr.s_addr = inet_pton(AF_INET, myIpAddress, &ip_bin);
__android_log_print(ANDROID_LOG_WARN, "MyApp", "Binary representation of %s: %x\n", myIpAddress, ntohl(ip_bin.s_addr));
int i;
for (i = 0; i < count; i++) {
__android_log_print(ANDROID_LOG_WARN, "MyApp", "\n>>> %d PING <<<", i);
if (connect(sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) >= 0) {
close(sock);
__android_log_print(ANDROID_LOG_WARN, "MyApp", "\n>>> IP connection successful !!! <<<");
my_call_back_func("1");
return;
}
close(sock);
usleep(PING_SLEEP_RATE);
}
NodeJs Server :
const MY_PORT = process.env.PORT || 4000;
const MY_HOST = "192.168.0.13";
const server = http.createServer(app);
server.on("listening", function () {
console.log(`>>> R.D Server is running ${JSON.stringify(server.address())}`);
});
server.listen(MY_PORT, MY_HOST, () => {
console.log(`Listening on port ${MY_PORT} . . . .`);
console.log(`CORS-enabled web server listening on port : ${MY_PORT}`);
});
What is it that I'm doing wrong?
Thank you all in advance.
I want to recieve text data from remote android bluetooth. I had written simple winApi server, but it doesnt respond to remote android sending. The connection was fine and did responds( paired) using control panel manager with my bluetooth. When sending and recieving over control panel manager was working fine. But This time, I want to test using some c++ winapi. Here's my code so far. It was adapted from somewhere codeproject site :)
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <string>
#include <tchar.h>
#include <WinSock2.h>
#include <ws2bth.h>
#include <BluetoothAPIs.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested = 0x202;
WSADATA m_data;
if (0 == WSAStartup(wVersionRequested, &m_data))
{
SOCKET s = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
const DWORD lastError = GetLastError();
if (s == INVALID_SOCKET)
{
ostringstream stream;
stream << lastError;
string data= stream.str();
printf("Failed to get bluetooth socket! %s\n", data.c_str());
return 1;
}
WSAPROTOCOL_INFO protocolInfo;
int protocolInfoSize = sizeof(protocolInfo);
if (0 != getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFO,
(char*)&protocolInfo, &protocolInfoSize))
{
return 1;
}
SOCKADDR_BTH address;
address.addressFamily = AF_BTH;
address.btAddr = 0;
address.serviceClassId = GUID_NULL;
address.port = BT_PORT_ANY;
sockaddr *pAddr = (sockaddr*)&address;
if (0 != bind(s, pAddr, sizeof(SOCKADDR_BTH)))
{
ostringstream stream;
stream << GetLastError();
string data= stream.str();
printf("%s\n", data.c_str() );
}
else
{
printf("\nBinding Successful....\n");
int length = sizeof(SOCKADDR_BTH) ;
getsockname(s,(sockaddr*)&address,&length);
wprintf (L"Local Bluetooth device is %04x%08x \nServer channel = %d\n",
GET_NAP(address.btAddr), GET_SAP(address.btAddr), address.port);
}
int size = sizeof(SOCKADDR_BTH);
if (0 != getsockname(s, pAddr, &size))
{
ostringstream stream;
stream << GetLastError();
string data= stream.str();
printf("%s\n", data.c_str());
}
if (0 != listen(s, 10))
{
ostringstream stream;
stream << GetLastError();
string data= stream.str();
printf("%s\n", data.c_str());
}
WSAQUERYSET service;
memset(&service, 0, sizeof(service));
service.dwSize = sizeof(service);
// service.lpszServiceInstanceName = reinterpret_cast<LPWSTR>(_T("Accelerometer Data..."));
//service.lpszServiceInstanceName = ;
// service.lpszComment = reinterpret_cast<LPWSTR>(_T("Pushing data to PC"));
GUID serviceID = OBEXFileTransferServiceClass_UUID;
service.lpServiceClassId = &serviceID;
service.dwNumberOfCsAddrs = 1;
service.dwNameSpace = NS_BTH;
CSADDR_INFO csAddr;
memset(&csAddr, 0, sizeof(csAddr));
csAddr.LocalAddr.iSockaddrLength = sizeof(SOCKADDR_BTH);
csAddr.LocalAddr.lpSockaddr = pAddr;
csAddr.iSocketType = SOCK_STREAM;
csAddr.iProtocol = BTHPROTO_RFCOMM;
service.lpcsaBuffer = &csAddr;
if (0 != WSASetService(&service, RNRSERVICE_REGISTER, 0))
{
printf("Service registration failed....");
ostringstream stream;
stream << GetLastError();
string data= stream.str();
printf("%d\n", data.c_str());
}
else
{
printf("\nService registration Successful....\n");
}
HANDLE hRadio ;
BLUETOOTH_FIND_RADIO_PARAMS btfrp = { sizeof(BLUETOOTH_FIND_RADIO_PARAMS) };
HBLUETOOTH_RADIO_FIND hFind = BluetoothFindFirstRadio(&btfrp, &hRadio);
if ((hFind != NULL)&& (hRadio !=NULL))
{
if (BluetoothEnableDiscovery(hRadio,TRUE)){
printf("BluetoothEnableDiscovery() is working!\n");
}
if (BluetoothEnableIncomingConnections(hRadio,TRUE)){
printf("BluetoothEnableIncomingConnections() is working!\n");
}
if (BluetoothIsConnectable(hRadio)){
printf("BluetoothIsConnectable() is working!\n");
}
}
printf("\nBefore accept.........");
SOCKADDR_BTH sab2;
int ilen = sizeof(sab2);
SOCKET s2 = accept (s,(sockaddr*)&sab2, &ilen);
if (s2 == INVALID_SOCKET)
{
wprintf (L"Socket bind, error %d\n", WSAGetLastError ());
}
wprintf (L"\nConnection came from %04x%08x to channel %d\n",
GET_NAP(sab2.btAddr), GET_SAP(sab2.btAddr), sab2.port);
wprintf (L"\nAfter Accept\n");
char buffer[1024] = {0};
memset(buffer, 0, sizeof(buffer));
int r = recv(s2,(char*)buffer, sizeof(buffer), 0);
printf("%s\n",buffer);
closesocket(s2);
if (0 != WSASetService(&service, RNRSERVICE_DELETE, 0))
{
ostringstream stream;
stream << GetLastError();
string data= stream.str();
printf("%s\n", data.c_str());
}
closesocket(s);
WSACleanup();
return 0;
}
}
I use microsoft BT device btw..
Just to be sure: you said you're on WinXP... OK, but WinXP SP3 with Microsoft BT stack and appropriate dongle? or another XP version and another BT stack (like Widcomm or BlueSoleil...)?
In the later case, BT Socket API won't work...
Otherwise, not much to say about the code, except a missing BluetoothFindRadioClose...
I'm writing some networking code on Android using POSIX sockets but I'm getting a weird SIGSEGV (Signal 11, code 1) when I make a call to sento. I've used the Tombstone trace to determine which line it is, but frankly I can't see what's wrong with it.
References to i_Socket and i_Server have been successful before this particular snippet. I should also mention that the strings are coming from marshaled strings from Mono/Unity.
// Set client informaion
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; // We don't care IPv4 or IPv6
hints.ai_socktype = SOCK_DGRAM; // UDP Datagram packets
// Resolve server domain name
int res = getaddrinfo(server, TFTP_PORT, &hints, &i_ServerList);
// Check if we got a valid result
if (res != 0) {
// Report error
if (res == EAI_SYSTEM)
StreamingVideoPluginError("getaddrinfo");
else {
std::stringstream str;
str << "error in getaddrinfo: " << gai_strerror(res);
}
return 1; // No such host
}
// Loop through all entries and bind to the first one we can
bool didBind = false;
for (auto i_Server = i_ServerList; i_Server != nullptr; i_Server = i_Server->ai_next) {
// Try create the socket
if ((i_Socket = socket(i_Server->ai_family, i_Server->ai_socktype, i_Server->ai_protocol)) == -1) {
// Display error
StreamingVideoPluginError("client: socket creation failure");
i_Socket = -1; // Reassert invalid socket
continue;
}
else {
// Binded a socket
didBind = true;
break;
}
}
// Check if we could bind to a server
if (!didBind) {
StreamingVideoPluginError("Failed to bind to a server.");
return 2;
}
// Set socket options
struct timeval tv;
memset(&tv, 0, sizeof (struct timeval));
tv.tv_sec = 5; // 5 second timeout
if (setsockopt(i_Socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv) == -1)
{
std::stringstream str;
str << "client: could not set timeout. errno =" << errno;
StreamingVideoPluginError(str.str());
return 3;
}
// Make the initial TFTP request
char tftp_buffer[512 + 4];
// Set the opcode to be read request
int packetLength = 0;
tftp_buffer[0] = 0;
tftp_buffer[1] = TFTP_RRQ;
packetLength = 2;
// Place filename
memcpy(&tftp_buffer[packetLength],tftpFileName, strlen(tftpFileName));
packetLength += strlen(tftpFileName);
tftp_buffer[packetLength] = 0; packetLength++;
// Set transfer type to be octet
memcpy(&tftp_buffer[packetLength], TRANSFER_TYPE, strlen(TRANSFER_TYPE));
packetLength += strlen(TRANSFER_TYPE);
tftp_buffer[packetLength] = 0; packetLength++;
std::stringstream str;
str << "Value of packetLength =" << packetLength;
StreamingVideoPluginLog(str.str());
// Send the TFTP request
if (sendto(i_Socket, tftp_buffer, packetLength, 0, i_Server->ai_addr, i_Server->ai_addrlen) == -1) {
// Could not send TFTP request
StreamingVideoPluginError("client: could not send tftp request.");
return 4;
}
Here is the output from NDK-Stack
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000018
Stack frame #00 pc 0001e544 /data/app-lib/com.imersia-2/PLUGINNAME.so (ImersiaTftpDa
taSource::Init(char const*, char const*)+1292)
Stack frame #01 pc 0001d428 /data/app-lib/NOPENOPENOPE-2/PLUGINNAME.so (std::priv::_S
TLP_alloc_proxy<char*, char, std::allocator<char> >::~_STLP_alloc_proxy()+16)
addr2line blames
C:/NVPACK/android-ndk-r10/sources/cxx-stl/stlport/stlport/stl/_alloc.h:472
Found out the issue. I was accidentally rebinding i_Server inside the for loop.
for (auto i_Server = i_ServerList; i_Server != nullptr; i_Server = i_Server->ai_next) {
should be
for (i_Server = i_ServerList; i_Server != nullptr; i_Server = i_Server->ai_next) {
I have set a UDP non-blocking socket. I am creating the socket, binding it, and joining a multicast group like this:
int hopLimit = 1;
int bAllowMultiple = 1;
in_addr localAddr;
localAddr.s_addr = 0;
in_addr groupAddress;
groupAddress.s_addr = inet_addr(ADDRESS);
sockaddr_in groupEndPoint;
groupEndPoint.sin_family = AF_INET;
groupEndPoint.sin_addr = groupAddress;
groupEndPoint.sin_port = htons(PORT);
SOCKET udpsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(udpsocket == -1){
printf("Socket fail\n%d\n", errno);
return 1;
}
if(setsockopt(udpsocket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&hopLimit, sizeof(hopLimit))==-1){
printf("sockopt failed: IP_MULTICAST_TTL\n%d\n", errno);
return 1;
}
if(setsockopt(udpsocket, IPPROTO_IP, IP_MULTICAST_IF, (char *)&localAddr, sizeof(localAddr))==-1){
printf("sockopt failed: IP_MULTICAST_IF\n%d\n", errno);
return 1;
}
if(setsockopt(udpsocket, SOL_SOCKET, SO_REUSEADDR, &bAllowMultiple, sizeof(bAllowMultiple))==-1){
printf("sockopt failed: SO_REUSEADDR\n%d\n", errno);
return errno;
}
// Set to non-blocking mode
unsigned long bMode = 1;
if(ioctl( udpsocket, FIONBIO, &bMode )==-1){
printf("ioctl failed\n%d\n", errno);
return errno;
}
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 != 0)
{
printf("Bind failed\n%d\n", errno);
return errno;
}
// Join the multicast group
struct ip_mreq imr;
imr.imr_multiaddr = groupEndPoint.sin_addr;
imr.imr_interface.s_addr = groupEndPoint.sin_addr.s_addr;
r = setsockopt(udpsocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr));
printf("%d\n",r);
if (r == -1){
printf("sockopt failed: IP_ADD_MEMBERSHIP\n%d\n", errno);
return errno;
}
The first 3 setsockopt calls - MULTICAST_TTL, MULTICAST-IF and REUSEADDRESS - work fine, and it binds. When I then try to join the multicast group it returns errno 19 - Device Not Found. Changing the imr interface address to INADDR_ANY means the device is found, but the program won't receive packets. I've changed the ADDRESS, I know it is in the multicast range. eth0 on my machine has multicast enabled. I've tried using struct ip_mreqn imr and changed interface to address appropriately, no change. I ran a stack trace, but it's no more informative, just says setsockopt failed with errno 19.
Does anyone have any ideas? I'm a bit desperate here, I've been on this for way too long.
I'm trying to produce a simple server that will allow me test the Androids security features. I need to develop an application that will open a socket.
I've produced something similar in C, but I am having no look with java. Here's the application in C
// simpleserver3.c
#define MY_PORT 9999
#define MAXBUF 99
void indata(int clientfd, struct sockaddr_in client_addr)
{
char buffer[12];
printf("%s:%d connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
recv(clientfd, buffer, MAXBUF, 0); //this is will overflow the buffer
printf("%X \n", &buffer);
}
int main(int Count, char *Strings[])
{
struct sockaddr_in self, client_addr;
int sockfd,clientfd;
/*---Create streaming socket---*/
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) //socketfd = handle for socket
{
perror("Socket");
exit(errno);
}
/*---Initialize address/port structure---*/
bzero(&self, sizeof(self));
self.sin_family = AF_INET;
self.sin_port = htons(MY_PORT);
self.sin_addr.s_addr = INADDR_ANY;
/*---Bind the structure to the socket handle ---*/
if ( bind(sockfd, (struct sockaddr*)&self, sizeof(self)) != 0 )
{
perror("socket--bind");
exit(errno);
}
/*---Make it a "listening socket"---*/
if ( listen(sockfd, 20) != 0 )
{
perror("socket--listen");
exit(errno);
}
//set socklen_t to length of client address
socklen_t addrlen=sizeof(client_addr);
/*---accept a connection (creating a data pipe)---*/
clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen); //create handle for communicating
indata(clientfd, client_addr);
close(clientfd);
close(sockfd);
return;
}
Any sugguestion would be great, Aneel
It's been a while since I used C, so I can't comment on your C code, but you should probably take a look at the Android documentation for the Socket class:
http://developer.android.com/reference/java/net/Socket.html
Check out this example: http://thinkandroid.wordpress.com/2010/03/27/incorporating-socket-programming-into-your-applications/