Skip to content

Instantly share code, notes, and snippets.

@tuvior
Last active December 27, 2020 18:12
Show Gist options
  • Save tuvior/206f97b12f4573b90583a05a05c9b2f7 to your computer and use it in GitHub Desktop.
Save tuvior/206f97b12f4573b90583a05a05c9b2f7 to your computer and use it in GitHub Desktop.
RotMG Server Ping Checker
import socket
import time
from collections import namedtuple
from itertools import takewhile
from threading import Thread
from timeit import default_timer as timer
from urllib import request
from xml.etree import ElementTree
SERVER_PORT = 2050
SHOW_COORD = False
Server = namedtuple("Server", "name, ping")
def print_separator():
print("-" * (80 if SHOW_COORD else 52))
def get_ping(host, port):
"""Estimate TCP ping with average socket connection time."""
total = 0.0
for _ in range(5):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5)
start = timer()
try:
s.connect((host, port))
s.shutdown(socket.SHUT_RD)
except socket.timeout:
return -1
total += timer() - start
time.sleep(0.5)
return int(total * 200)
def get_ping_fast(host, port):
"""Estimate TCP ping with one connection time."""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
start = timer()
try:
s.connect((host, port))
s.shutdown(socket.SHUT_RD)
except socket.timeout:
return -1
return int((timer() - start) * 1000)
# char/list for random guest account
char_list = request.urlopen(
f"http://realmofthemadgodhrd.appspot.com/char/list?guid={time.time()}"
).read()
char_xml = ElementTree.fromstring(char_list)
# server list
servers = char_xml.find("Servers")
print_separator()
print(f"Checking {len(servers)} Servers:")
print_separator()
pings = [None] * len(servers)
def check_server(i, server):
ip = server.find("DNS").text
ping = get_ping(ip, SERVER_PORT)
pings[i] = (ping, server)
checkers = []
for i, server in enumerate(servers):
checker = Thread(target=check_server, args=[i, server])
checker.start()
checkers.append(checker)
for checker in checkers:
checker.join()
server_list = []
pings.sort(key=lambda s: s[1].find("Name").text)
for (ping, server) in pings:
name = server.find("Name").text
ip = server.find("DNS").text
lat = server.find("Lat").text
lon = server.find("Long").text
if SHOW_COORD:
print(f"{name:15} ip: {ip:15} | ping: {ping:>4} ms")
else:
print(f"{name:15} ip: {ip:15} | ping: {ping:>4} ms")
if ping > -1:
server_list.append(Server(name, ping))
print_separator()
server_list.sort(key=lambda server: server.ping)
min_ping = server_list[0].ping
best_servers = list(takewhile(lambda server: server.ping <= min_ping + 5, server_list))
listed = ", ".join(server.name for server in best_servers)
print(f"Best Servers: {listed}")
us_servers = [server.ping for server in server_list if "US" in server.name]
eu_servers = [server.ping for server in server_list if "EU" in server.name]
asia_servers = [
server.ping
for server in server_list
if "US" not in server.name and "EU" not in server.name
]
avg_us = sum(us_servers) // len(us_servers)
avg_eu = sum(eu_servers) // len(eu_servers)
avg_as = sum(asia_servers) // len(asia_servers)
print(f"Average Europe Ping: {avg_eu} ms")
print(f"Average US Ping: {avg_us} ms")
print(f"Average Asia Ping: {avg_as} ms")
print_separator()
@daniel-zimmer
Copy link

When trying to connect to USSouth I got -1ms as response (probably couldn't connect), so the script thought that USSouth was the best server. The -1 case should be checked and something like [could not connect] should be displayed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment