I am trying to check whether a server is online or offline: I face the problem that it has a port when connecting to it
My code at the moment:
struct sockaddr_in address;
address.sin_len = sizeof(address);
address.sin_family = AF_INET;
address.sin_port = htons(25667);
address.sin_addr.s_addr = inet_addr("fr7.mooshroom.net");
Reachability *reachability = [Reachability reachabilityWithAddress:&address];
Please let me know what im doing wrong. And please dont link me to other questions, I have searched and none of them have what I'm looking for.
Basically the inet_addr() function does not do domain name resolution for you. You need to pass it an IP address (for example 127.0.0.1).
To resolve a DNS name into an IP address you need to look at the standard gethostbyname() functions.
To clarify:
struct hostent *host = gethostbyname("fr7.mooshroom.net");
if (host) {
struct in_addr in;
NSLog(#"HOST: %s" , host->h_name);
while (*host->h_addr_list)
{
bcopy(*host->h_addr_list++, (char *) &in, sizeof(in));
NSLog(#"IP: %s", inet_ntoa(in));
}
}
Now, having said all that, are you sure this is going to do what you want? Documentation for SCNetworkReachabilityRef suggests not:
http://developer.apple.com/library/ios/#documentation/SystemConfiguration/Reference/SCNetworkReachabilityRef/Reference/reference.html
"A remote host is considered reachable when a data packet, sent by an
application into the network stack, can leave the local device.
Reachability does not guarantee that the data packet will actually be
received by the host."
I have fixed it now, i needed to put the line:
const char *serverIPChar = [serverIP cStringUsingEncoding:NSASCIIStringEncoding];
and replace the "fr7.mooshroom.net" inside the inet_addr to serverIPChar. Thanks anyway
Related
I have a device that listen to UDP packets on port IN_PORT and echo the message on port OUT_PORT. I can communicate with it using a test software like Packet Sender.
I have to write a C++ library (Win32 at the moment) to communicate with the device. I made several tests but I still wasn't able to communicate. My guess is to use this workflow:
create socket
fill sockaddr_in structure with the device address, AF_INET family and the listeng port (OUT_PORT)
bind the socket
change sockaddr_in.sin_port with IN_PORT and send a packet (using sendto)
wait for an answer (using recvfrom)
repeat from 4
This works if I simulate the device with the Packet Sender utility working locally (device address = 127.0.0.1). I can't use the same workflow to connect to a remote address, even in the same subnet (e.g. my PC address: 192.168.1.2, remote PC address 192.168.1.5), since I get WSAEADDRNOTAVAIL error.
I've tested several different workflows, and read several discussions on the topic here and there, but none works, awfully.
Can someone give me some hints on the subject.
Thanks!
MIX
Your work flow is slightly wrong. It should be more like this instead:
create socket
fill sockaddr_in structure with the address of the local network adapter that is communicating with the device, AF_INET family, and the listenig port (OUT_PORT)
bind the socket
change sockaddr.sin_addr with device address, and sockaddr_in.sin_port with IN_PORT, and send a packet (using sendto)
wait for an answer (using recvfrom)
repeat from 4
I changed my code following Remy Lebeau hints. It works now. If someone will like to have a look and spot some weak points, or suggest improvements, I'll be glad (a code that "just works" is never enough; it must also "shine"!). Comments mark the previous (wrong) version of the code.
#pragma comment (lib, "Ws2_32.lib")
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <STRING>
#define IN_PORT 18
#define OUT_PORT 17
#define LOCAL_IP "10.0.10.108"
#define DEVICE_IP "10.0.10.104"
#define DEFAULT_BUFLEN 1024
int main(int argc, char *argv[])
{
WSADATA wsaData;
SOCKET sck;
struct sockaddr_in sckAddrInfo;
bool terminate;
char dataBuffer[DEFAULT_BUFLEN];
int rcvDataLength;
int sckAddrInfoLength;
WSAStartup(MAKEWORD(2,2), &wsaData);
sck = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
memset((&sckAddrInfo), 0, sizeof(sckAddrInfo));
sckAddrInfo.sin_family = AF_INET;
sckAddrInfo.sin_port = htons(IN_PORT);
//sckAddrInfo.sin_addr.s_addr = inet_addr(DEVICE_IP); // WRONG! Must bind local address
sckAddrInfo.sin_addr.s_addr = inet_addr(LOCAL_IP);
bind(sck, (struct sockaddr*)(&sckAddrInfo), sizeof(sckAddrInfo));
terminate = false;
sckAddrInfoLength = sizeof(sckAddrInfo);
while(!terminate)
{
printf("Write echo request: ");
gets(dataBuffer);
sckAddrInfo.sin_addr.s_addr = inet_addr(DEVICE_IP); // Must set device address, too, not just output port
sckAddrInfo.sin_port = htons(OUT_PORT);
sendto(sck, dataBuffer, strlen(dataBuffer), 0, (struct sockaddr*)(&sckAddrInfo), sizeof(sckAddrInfo));
memset(dataBuffer, '\0', DEFAULT_BUFLEN);
rcvDataLength = recvfrom(sck, dataBuffer, DEFAULT_BUFLEN, 0, (struct sockaddr*)(&sckAddrInfo), &sckAddrInfoLength);
printf("Device answer: %s\n", dataBuffer);
if(strcmp(dataBuffer, "quit") == 0)
terminate = true;
}
closesocket(sck);
WSACleanup();
return 0;
}
I am writing a kernel module that should receive messages from user-space and send response back via socket.
When program and module are on the same machine and I use IP 127.0.0.1, everything works fine. But when I try it on different machines and use real network IP, something like 192.168.3.146 it works only in one way.
I receive message from user-space, but I can not receive it from kernel. I use sock_sendmsg function for sending message from kernel and it's not return any error. Also I am not get any messages from firewall that something is came up from another machine, from kernel module.
Here were similar questions and examples, but they were not useful enough for me or examples were used too old kernel version.For skeleton I used this one,from UDP sockets: http://people.ee.ethz.ch/~arkeller/linux/multi/kernel_user_space_howto-3.html. Any help?
Kernel module code for sending:
void send_data(unsigned char *data)
{
if(!IS_ERR_OR_NULL(data))
{
int ret;
mm_segment_t oldfs;
struct msghdr message;
struct iovec ioVector;
struct sockaddr_in sendAddr;
sendAddr.sin_family = AF_INET;
sendAddr.sin_addr.s_addr = INADDR_ANY;
//sendAddr.sin_addr.s_addr = in_aton("192.168.1.75");
//here I get port from sk_buff structure that I received.
sendAddr.sin_port = *((unsigned short*)skBuffer->data);
memset(&message, 0, sizeof(message));
message.msg_name = &sendAddr;
message.msg_namelen = sizeof(sendAddr);
/* send the message back */
ioVector.iov_base = data;
ioVector.iov_len = strlen(data);
message.msg_iov = &ioVector;
message.msg_iovlen = 1;
message.msg_control = NULL;
message.msg_controllen = 0;
oldfs = get_fs();
set_fs(KERNEL_DS);
ret = sock_sendmsg(sendSocket, &message, strlen(data));
set_fs(oldfs);
}
}
I found an alternative solution, using netpoll sockets. It is more easier than sockets, I used before and it works. The answer and proper code is here, on another StackOverflow question.
I want to know if my server is online via my ios application. Here's what I'm doing:
Boolean result;
CFHostRef hostRef = CFHostCreateWithName(kCFAllocatorDefault, (__bridge CFDataRef)(serverIPAddress)); //serverIPAdress = "10.10.10.100:5010"
if(hostRef) {
result = CFHostStartInfoResolution(hostRef, kCFHostAddresses, NULL); // pass an error instead of NULL here to find out why it failed
}
if (!result) { //This means that the host was unreachable
return ;
}
My server is online and I can access it later on in the code(meaning that my connection to the server works perfectly fine). However, I want to be able to detect if my server, on a certain port, is reachable.
Also, if I remove the ":5010" from the ip address, it detects that my server is online (it doesn't go in the "!result" condition) and detects that my server is offline if I put "10.10.10.253" which corresponds to no ip address on my network.
How can I manage to determine if my server is online or not ?
I've looked at this question : Reachability with Address - Server AND Port - iOS 5 but it doesn't work since it always return that it is reachable no matter what ip address I enter
Thanks in advance
One approach could be to open a socket connection to a specific port to see if you get any response back. If not, then the destination is unreachable. For example
#include <arpa/inet.h> //for PF_INET, SOCK_STREAM, IPPROTO_TCP etc
CFRunLoopSourceRef gSocketSource;
void ConnectCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
{
UInt8 buffer[1024];
bzero(buffer, sizeof(buffer));
CFSocketNativeHandle sock = CFSocketGetNative(socket); // The native socket, used recv()
//check here for correct connect output from server
recv(sock, buffer, sizeof(buffer), 0);
printf("Output: %s\n", buffer);
if (gSocketSource)
{
CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
if (CFRunLoopContainsSource(currentRunLoop, gSocketSource, kCFRunLoopDefaultMode))
{
CFRunLoopRemoveSource(currentRunLoop, gSocketSource, kCFRunLoopDefaultMode);
}
CFRelease(gSocketSource);
}
if (socket) //close socket
{
if (CFSocketIsValid(socket))
{
CFSocketInvalidate(socket);
}
CFRelease(socket);
}
}
void ConnectSocket()
{
//socket
CFSocketContext context = {0, NULL, NULL, NULL, NULL};
CFSocketRef theSocket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketConnectCallBack , (CFSocketCallBack)ConnectCallBack, &context);
//address
struct sockaddr_in socketAddress;
memset(&socketAddress, 0, sizeof(socketAddress));
socketAddress.sin_len = sizeof(socketAddress);
socketAddress.sin_family = AF_INET;
socketAddress.sin_port = htons(5010);
socketAddress.sin_addr.s_addr = inet_addr("10.10.10.253");
gSocketSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, theSocket, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), gSocketSource, kCFRunLoopDefaultMode);
CFDataRef socketData = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)&socketAddress, sizeof(socketAddress));
CFSocketError status = CFSocketConnectToAddress(theSocket, socketData, 30); //30 second timeout
//check status here
CFRelease(socketData);
}
Basically, if the server is unreachable at that port, you will most likely get a kCFSocketTimeout for CFSocketError status. If you are looking to parse a specific response back from the server to determine if the server is ready or not, the ConnectCallBack function will be called upon successful socket connection.
This is just a simple example, make sure not to block the UI by calling socket connections on the main thread such as recv()
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
iPhone SDK reachabilityWithAddress issue
I am trying to determine if the iphone can connect to a particular IP address (Simple ping) using following code:
struct sockaddr_in server_address;
server_address.sin_len = sizeof(server_address);
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8888);
server_address.sin_addr.s_addr = inet_addr("192.168.105.44"); // ip address of a server on LAN
Reachability *r = [[Reachability reachabilityWithAddress:&server_address ] retain];
NetworkStatus internetStatus = [r currentReachabilityStatus];
But it always says that the status is 'Reachable' regarless of what I give in the IP address. Am I doing anything wrong? Why won't this work? Thanks in advance.
Same behavior
+ (Reachability*) reachabilityWithHostName: (NSString*) hostName;
Reachability will always return TRUE, doesn't matter if your HTTP return code will be 200 or 404. If you can not use the solution the link posted by Prince suggests, you can
Check your internet reachability
Fire a timer based HTTPRequest and check the return code
or check NetReachability.
Don't know if it helps you as it uses the same framework and I had no time to test it myself.
I'm writing simple program to communicate between smart devices and I receive 11001 when calling gethostbyaddr(). Both devices show they are connected to the same network, but from msdn document 11001 error is Host not found. No such host is known. Does anybody have any suggestion, thanks? My code is below.
void InitializeSocket()
{
WORD socketVersion;
WSADATA wsaData;
SOCKADDR_IN serverInfo;
int returnVal;
LPHOSTENT remotHost;
socketVersion = MAKEWORD(2,2);
WSAStartup(socketVersion, &wsaData);
in_addr iaHost;
//iaHost.s_addr = inet_addr("120.15.22.14");
iaHost.S_un.S_un_b.s_b1 = 120;
iaHost.S_un.S_un_b.s_b2 = 15;
iaHost.S_un.S_un_b.s_b3 = 22;
iaHost.S_un.S_un_b.s_b4 = 14;
remotHost = gethostbyaddr((const char *)&iaHost, sizeof(struct in_addr),
AF_INET);
if(iaHost.s_addr == INADDR_NONE)
{
MessageBox(NULL, TEXT("inet_addr has invalid address"),
TEXT("inet_addr"), MB_OK);
WSACleanup();
closesocket(theSocket);
return;
}
if(!remotHost)
{
returnVal = WSAGetLastError();
WSACleanup();
closesocket(theSocket);
return;
}
theSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(theSocket == INVALID_SOCKET)
{
returnVal = WSAGetLastError();
WSACleanup();
closesocket(theSocket);
return;
}
serverInfo.sin_family = AF_INET;
serverInfo.sin_addr = *((LPIN_ADDR)*remotHost->h_addr_list);
serverInfo.sin_port = htons(8888);
//Connect to the server
returnVal = connect(theSocket, (LPSOCKADDR)&serverInfo,
sizeof(struct sockaddr));
if(returnVal == SOCKET_ERROR)
{
returnVal = WSAGetLastError();
WSACleanup();
closesocket(theSocket);
return;
}
}
Error 11001 is a generic DNS lookup error so I have only one question. Does the 120.15.22.14 address actually exist in DNS?
You can find this out by typing
nslookup 120.15.22.14
from the command line.
If you get an error, it's because DNS doesn't know anything about those addresses, so a gethostbyaddr() will not be able to give you any information.
Update:
Answering your points:
I just type nslookup 120.15.22.14, but it returns back as cant find 120.15.22.14. Non-existent domain.
Since nslookup 120.15.22.14 returns an error, there is no entry in DNS for that IP address. That's your problem.
I look at my device settings for the DNS and it sets to 120.20.32.10 which is different 120.15.22.14 so does it mean I haven't configured the DNS?
If 120.20.32.10 is what's in DNS for your device, and 120.15.22.14 is the actual address, then DNS is wrong. Plain and simple. Fix DNS.
will it produce the same result if I use gethostbyname() instead of gethostbyaddr()?
If you want to turn a DNS name into an IP address, use gethostbyname(). To turn an IP address into a DNS name, use gethostbyaddr().
For connecting to a remote host, you would normally use the gethostbyname() call since the IP address of the host could change at any time. Provided DNS always accurately represents the IP address of that host, that's the preferred way.
I just type nslookup 120.15.22.14, but it returns back as cant find 120.15.22.14. Non-existent domain.
I look at my device settings for the DNS and it sets to 120.20.32.10 which is different 120.15.22.14 so does it mean I haven't configured the DNS?