Tried to play civ 5 mp with a friend this weekend over hamachi. Although we spent about day overall on it we couldn't get it to work. Just thought I would document our findings in case it helps anyone or anybody had any input.
Firstly, these tests were conducted on two relatively recent machines running windows 7 with full copies of civ5.
Upon initial setup of hamachi we established both peers could ping each other. We started civ. Neither of us could discover the other's game.
Netstat output indicated that the game listens on UDP port 62900. Other ports maybe involved but this seems pretty certain. The ports the game uses seems to be totally undocumented (not even a readme!).
It seemed logical to establish that udp broadcast packets were being blocked before drawing any more conculsions. To do this I wrote a humble java program that has two modes. A "broadcast" mode that sends "hello world! i am [hostname]" message in a udp packet to 255.255.255.255 (the general broadcast address) and then awaits a response from a listener on another machine. The second mode is a listener that awaits a message and then sends a response "hello i am [hostname]" to the broadcaster.
The output should look like:
broadcaster:
broadcasting
sending message "Hello world! I am [hostname]"
awaiting message
received message:
"Hello I am [otherhostname]"
sending message ...
[etc]
responder:
listening
awaiting message
received message:
"Hello I am [otherhostname]"
sending message "Hello I am [hostname]"
The point of this is to model at least conceptually clients broadcasting to servers "who is serving civ5?" and then connecting up.
We tried this program. It didnt work until we *completly* removed the gateway entry under the hamachi network adapter settings -> ipv4 -> advanced. I suspect this is because the "gateway" whatever it represents on hamachi was winning out over the broadcast entry in the routing table. For some reason this gateway cannot forward broadcast packets. Note when doing this windows will suddenly decide it cannot recognise the network and will force it into "public" mode, bringing a load of firewall rules into force. For simplicity, we disabled the firewall at this point.
We also needed a program called winip broadcast http://winipbroadcast.e-t172.net/. This corrects the behaviour on windows 7 so that broadcasts to 255.255.255.255 go to all interfaces including hamachi. By default windows only broadcasts on the interface with the lowest metric. Without this program we would need to broadcast on 5.255.255.255 (the hamachi broadcast address).
With these fixes the java program worked. And we thought we might be in business.
I asked my friend to make a civ5 server and I opened the server browser in LAN mode and lo-and-behold I could see his server!
...
Alas I could not connect!
(it was stuck at the screen that says roughly "retrieving server information")
We tried the other way around however he could not see my server. We don't know why this is. He should have been using identical network settings to me. Perhaps this indicates that my broadcast packets were getting through but his were not.
We did more and more testing but no luck.
We discovered that we could partly reintroduce the gateway setting in hamachi provided that we change the automatic *gateway* metric setting to 9000 (leaving the interface metric at the default of 9000). The java program would continue to work, however neither of us could see the others civ5 server.
Java code is in the spoiler tag. Run the program without arguments for "listen" mode and with the "bcast" argument for broadcast mode. The file broadcast.zip contains the compiled program as broadcast.jar, which you can run as "java -jar broadcast.jar [bcast]". You must run the listener before the broadcaster for the system to work.
Edit #1: Note about running listener before the broadcaster.
Firstly, these tests were conducted on two relatively recent machines running windows 7 with full copies of civ5.
Upon initial setup of hamachi we established both peers could ping each other. We started civ. Neither of us could discover the other's game.
Netstat output indicated that the game listens on UDP port 62900. Other ports maybe involved but this seems pretty certain. The ports the game uses seems to be totally undocumented (not even a readme!).
It seemed logical to establish that udp broadcast packets were being blocked before drawing any more conculsions. To do this I wrote a humble java program that has two modes. A "broadcast" mode that sends "hello world! i am [hostname]" message in a udp packet to 255.255.255.255 (the general broadcast address) and then awaits a response from a listener on another machine. The second mode is a listener that awaits a message and then sends a response "hello i am [hostname]" to the broadcaster.
The output should look like:
broadcaster:
broadcasting
sending message "Hello world! I am [hostname]"
awaiting message
received message:
"Hello I am [otherhostname]"
sending message ...
[etc]
responder:
listening
awaiting message
received message:
"Hello I am [otherhostname]"
sending message "Hello I am [hostname]"
The point of this is to model at least conceptually clients broadcasting to servers "who is serving civ5?" and then connecting up.
We tried this program. It didnt work until we *completly* removed the gateway entry under the hamachi network adapter settings -> ipv4 -> advanced. I suspect this is because the "gateway" whatever it represents on hamachi was winning out over the broadcast entry in the routing table. For some reason this gateway cannot forward broadcast packets. Note when doing this windows will suddenly decide it cannot recognise the network and will force it into "public" mode, bringing a load of firewall rules into force. For simplicity, we disabled the firewall at this point.
We also needed a program called winip broadcast http://winipbroadcast.e-t172.net/. This corrects the behaviour on windows 7 so that broadcasts to 255.255.255.255 go to all interfaces including hamachi. By default windows only broadcasts on the interface with the lowest metric. Without this program we would need to broadcast on 5.255.255.255 (the hamachi broadcast address).
With these fixes the java program worked. And we thought we might be in business.
I asked my friend to make a civ5 server and I opened the server browser in LAN mode and lo-and-behold I could see his server!
...
Alas I could not connect!

We tried the other way around however he could not see my server. We don't know why this is. He should have been using identical network settings to me. Perhaps this indicates that my broadcast packets were getting through but his were not.
We did more and more testing but no luck.
We discovered that we could partly reintroduce the gateway setting in hamachi provided that we change the automatic *gateway* metric setting to 9000 (leaving the interface metric at the default of 9000). The java program would continue to work, however neither of us could see the others civ5 server.
Java code is in the spoiler tag. Run the program without arguments for "listen" mode and with the "bcast" argument for broadcast mode. The file broadcast.zip contains the compiled program as broadcast.jar, which you can run as "java -jar broadcast.jar [bcast]". You must run the listener before the broadcaster for the system to work.
Edit #1: Note about running listener before the broadcaster.
Spoiler :
Code:
package bcast;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
/**
* UDP Broadcast testing program
*/
public class Broadcast {
/**
* Main - Program entry point, may take one argument
* <ul><li>If given the argument "bcast" will broadcast to peers,</li>
* otherwise will listen and respond to broadcasters.
* <li>Listeners must be started before broadcasters.</li></ul>
* @param args command line args
* @throws IOException on any ioerror
* @throws InterruptedException if sleep is interrupted
*/
public static void main(String[] args) throws IOException, InterruptedException {
DatagramSocket socket;
InetSocketAddress sendAddr;
String message = "Hello ";
String myname = Inet4Address.getLocalHost().getHostName();
boolean bcast = args.length > 0 && args[0] != null && args[0].equals("bcast");
if(bcast) { // broadcast
System.out.println("broadcasting");
sendAddr =
new InetSocketAddress("255.255.255.255", 6666);
socket = new DatagramSocket();
message += "world! ";
} else { // listen
System.out.println("listening");
sendAddr = null;
socket = new DatagramSocket(6666);
}
message += "I am " + myname + "\n";
for (;;) {
if(sendAddr != null) {
Thread.sleep(5000);
System.out.println("sending message \""+message.substring(0, message.length()-1)+"\"");
DatagramPacket sendpacket =
new DatagramPacket(message.getBytes(),message.getBytes().length);
socket.connect(sendAddr);
System.out.println("sending message");
socket.send(sendpacket);
socket.disconnect();
if (!bcast) {
sendAddr = null;
}
}
System.out.println("awaiting message");
byte[] recBuffer = new byte[256];
DatagramPacket recpacket = new DatagramPacket(recBuffer, recBuffer.length);
socket.receive(recpacket);
System.out.println("recieved message:");
if( sendAddr == null) {
sendAddr = new InetSocketAddress(recpacket.getAddress(), recpacket.getPort());
}
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(new ByteArrayInputStream(recBuffer)));
// print response
System.out.println(new String(bufferedReader.readLine()));
}
}
}