libmemcached - checking if I'm connected - memcached

Is there an easy way to check if a given memcached_st* is successfully connected to a memcached server?
I'm connecting via memcached_server_add_with_weight, and it's returning MEMCACHED_SUCCESS when I give it spurious hostnames. Similarly, calling memcached_last_error_errno immediately after the call to memcached_server_add_with_weight gives me MEMCACHED_SUCCESS.

One interesting way to do this is checking the actual socket descriptor.
If libmemcached successfully connected to the server then the socket descriptor is positive, otherwise it is -1.
std::shared_ptr<memcached_st> es (memcached_create (NULL), [](memcached_st* msp) {memcached_free (msp);});
memcached_server_add_with_weight (es.get(), "server1", 9201, 100);
memcached_server_add (es.get(), "server2", 9201);
memcached_server_add (es.get(), "server3", 9201);
memcached_server_fn serverVisitor = [](const memcached_st *ptr, memcached_server_instance_st server, void *context) {
if (server->fd < 0) throw std::runtime_error (std::string ("libmemcached connection to ") + server->hostname + " failed!");
return MEMCACHED_SUCCESS;
};
memcached_server_cursor (es.get(), &serverVisitor, NULL, 1);

Related

connect() - IP blocked, how to connect using hostname?

when I try to connect to a webserver, my "FritzBox" (residential gateway device) is configured to block all connections that connect directly to an IP, not a host name.
However, the connect() function only lets me connect using an IP address.
How can I connect() to a server using the host name (the way web browsers do)?
Many thanks.
... my "FritzBox" (residential gateway device) is configured to block all connections that connect directly to an IP, not a host name...
It looks like you are trying to bypass the settings of the child protection feature of the Fritzbox. What these settings mean in reality is that it will only allow HTTP connections which have a real hostname inside the Host-header of the HTTP-Request and not connections containing an IP only, i.e. it will allow http://example.com/ but not http://10.10.10.10/. For an example of the Host header look at the HTTP example request at Wikipedia.
First of all connections are always connecting to an IP address, not a host name. So your gateway is doing something else than what you're telling us, it can't tell the difference on how a client connects to something. What it could do is inspect certain protocols specifically, e.g. look for a Host: header in HTTP requests.
But to answer your question: You need to look up the host name with DNS and convert it to an IP address. This can be done all in one go by the getaddrinfo() function, getaddrinfo() will perform lookups in a platform specific way by e.g. looking at host files and/or do DNS lookups: e.g.
int clientfd;
struct addrinfo hints, *servinfo, *p;
int rc;
const char *port = "80";
const char *host = "www.google.com";
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rc = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
exit(1);
}
// getaddrinfo() can map the name to several IP addresses
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((clientfd= socket(p->ai_family,
p->ai_socktype,p->ai_protocol)) == -1) {
perror("socket()");
continue;
}
if (connect(clientfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
continue;
}
break; //got a connection
}
if (p == NULL) {
fprintf(stderr, "connect() failed\n");
exit(2);
}
freeaddrinfo(servinfo);
//use clientfd

how to check if connection is established when use libev with non-block socket

I have some code use libev on how to deal with connection timeout as below (please refer to http://lists.schmorp.de/pipermail/libev/2011q2/001365.html):
sd = create_socket()
set_socket_nonblock(sd)
connect("127.0.0.1", port) // connect to an invalid port
ev_io_init(&w_io, connect_cb, sd, EV_WRITE)
ev_io_start(...)
ev_timer_init(&w_timer, timeout_cb, 5.0, 0)
ev_timer_start(...)
and in someplace perform ev_run. The connect_cb is called and in this callback function I checked the revents with EV_ERROR, the result is no error. This is strange because I provide an invalid port number which is not listening in local machine. Anyway, I try to send a message in the connect_cb function, got an error 111, which means that connection refused. I'm confused! How to check if the connection is established correctly when use non-block socket?
getsockopt is possible way to get if the connection has some error happen:
int err;
socklen_t len = sizeof(err);
getsockopt(sd, SOL_SOCKET, SO_ERROR, &err, &len);
if (err) {
// error happen
} else {
connection is OK
}

RMI and 2 machines - two way communication

I've got problem with RMI comunication between 2 machines (win 7 and win xp VM). The exception with I have problem is:
java.rmi.ConnectException: Connection refused to host: 169.254.161.21; nested exception is:
java.net.ConnectException: Connection timed out: connect
It's really weired because during connection I use address 192.168.1.4 (server), but exception somehow show sth different. I disabled firewall on both side. Ping working to both side. I tried telnet to server and use server port:
telnet 192.168.1.4 1099 and it's working... I can't figure out where the problem is.
If I run this on host side (eg server side) everything works fine.
How is it look from SERVER:
public class Server
{
public static void main(String args[])
{
InputStreamReader is = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(is);
String portNum, registryURL;
try{
System.out.println("Enter the RMIregistry port number:");
portNum = (br.readLine()).trim();
int RMIPortNum = Integer.parseInt(portNum);
startRegistry(RMIPortNum); // Registry registry = LocateRegistry.createRegistry(RMIPortNum);
ServerSide_Impl exportedObj = new ServerSide_Impl();
registryURL = "rmi://localhost:" + portNum + "/callback";
//registryURL = "rmi://192.168.1.4:" + portNum + "/callback";
Naming.rebind(registryURL, exportedObj);
System.out.println("Callback Server ready.");
}// end try
catch (Exception re) {
System.out.println(
"Exception in HelloServer.main: " + re);
} // end catch
} // end main
//This method starts a RMI registry on the local host, if
//it does not already exists at the specified port number.
private static void startRegistry(int RMIPortNum) throws RemoteException
{
try
{
Registry registry = LocateRegistry.getRegistry(RMIPortNum);
registry.list( );
// This call will throw an exception
// if the registry does not already exist
}
catch (RemoteException e)
{
Registry registry = LocateRegistry.createRegistry(RMIPortNum);
}
} // end startRegistry
} // end class
Client side is look like:
try
{
this.serverAd = serverAddress.getText();
String path = System.getProperty("user.dir");
String pathAfter = path.replace("\\", "/");
String pathFile = "file:/"+pathAfter + "/wideopen.policy";
System.setProperty("java.security.policy", pathFile);
System.setSecurityManager(new RMISecurityManager());
this.hostName = hostNameTextField.getText();
this.portNum = hostPortNumberTextField.getText();
RMIPort = Integer.parseInt(this.portNum);
this.time = Integer.parseInt(timeTextField.getText());
//this.registryURL = "rmi://localhost:" + this.portNum + "/callback";
String registryURLString = "rmi://"+this.serverAd+":" + this.portNum + "/callback";
this.registryURL = registryURLString;
ConsoleTextField.append("\n"+ this.registryURL + "\n");
// find the remote object and cast it to an
// interface object
obj = (ServerSide_Interface)Naming.lookup(this.registryURL);
boolean test = obj.Connect();
if(test)
{
callbackObj = new ClientSide_Impl();
// register for callback
obj.registerForCallback(callbackObj);
isConnected = true;
ConsoleTextField.append("Nawiązano połaczenie z serwerem\n");
TableModel modelTemp = obj.Server_GenerateStartValues();
myDataTable.setModel(modelTemp);
myDataTable.setEnabled(true);
}
else ConsoleTextField.append("Brak połączenia z serwerem\n");
}
catch (Exception ex ){
ConsoleTextField.append(ex + "\n");
System.out.println(ex);
}
This connection is working fine if I run client on host side. If I use VM and try connect between 2 different machines, I can;t figure out what did I do bad
There is something wrong with your etc/hosts file or your DNS setup. It is providing the wrong IP address to the server as the server's external IP address, so RMI embeds the wrong address into the stub, so the client attempts to connect to the wrong IP address.
If you can't fix that, you can set the system property java.rmi.server.hostname to the correct IP address at the server JVM, before exporting any RMI objects (including Registries). That tells RMI to embed that address in the stub.

connect and send on the socket succeeds, even if WIFI not enabled and server is only reacheable in the wireless network - Windows Mobile 6.5 - C/C++

I wrote a small C/C++ Windows Mobile 6.5 client-application that is connecting to a server and sends some data to this server. The server is in my internal wireless network and is not reacheable outside.
The weird behaviour I'm having:
1) Even if the WIFI is not started on my mobile device, the connect() from the client-application returns success (!= SOCKET_ERROR), which is not the case b/c the server is reacheable only in the wireless network.
2) If the WIFI is not started on my mobile device, if there is a Sleep(1000) between the connect() and the send(), the send() fails with WSAECONNRESET, BUT if there is no Sleep() between the connect() and send() the send() succeeds! (only when doing the read() I finally get the WSAECONNRESET error).
Can somebody pls point me some tips why do I have this behaviour. It's pretty scary that without actually being able to reach the server I still get success for the connect() and for the send() :(
As requested, here is a sample code:
#include <windows.h>
#include <Winsock2.h>
#include "dbgview.h"
# define FxMemZero(buf,len) RtlZeroMemory ((VOID*)(buf),(SIZE_T)(len))
# define FxMemCopy(dst,src,len) RtlCopyMemory ((VOID*)(dst),(CONST VOID*)(src),(SIZE_T)(len))
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
SOCKET proxy_connection;
WSADATA wsadata;
if( 0 != WSAStartup (MAKEWORD(1, 1), &wsadata))
return -1;
proxy_connection = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
if(proxy_connection == INVALID_SOCKET) {
// error creating the socket
DbgViewTraceError((L"main", L"error creating socket."));
return -1;
}
// try to connect
UINT proxy_ip_ = 0x00000000;
CHAR* proxy_0_ = "192.168.1.105";
UINT proxy_port = 3100;
// get the proxy ip
{
struct hostent *he_;
if((he_ = gethostbyname(proxy_0_)) == NULL) {
DbgViewTraceWarning((L"main", L"error %d resolving hostname %hs", WSAGetLastError(), proxy_0_));
return -1;
}
FxMemCopy((PBYTE)&proxy_ip_, (PBYTE)he_->h_addr, he_->h_length);
}
// prepare the connection data
sockaddr_in saddr_;
FxMemZero(&saddr_,sizeof(sockaddr_in));
saddr_.sin_family = AF_INET;
saddr_.sin_addr.S_un.S_addr = proxy_ip_;// address
saddr_.sin_port = htons((USHORT)proxy_port);
// do the conection
if(SOCKET_ERROR == connect(proxy_connection, (SOCKADDR*) &saddr_, sizeof(saddr_))) {
// error connecting to the proxy
DbgViewTraceWarning(( L"main", L"error %d connecting to %hs:%d", WSAGetLastError(), proxy_0_, proxy_port));
closesocket(proxy_connection);
proxy_connection = INVALID_SOCKET;
return -1;
}
DbgViewTraceInfo(( L"main", L"SUCCESS. connected to %hs:%d.", proxy_0_, proxy_port));
CHAR* buffer_ = "Momo";
UINT count_ = strlen(buffer_);
DWORD total_ = 0;
DWORD sent_ = 0;
while(total_ < count_) {
// ISSUE: IF the WIFI is not started on the mobile, the connect returns success AND the send() returns success, even though with putty
// on the mobile, a telnet on 192.168.1.105:3100 will fail with: "Network error: Connection reset by peer"
// IF I add a long-enough Sleep() between the connect() and the send(), the send() will fail with: WSAECONNRESET
//Sleep(5000);
if(SOCKET_ERROR == (sent_ = send(proxy_connection, (const char*)buffer_ + total_, count_ - total_, 0))) {
// error sending data to the socket
DbgViewTraceError((L"main", L"error %d sending data to proxy", WSAGetLastError()));
return -1;
}
total_ += sent_;
}
DbgViewTraceInfo((L"main", L"send() SUCCESS"));
return 0;
}
The results are:
1) Without Sleep():
main [INFO ] SUCCESS. connected to 192.168.1.105:3100.
main [INFO ] send() SUCCESS
2) With Sleep():
main [INFO ] SUCCESS. connected to 192.168.1.105:3100.
main [ERROR ] error 10054 sending data to proxy
So the questions are:
1) Why the connect() succeeds? How can I be sure that there is actually a real connection?
2) Why the send() succeeds?
3) Why with a Sleep() in between connect() and send() the behaviour is different?
The problem seems to be ActiveSync. If ActiveSync is running, I get the behavior described above (connect() and send() report success, even though they are not). If ActiveSync is not running, gethostbyname() fails with:
WSAENETDOWN -> if WIFI is disabled
WSAHOST_NOT_FOUND -> if WIFI is enabled
which is correct!
How can this be? What is ActiveSync doing that is ruining everything? How can I avoid this problem? I mean, I can't be sure that the user is running my application when there is no ActiveSync running, so what can I do to avoid this behavior when ActiveSync is running?
Thx,
MeCoco
Looks like you are at least misusing struct sockaddr_in. Try more modern API for address conversion - Windows has InetPton - and see if that fixes the issues.

SO_REUSEADDR with UDP datagrams - Resource unavailable

I'm using SO_REUSEADDR option, but I'm not sure why am getting
Resource temporary unvailable option.
I'm testing client server code on 127.0.0.1
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 )
{
perror("socket() error!!\n");
exit(1);
}
if ( setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse) ) < 0 ) {
perror("SO_REUSEADDR failed::");
exit(1);
}
while(1) {
nbytes_read = recvfrom(sockfd, (void *)&recvd_msg, sizeof(recvd_msg),
flags, &from, &from_len);
printf("nbytes_read = %d\n", nbytes_read);
if(nbytes_read == -1) {
perror("client: recvfrom() failed");
return FAILED;
}
if (nbytes_read > 0) {
if(recvd_msg.hdr.msgtype == DATA)
printf("recvd %d bytes from server\n", recvd_msg.hdr.payload_size);
ftp_show_payload(&recvd_msg);
}
if(recvd_msg.hdr.is_last == TRUE) {
break;
}
}
Error message:
" client: recvfrom() failed: Resource temporarily unavailable"
errno:11
After trying to run client for 3-4 times, I get the data, I'm not sure whats happening.
Also, this problem is on Ubuntu Linux, but when I run the same client server on Solaris,
it works fine!!
SO_REUSEADDR is useful when you use bind(), but here you are not using bind.
I dont see any problem if recvfrom() returns -1
Use bind() and replace your call recvfrom() with recv(). recv() will receive all the packets at the port you used in your bind call.
Are you trimming out any other socket configuration? EAGAIN is typically returned when you read a non-blocking socket and there's no data available. The manpage for recvfrom lists the possible errnos that will be set on failure with an explanation for each one.
Your test is invalid. recvfrom() can return zero, which doesn't indicate an error. It is only valid to call perror() if you get -1. So you may not have a problem at all ..
I don't see why you're using SO_REUSEADDR at all here, as you're not binding to a specific port.