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.
Related
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
I just installed openfire server in my Suse-Linux EC2 instance and I've configured the openfire server by creating one user named 'balaji' in addition to the admin.
I then installed the ilibjingle code for the iOS platform and I was able to build it. I ran it in the simulator and it worked perfectly for my gmail-id. It logged in, then brought the users from the roster list.
I then modified the code to point to my openfire server IP address and gave the username as 'balaji' (the one I created in openfire) and the appropriate password. I also have a self signed SSL certificate in the openfire server. When I ran this code, it was able to connect, but not able to login (I believe). The ilibjingle code is supposed to go from Connect to Login to LoggedIn to the Roster list. When I ran with my openfire server, it went from Connect to Login, but nothing beyond that.
What could have possibly gone wrong? Should I modify anything in my openfire server to make this work? Here's my iPhone code.
In the rootviewcontroller.mm, I have the following snippet.
-(void) _mainGtalkThread:(id)sender
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//you need to setup name and passwd manuelly here
char *name = "balaji";
char *password = "mypasswd";
[self gtalk_main:(char*)name userpassword:(char*)password];
[pool release];
}
-(int) gtalk_main:(char*)un userpassword:(char*)password
{
// This app has three threads. The main thread will run the XMPP client,
// which will print to the screen in its own thread. A second thread
// will get input from the console, parse it, and pass the appropriate
// message back to the XMPP client's thread. A third thread is used
// by MediaSessionClient as its worker thread.
buzz::Jid jid;
talk_base::InsecureCryptStringImpl pass;
std::string username = un;
if (username.find('#') == std::string::npos) {
username.append("#localhost");
}
jid = buzz::Jid(username);
if (!jid.IsValid() || jid.node() == "") {
printf("Invalid JID. JIDs should be in the form user#domain\n");
return 1;
}
pass.password() = password;
buzz::XmppClientSettings xcs;
xcs.set_user(jid.node());
//xcs.set_resource("call");
xcs.set_host(jid.domain());
xcs.set_pass(talk_base::CryptString(pass));
xcs.set_use_tls(false);
xcs.set_allow_plain(true);
xcs.set_server(talk_base::SocketAddress("50.37.185.206", DEFAULT_PORT));
printf("Logging in as %s with user as %s\n", jid.Str().c_str(), jid.node().c_str());
talk_base::InitializeSSL();
talk_base::Thread athread;
talk_base::ThreadManager::SetCurrent(&athread);
talk_base::Thread* main_thread = talk_base::Thread::Current();
assert(main_thread!=NULL);
XmppPump pump;
//CallClient *client = new CallClient(pump.client());
gtalkClient_ = new gtalkClient(pump.client(), self);
pump.DoLogin(xcs, new XmppSocket(true), NULL);
main_thread->Run();
return 0;
}
and in another file 'gtalkclient.mm', I have the following:
gtalkClient::gtalkClient(buzz::XmppClient* xmpp_client, void * controller) :
xmpp_client_(xmpp_client), controller_(controller), media_engine_(NULL),
media_client_(NULL), call_(NULL), incoming_call_(false), auto_accept_(false),
pmuc_domain_("conference.localhost"), local_renderer_(NULL), remote_renderer_(NULL),
roster_(new RosterMap), portallocator_flags_(0)
{
xmpp_client_->SignalStateChange.connect(this, >alkClient::OnStateChange);
}
void gtalkClient::OnStateChange(buzz::XmppEngine::State state)
{
RootViewController * tvc = (RootViewController*)controller_;
switch (state) {
case buzz::XmppEngine::STATE_START:
printf("connecting...");
[tvc.roster_ removeAllObjects];
[tvc.roster_ addObject:#"connecting..."];
[tvc reloadTableViewData];
break;
case buzz::XmppEngine::STATE_OPENING:
printf("logging in...");
[tvc.roster_ removeAllObjects];
[tvc.roster_ addObject:#"logging in..."];
[tvc reloadTableViewData];
break;
case buzz::XmppEngine::STATE_OPEN:
printf("logged in...");
[tvc.roster_ removeAllObjects];
[tvc.roster_ addObject:#"logged in..."];
[tvc reloadTableViewData];
InitPhone();
InitPresence();
// prepare to add roster
[tvc.roster_ removeAllObjects];
break;
case buzz::XmppEngine::STATE_CLOSED:
buzz::XmppEngine::Error error = xmpp_client_->GetError(NULL);
printf("logged out...%s", strerror(error).c_str());
[tvc.roster_ removeAllObjects];
[tvc.roster_ addObject:#"logged out..."];
[tvc reloadTableViewData];
Quit();
}
}
I also had the same issue while am running libjingle sample program with my openfire server.Its because newer version of libjingle didn't support the certificates of unknown authorities.
So you need to undo the changes made on xmppsocket.cc on rev65 (when libjingle was updated to version 0.5.6):
This link will help you to see difference between two version
http://code.google.com/p/libjingle/source/diff?spec=svn95&r=65&format=side&path=/trunk/talk/examples/login/xmppsocket.cc&old_path=/trunk/talk/examples/login/xmppsocket.cc&old=30
In this commit, they removed two lines that were allowing certificates of unknown Certificate Authorities.
I got solved the problem by following the above instructions
Or you can follow the below link to get the complete idea.
http://code.google.com/p/libjingle/issues/detail?id=250.
I want to establish tcp connection between iphone and PC. On PC QTspServer is running and working (was tested with other client application).
Here is the connection method i'm using on iphone:
- (IBAction)connectToServer:(id)sender {
CFReadStreamRef read = NULL;
CFWriteStreamRef write = NULL;
NSString *host = #"192.168.1.169";
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)host, 1000, &read, &write);
CFWriteStreamOpen(write);
int k = 0;
}
The server on PC is not reacting. Any help is appropriate
By the way: Server is nothing more then a QTcpServer with replemented incomingConnection method. Here is the main function on server side:
int main(int argc, char **argv)
{
QApplication app(argc, argv);
AbstractServer server;
server.listen(QHostAddress::Any, 1000);
QLabel label("Hello server");
label.setFixedSize(400, 400);
label.show();
return app.exec();
}
The connection is established after something was sent to the server
Check that write isn't NULL after the call to CFStreamCreatePairWithSocketToHost. If it is, the socket connection is failing.
-(IBAction)connectToServer:(id)sender {
CFWriteStreamRef write = NULL;
NSString *host = #"192.168.1.169";
int port = 1000;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)host, port, NULL, &write);
if (!write) {
// connection failed.
NSLog(#"Connection to %#:%d failed.",host,port);
} else {
CFWriteStreamOpen(write);
// keep a reference to the output stream for later use.
self.output = (NSOutputStream*)write;
// the function that made the output stream has "Create" in its name, so
// this method owns the write stream & should release it.
CFRelease(write);
}
}
Note that I store the output stream in a property of self. In your sample code, the stream isn't saved anywhere. You don't release it, so it still exists when the method exits, but there's no way of accessing it. If the sample -connectToServer: is representative, that error will prevent your object from sending anything to the server.
I do have a java server. I am trying to build IPhone application that connect to the server. Also sends and receives messages. I a little confused about using CFReadStreamRef and CFWriteStreamRef. How can I pair the socket with the streams successfully. This is what i have:
fd = socket(AF_INET, SOCK_STREAM, 0);
emset(&addr, 0, sizeof(addr));
addr.sin_len = sizeof(addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);//0;
inet_aton("192.168.1.101", &addr.sin_addr.s_addr);
CFSocketContext context = { 0, self, NULL, NULL, NULL };
listeningSocket = CFSocketCreateWithNative( NULL, fd,kCFSocketConnectCallBack, AcceptCallback, &context);
CFDataRef connectAddr = CFDataCreate(NULL, (unsigned char *)&addr, sizeof(addr));
CFSocketConnectToAddress(self.listeningSocket, connectAddr, -1);
// As soon as i get the Connect call back into my function I try to pair the streams to the socket
CFReadStreamRef readStreamm;
CFWriteStreamRef writeStreamm;
CFStreamCreatePairWithSocket(NULL, CFSocketGetNative(listeningSocket), &readStreamm, &writeStreamm);
[readStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[writeStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[readStream open];
[writeStream open];
However when i try to write or read from the stream is returning an error (-1). Another question I have if I use readStream or writeStream open, and if it was successful. Is that mean that I am already connected to the server?? or do I actually have to call CFSocketConnectToAddress . I am just trying to figure out if i need to use both the connectToAdderss and stream open. Or I should use one or the other.
Thanks in advance.
I recommend using cocoaasyncsocket. Its is a lightweight wrapper to make socket-based communication much easier. Just now I am workin on communication between iPhone and a network device. It works flawless.
[sock writeData:[#"Hello World" dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:1];
Going through the implementation of cocoaasyncsocket. The socket has to be closed before opening the read/write streams. I used the CFSocketConnectToAddress, then invalidate and release the socket. Then establish my streams. qoute:
// Invalidate and release the CFSocket - All we need from here on out is the nativeSocket
// Note: If we don't invalidate the socket (leaving the native socket open)
// then theReadStream and theWriteStream won't function properly.
// Specifically, their callbacks won't work, with the exception of kCFStreamEventOpenCompleted.
// I'm not entirely sure why this is, but I'm guessing that events on the socket fire to the CFSocket we created,
// as opposed to the CFReadStream/CFWriteStream.
CFSocketInvalidate(listeningSocket);
CFRelease(listeningSocket);
listeningSocket = NULL:
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?