import
http.server
import
socketserver
import
socket
import
os
import
threading
import
qrcode
import
clipboard
import
psutil
import
ipaddress
import
threading
import
json,requests,time
class
Server(
object
):
def
__init__(
self
):
self
.ipv4_list
=
[]
self
.ipv6_list
=
[]
self
.ipv4_server_thread
=
None
self
.ipv6_server_thread
=
None
self
.port
=
80
self
.server_way
=
""
self
.all_ip
=
[]
self
.all_ip_dict
=
{}
self
.stop_event
=
threading.Event()
self
.load_config()
self
.get_non_loopback_ip()
self
.run_http_server()
num
=
-
1
for
name,ip
in
self
.ipv4_list:
num
=
num
+
1
self
.all_ip.append(f
"{name}-{ip}"
)
self
.all_ip_dict[num]
=
{
"name"
:name,
"ip"
:ip,
"ipv4"
:
True
}
for
name,ip
in
self
.ipv6_list:
num
=
num
+
1
self
.all_ip.append(f
"{name}-{ip}"
)
self
.all_ip_dict[num]
=
{
"name"
:name,
"ip"
:ip,
"ipv4"
:
False
}
def
get_non_loopback_ip(
self
,):
network
=
ipaddress.IPv4Network(
'169.254.0.0/16'
)
interfaces
=
psutil.net_if_addrs()
for
name, info
in
interfaces.items():
for
addr
in
info:
if
addr.family
=
=
socket.AF_INET:
ip
=
ipaddress.ip_address(addr.address)
if
not
ip.is_loopback
and
not
ip.is_multicast:
if
ip
not
in
network:
self
.ipv4_list.append([name,addr.address])
elif
addr.family
=
=
socket.AF_INET6:
ip
=
ipaddress.ip_address(addr.address)
if
not
ip.is_loopback
and
not
ip.is_multicast:
if
ip
not
in
network:
self
.ipv6_list.append([name,addr.address])
def
start_http_server_v6(
self
, ip
=
'::'
, port
=
80
):
if
port !
=
self
.port:
self
.port
=
port
os.chdir(
self
.server_way)
handler
=
http.server.SimpleHTTPRequestHandler
class
DualStackTCPServer(socketserver.TCPServer):
allow_reuse_address
=
True
def
__init__(
self
, server_address, RequestHandlerClass):
self
.address_family
=
socket.AF_INET6
super
().__init__(server_address, RequestHandlerClass)
with DualStackTCPServer((ip, port), handler) as httpd:
print
(f
"HTTP服务已经运行,地址为:http://[{ip}]:{port}/"
)
while
not
self
.stop_event.is_set():
httpd.handle_request()
def
start_http_server_v4(
self
, ip
=
"0.0.0.0"
, port
=
80
):
if
port !
=
self
.port:
self
.port
=
port
os.chdir(
self
.server_way)
handler
=
http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer((ip, port), handler) as httpd:
print
(f
"HTTP服务已经运行,地址为:http://{ip}:{port}/"
)
while
not
self
.stop_event.is_set():
httpd.handle_request()
def
run_http_server(
self
, ipv4
=
"0.0.0.0"
, ipv6
=
"::"
, port
=
80
):
if
port !
=
self
.port:
self
.port
=
port
self
.ipv4_server_thread
=
threading.Thread(target
=
self
.start_http_server_v4, args
=
(ipv4, port))
self
.ipv6_server_thread
=
threading.Thread(target
=
self
.start_http_server_v6, args
=
(ipv6, port))
self
.ipv4_server_thread.start()
self
.ipv6_server_thread.start()
def
generate_qr_and_copy(
self
,url):
qr
=
qrcode.QRCode(
version
=
1
,
error_correction
=
qrcode.constants.ERROR_CORRECT_L,
box_size
=
1
,
border
=
1
,
)
qr.add_data(url)
qr.make(fit
=
True
)
qr_ascii
=
qr.print_ascii(invert
=
True
, tty
=
True
)
print
(qr_ascii)
clipboard.copy(url)
print
(f
"服务地址: {url} 已经复制到您的剪切板中。"
)
def
get_desktop(
self
):
self
.server_way
=
os.path.join(os.path.expanduser(
"~"
),
"Desktop"
)
def
load_config(
self
):
config_file
=
"config.ini"
self
.get_desktop()
if
not
os.path.exists(config_file):
config
=
{
"server_dir"
:
self
.server_way}
with
open
(config_file,
"w"
,encoding
=
"utf-8"
) as f:
json.dump(config, f, indent
=
4
)
else
:
with
open
(config_file,
"r"
,encoding
=
"utf-8"
) as f:
config
=
json.load(f)
self
.server_way
=
config.get(
"server_dir"
)
def
get_url(
self
,ip_addr,ipv4
=
True
):
if
ipv4:
return
f
"http://{ip_addr.strip()}:{self.port}"
else
:
return
f
"http://[{ip_addr.strip()}]:{self.port}"
def
close_th(
self
):
self
.stop_event.
set
()
time.sleep(
0.3
)
try
:
requests.get(f
"http://[::1]:{self.port}"
,timeout
=
1
)
except
Exception as err:
pass
try
:
requests.get(f
"http://127.0.0.1:{self.port}"
,timeout
=
1
)
except
Exception as err:
pass
self
.ipv4_server_thread.join()
self
.ipv6_server_thread.join()