Skip to content

Make RPC port assignment more robust #797

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions pyaedt/common_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import rpyc
from rpyc.utils.server import ThreadedServer
from pyaedt.rpc.rpyc_services import GlobalService
from pyaedt.rpc.rpyc_services import GlobalService, check_port
import rpyc.core.consts

# Maximum Stream message size. Set to 256MB
Expand All @@ -24,7 +24,6 @@
import subprocessdotnet as subprocess
else:
import subprocess
import socket


def launch_server(port=18000, ansysem_path=None, non_graphical=False):
Expand All @@ -46,6 +45,12 @@ def launch_server(port=18000, ansysem_path=None, non_graphical=False):
>>> launch_server( port=18000)

"""
port1 = check_port(port)
if port == 0:
print("Error. No Available ports.")
return False
if port1 != port:
print("Port {} already in use. Starting Service on {}.".format(port, port1))
if os.name == "posix":
os.environ["PYAEDT_SERVER_AEDT_PATH"] = ansysem_path
os.environ["PYAEDT_SERVER_AEDT_NG"] = str(non_graphical)
Expand Down Expand Up @@ -145,7 +150,7 @@ def launch_server(port=18000, ansysem_path=None, non_graphical=False):
t = ThreadedServer(
GlobalService,
hostname=hostname,
port=port,
port=port1,
protocol_config={
"sync_request_timeout": None,
"allow_public_attrs": True,
Expand Down Expand Up @@ -221,7 +226,7 @@ def client(server_name, server_port=18000, beta_options=None):
>>> cl2.root.run_script(script_to_run, ansysem_path = "/path/to/AnsysEMxxx/Linux64")

"""
t = 20
t = 60
while t > 0:
try:
c = rpyc.connect(server_name, server_port, config={"sync_request_timeout": None})
Expand All @@ -236,7 +241,7 @@ def client(server_name, server_port=18000, beta_options=None):
print("Connecting to new session of Electronics Desktop on port {}. Please Wait.".format(port))
if port:
time.sleep(20)
timeout = 60
timeout = 80
while timeout > 0:
try:
c1 = rpyc.connect(server_name, port, config={"sync_request_timeout": None})
Expand Down Expand Up @@ -368,6 +373,10 @@ def launch_ironpython_server(aedt_path, non_graphical=False, port=18000, launch_
>>> my_face_list = client.convert_remote_object(box.faces)

"""
port1 = check_port(port)
if port1 == 0:
print("Error. No Available ports.")
return False
if non_graphical:
val = 1
else:
Expand All @@ -378,13 +387,14 @@ def launch_ironpython_server(aedt_path, non_graphical=False, port=18000, launch_
os.path.join(os.path.dirname(__file__), "rpc", "local_server.py"),
aedt_path,
str(val),
str(port),
str(port1),
]
proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=non_graphical)
print("Process {} started on {}".format(proc.pid, socket.getfqdn()))
print("Using Port {}".format(port1))
print("Warning: Remote CPython to Ironpython may have some limitations.")
print("Known Issues are on returned list and dict. ")
print("For those it is recommended to use client.convert_remote_object method.")
if proc and launch_client:
return client(server_name=socket.getfqdn(), server_port=port)
return client(server_name=socket.getfqdn(), server_port=port1)
return False
37 changes: 35 additions & 2 deletions pyaedt/rpc/rpyc_services.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import socket
import os
import random
import tempfile
Expand Down Expand Up @@ -30,6 +31,34 @@
from pyaedt import Mechanical


def check_port(port):
"""Check for an available port on the machine starting from input port.

Parameters
----------
port : int
Ports to search.

Returns
-------
int
Next Port available.
"""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
check = False
while not check:
try:
s.bind((socket.getfqdn(), port))
check = True
except socket.error as e:
port += 1
# stop search at port 30000 (range search 18000 30000 is more then enough for rpc)
if port > 29999:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maxcapodi78 Please add a small comment to explain why this limit "29999". I might be missing something obvious.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

return 0
s.close()
return port


class PyaedtServiceWindows(rpyc.Service):
"""Server Pyaedt rpyc Service."""

Expand Down Expand Up @@ -742,7 +771,11 @@ def exposed_start_service(self, hostname, beta_options=None):
hostname : str
Hostname.
"""
port = random.randint(18001, 20000)

port = check_port(random.randint(18500, 20000))
if port == 0:
print("Error. No Available ports.")
return False
ansysem_path = ""
non_graphical = True
if os.name == "posix":
Expand All @@ -755,7 +788,7 @@ def exposed_start_service(self, hostname, beta_options=None):
script_file = os.path.normpath(
os.path.join(os.path.abspath(os.path.dirname(__file__)), "pyaedt_client_linux.py")
)
dest_file = os.path.join(tempfile.gettempdir(), "pyaedt_client_linux.py")
dest_file = os.path.join(tempfile.gettempdir(), "pyaedt_client_linux_{}.py".format(port))
print(dest_file)
with open(dest_file, "w") as f:
f.write("port={}\n".format(port))
Expand Down