Last active
December 27, 2020 18:12
-
-
Save tuvior/206f97b12f4573b90583a05a05c9b2f7 to your computer and use it in GitHub Desktop.
RotMG Server Ping Checker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.