Why is networking so slow in this Fig/Docker container? - ruby-on-rails

I'm using Fig and Docker to containerise a sample Rails app. Currently, it works fine, the database and server start up. When I have an active Internet connection it all works perfectly. However when I don't have an Internet connection it takes a long time to connect (20 seconds from the browser requesting the localhost page) to the Rails/WEBrick server.
I've looked into the logs and nothing is out of the ordinary. It just takes a long time for the container to receive the initial connection and furthermore a long time to transmit the data.

Okay, I tested it, and it was because of DNS resolution. When you "disable" typical Google DNS and instead use localhost, the latency goes away. This is probably because without doing this Docker assumes that 127.0.0.1 is some address that needs to be looked up via a NS, and spends a lot of time waiting for a response (presumably because it sent it via UDP, it waits longer because of lost/dropped packets). This is also why the request wasn't recorded immediately, as DNS is at a lower-level on the net stack.

Related

iOS - NSURLConnection connections to more than 5 different IPs over LAN

My app tries to determine the IP of a web server located on the same LAN when it starts up.
It works out the IP range to scan, and uses NSURLConnection objects with a 1 second time out to determine whether an IP is reachable, and if it is, try to call a service on it, if the service call is successful then we know we've found the correct IP.
The problem though is that the app cannot open more than 5 connections at a time, even though all the connections have different IPs to connect to. I would get about a dozen connections firing off but the rest will just report The request timed out. without ever leaving the device.
I have read that this restriction applies to NSURLConnection connections to a single IP address, but as I said, each connection has its own different IP.
I have also tried using the SCNetworkReachability to determine whether an IP is reachable but all it tells me is that the IP addresses on the LAN are reachable, in theory, without making an actual connection.
Are there reliable ways to connect to more IPs at a time?
Every operating system maintains a maximum number of sockets per process. I couldn't find an authoritative source for iOS, but it would make sense for Apple to keep that number very low and five seems to be a common answer by others trying this.
You may want to look at NSOperationQueue to manage the connections (see Asynchronous HTTP Client Using NSOperationQueue) or use AFNetworking to do all the real work.

Asyncronously send file over TCP connection

so I'm making an iOS app, but this is more of a general networking question.
So what I have is one phone that acts as the server and then a bunch of phones connect to the phone as the client. Basically it's a game/music sharer.
It's kind of hard to really get into the semantics of it, but that isn't important.
What is important is that the server and client are repeatedly sending each other commands and positions rapidly over a TCP connection, and sometimes the client wants to send the server a music file (4MB usually) to play as the music.
The problem I initially encountered was that when sending the large file, it would hang the sending of commands from the client to the server.
My naive solution was to create another socket to connect to the server to send the file to the server, the server would check the IP of the new socket, and if it has the IP of an existing connection then it would just tie it to that connection, receive the file, and then disconnect the socket.
But the problem with this is that it takes a 1-2 second delay for the socket to connect, and I'm aware that there are man-in-the-middle attacks that can occur.
Is there a more elegant solution to this problem?
I would not call your solution naive, this is largely how FTP works, separating data and control paths is a good design pattern in my view.
I wouldn't worry about the man in the middle thing. If you wanted, you could add a command to the client that it responds to over the data connection with a secret the server supplies, this would let you associate the connections without using the ip addressing.
If the delay is a problem then why not establish both connections at the start, the overhead of a few tcp connections on an operating system is not usually significant.
You could also use the two connections for both commands and data, alternating between them. Since both the server and client know when a connection is busy they can choose to use the idle one. The advantage of this is that it will keep both connections busy to ensure they are both known to be working.
You probably should also use a different thread for each socket but I suspect you are doing this since it won't work too well without it.

Monitoring Remote Folder over SFTP in a Rails App

As the title says, I need to monitor a remote folder for new files through a SFTP connection.
I setup a daemon process that opens a connection and if it finds any files then it retrieves their contents and if it doesn't then it sleeps for 5 seconds. This works fine it just hovers around 4% CPU usage. Is there a better way to do this and is it bad to keep a connection like this open indefinitely?
That's probably the best thing you can do, given the circumstances. When watched directories get bigger, your daemon will likely run slower and consume more resources.
A single persistent connection is nothing, both on client and server. But if there are many clients, server may slow down.
If you control the other server, a much better way would be to install a daemon on it. Local process can listen to filesystem notifications and broadcast to connected watchers.

SmtpClient.Timeout on MonoTouch (iOS), does not seem to have any effect, am I doing it wrong?

I am building a "test" button to verify SMTP configuration in an app.
If the user types in an incorrect port number, switches SSL on/off to the incorrect state, or types in a valid domain name, but one that isn't hosting an SMTP server, the app hangs, waiting for a timeout.
Basically, it found a server, but is unable to connect to the specified port.
This timeout seems to be about 1 minute 15 seconds in this case.
I tried setting the timeout like this:
var client = new SmtpClient(hostname, port);
client.Timeout = 15000; // milliseconds
but the timeout is still around 1 minute 15 seconds.
Is there anything else I need to configure?
Note that while I can use "SendAsync" to avoid the hang, I still want to use a bit lower timeout in this case.
This could be related to DNS resolution which is done synchronously. You can confirm this easily by using an IP address, instead of a host name, and see if the timeout gets closer to the expected 15 seconds.
If that's the case then a possible alternative, that I have not tested under iOS, could be to use Mono.Dns.

Localhost is taking abnormally long time to load any page

The logs don't show anything different, and the computer is four times faster than the last one. Anyone know any common reasons why making a request to localhost would take a very long time?
I am using Mongrel.
Hard to give a solution based on the little information you give, so try to narrow it down. I would say that these three causes seem the most likely:
the database is slow. You can check this if your queries take a long time (check the logs). Perhaps you are using a slow connector (i.e. the default Ruby MySQL library), or your indexes haven't made it to your new machine.
Mongrel is slow. Check by starting it with Webrick and see if that's any better
your computer is slow. Perhaps it's running something else that's taking up CPU or memory. See your performance monitor (application to use for this differs per OS).
Could be a conflict between IPv4 and IPv6. If you're running Apache you have to take special steps to make it work nicely with IPv6 (my information here might be out of date.) I've found that an IPv6-enabled client would try to talk IPv6 to the server, and Apache would not receive the request. After it timed out the client would retry on IPv4.

Resources