mirror of
https://github.com/damp11113/IDRB.git
synced 2025-04-27 22:48:09 +00:00
update 1.6.2
this update is update on server side new Buffer client side fix buffer
This commit is contained in:
parent
d5e6b8e1ea
commit
1e77eae2d8
Binary file not shown.
Binary file not shown.
@ -1,3 +1,20 @@
|
|||||||
|
"""
|
||||||
|
This file is part of IDRB Project.
|
||||||
|
|
||||||
|
IDRB Project is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
IDRB Project is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with IDRB Project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
import dearpygui.dearpygui as dpg
|
import dearpygui.dearpygui as dpg
|
||||||
|
|
||||||
from utils import *
|
from utils import *
|
||||||
@ -60,7 +77,7 @@ def window(self):
|
|||||||
dpg.add_spacer()
|
dpg.add_spacer()
|
||||||
dpg.add_text("IDRB (Internet Digital Radio Broadcasting System) Client")
|
dpg.add_text("IDRB (Internet Digital Radio Broadcasting System) Client")
|
||||||
dpg.add_spacer()
|
dpg.add_spacer()
|
||||||
dpg.add_text(f"IDRB Client v1.6.1 Beta")
|
dpg.add_text(f"IDRB Client v1.6.2 Beta")
|
||||||
dpg.add_spacer()
|
dpg.add_spacer()
|
||||||
|
|
||||||
desc = "IDRB is a novel internet radio broadcasting alternative that uses HLS/DASH/HTTP streams, transferring over TCP/IP. This system supports images and RDS (Dynamic update) capabilities, enabling the transmission of station information. Additionally, it allows for setting station logos and images. IDRB offers multi-broadcasting functionalities and currently supports the Opus codec, with plans to incorporate PCM, MP2/3, AAC/AAC+, and more in the future, ensuring low delay. If you find this project intriguing, you can support it at damp11113.xyz/support."
|
desc = "IDRB is a novel internet radio broadcasting alternative that uses HLS/DASH/HTTP streams, transferring over TCP/IP. This system supports images and RDS (Dynamic update) capabilities, enabling the transmission of station information. Additionally, it allows for setting station logos and images. IDRB offers multi-broadcasting functionalities and currently supports the Opus codec, with plans to incorporate PCM, MP2/3, AAC/AAC+, and more in the future, ensuring low delay. If you find this project intriguing, you can support it at damp11113.xyz/support."
|
||||||
@ -148,8 +165,10 @@ def window(self):
|
|||||||
dpg.add_text("Please restart software when configured")
|
dpg.add_text("Please restart software when configured")
|
||||||
with dpg.tab_bar():
|
with dpg.tab_bar():
|
||||||
with dpg.tab(label="Audio"):
|
with dpg.tab(label="Audio"):
|
||||||
dpg.add_combo([], label="Output Device", tag="selectaudiooutputdevicecombo",
|
dpg.add_combo([], label="Output Device", tag="selectaudiooutputdevicecombo", callback=self.changeaudiodevice)
|
||||||
callback=self.changeaudiodevice)
|
with dpg.tab(label="Network"):
|
||||||
|
dpg.add_input_int(label="Buffer Size", tag="buffersizeintinput", callback=self.changebuffersize)
|
||||||
|
|
||||||
|
|
||||||
def menubar(self):
|
def menubar(self):
|
||||||
with dpg.viewport_menu_bar():
|
with dpg.viewport_menu_bar():
|
||||||
|
@ -40,8 +40,7 @@ class App:
|
|||||||
self.config = configparser.ConfigParser()
|
self.config = configparser.ConfigParser()
|
||||||
self.config.read("config.ini")
|
self.config.read("config.ini")
|
||||||
self.device_name_output = self.config["audio"]["device"]
|
self.device_name_output = self.config["audio"]["device"]
|
||||||
self.buffersize = 64 # can configable
|
self.buffersize = self.config["network"]["buffersize"]
|
||||||
|
|
||||||
|
|
||||||
self.working = False
|
self.working = False
|
||||||
self.readchannel = 1
|
self.readchannel = 1
|
||||||
@ -60,8 +59,6 @@ class App:
|
|||||||
self.lsitem = None
|
self.lsitem = None
|
||||||
self.ccconwithpubselect = False
|
self.ccconwithpubselect = False
|
||||||
self.buffer = queue.Queue(maxsize=self.buffersize)
|
self.buffer = queue.Queue(maxsize=self.buffersize)
|
||||||
self.okbuffer = False
|
|
||||||
self.firstrunbuffer = True
|
|
||||||
|
|
||||||
def connecttoserverwithpubselect(self, sender, data):
|
def connecttoserverwithpubselect(self, sender, data):
|
||||||
self.ccconwithpubselect = True
|
self.ccconwithpubselect = True
|
||||||
@ -125,8 +122,6 @@ class App:
|
|||||||
dpg.configure_item("station_logo_config", show=False)
|
dpg.configure_item("station_logo_config", show=False)
|
||||||
dpg.configure_item("RDSinfo", show=False)
|
dpg.configure_item("RDSinfo", show=False)
|
||||||
dpg.configure_item("disconnectbutton", show=False)
|
dpg.configure_item("disconnectbutton", show=False)
|
||||||
dpg.configure_item("connectservergroup", show=True)
|
|
||||||
dpg.configure_item("serverstatus", default_value='disconnected', color=(255, 0, 0))
|
|
||||||
dpg.configure_item("logostatus", show=False)
|
dpg.configure_item("logostatus", show=False)
|
||||||
self.firstrun = True
|
self.firstrun = True
|
||||||
self.firststart = True
|
self.firststart = True
|
||||||
@ -136,9 +131,7 @@ class App:
|
|||||||
self.ccisdecryptpassword = None
|
self.ccisdecryptpassword = None
|
||||||
self.cciswaitlogoim = True
|
self.cciswaitlogoim = True
|
||||||
self.ccthreadlogorecisworking = False
|
self.ccthreadlogorecisworking = False
|
||||||
self.buffer = queue.Queue(maxsize=self.buffersize)
|
# clear buffer
|
||||||
self.okbuffer = False
|
|
||||||
self.firstrunbuffer = True
|
|
||||||
|
|
||||||
def RDSshow(self):
|
def RDSshow(self):
|
||||||
try:
|
try:
|
||||||
@ -231,6 +224,11 @@ class App:
|
|||||||
self.config["audio"]["device"] = dpg.get_value(sender)
|
self.config["audio"]["device"] = dpg.get_value(sender)
|
||||||
self.config.write(open('config.ini', 'w'))
|
self.config.write(open('config.ini', 'w'))
|
||||||
|
|
||||||
|
def changebuffersize(self, sender, data):
|
||||||
|
self.buffersize = int(dpg.get_value(sender))
|
||||||
|
self.config["network"]["buffersize"] = str(dpg.get_value(sender))
|
||||||
|
self.config.write(open('config.ini', 'w'))
|
||||||
|
|
||||||
def pubserverselectone(self, sender, data):
|
def pubserverselectone(self, sender, data):
|
||||||
if data == False:
|
if data == False:
|
||||||
dpg.configure_item("connectbuttonpubserverselect", show=False)
|
dpg.configure_item("connectbuttonpubserverselect", show=False)
|
||||||
@ -295,25 +293,33 @@ class App:
|
|||||||
self.pubserverselectsearch()
|
self.pubserverselectsearch()
|
||||||
|
|
||||||
def streambuffer(self, socket):
|
def streambuffer(self, socket):
|
||||||
consecutive_above_threshold = 0 # Counter to track consecutive iterations above threshold
|
|
||||||
tolerance_iterations = 5 # Number of consecutive iterations required above threshold
|
|
||||||
while self.working:
|
while self.working:
|
||||||
if self.cprotocol == "TCP":
|
try:
|
||||||
tempdata = b''
|
if self.cprotocol == "TCP":
|
||||||
# data = socket.recv(1580152)
|
tempdata = b''
|
||||||
while True:
|
# data = socket.recv(1580152)
|
||||||
part = socket.recv(1024)
|
while True:
|
||||||
tempdata += part
|
part = socket.recv(1024)
|
||||||
if len(part) < 1024:
|
tempdata += part
|
||||||
# either 0 or end of data
|
if len(part) < 1024:
|
||||||
break
|
# either 0 or end of data
|
||||||
self.buffer.put(tempdata)
|
break
|
||||||
elif self.cprotocol == "ZeroMQ":
|
self.buffer.put(tempdata, timeout=0.1)
|
||||||
self.buffer.put(socket.recv())
|
elif self.cprotocol == "ZeroMQ":
|
||||||
else:
|
self.buffer.put(socket.recv(), timeout=0.1)
|
||||||
self.buffer.put(b"")
|
else:
|
||||||
|
self.buffer.put(b"")
|
||||||
|
|
||||||
dpg.configure_item("bufferstatus", default_value=f'Buffer: {self.buffer.qsize()}/{self.buffersize}')
|
dpg.configure_item("bufferstatus", default_value=f'Buffer: {self.buffer.qsize()}/{self.buffersize}', color=(0, 255, 0))
|
||||||
|
except queue.Full:
|
||||||
|
dpg.configure_item("bufferstatus", default_value=f'Buffer: {self.buffer.qsize()}/{self.buffersize}', color=(255, 0, 0))
|
||||||
|
|
||||||
|
while not self.buffer.empty():
|
||||||
|
self.buffer.get()
|
||||||
|
|
||||||
|
dpg.configure_item("bufferstatus", default_value=f'Buffer: {self.buffer.qsize()}/{self.buffersize}', color=(255, 255, 0))
|
||||||
|
dpg.configure_item("serverstatus", default_value='disconnected', color=(255, 0, 0))
|
||||||
|
dpg.configure_item("connectservergroup", show=True)
|
||||||
|
|
||||||
def stream(self, socket):
|
def stream(self, socket):
|
||||||
opus_decoder = None
|
opus_decoder = None
|
||||||
@ -339,6 +345,7 @@ class App:
|
|||||||
if self.buffer.not_empty:
|
if self.buffer.not_empty:
|
||||||
data = self.buffer.get()
|
data = self.buffer.get()
|
||||||
else:
|
else:
|
||||||
|
dpg.configure_item("serverstatus", default_value='Buffering...', color=(255, 255, 0))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
bytesconunt += len(data)
|
bytesconunt += len(data)
|
||||||
@ -589,7 +596,7 @@ class App:
|
|||||||
ctypes.CDLL("opus.dll")
|
ctypes.CDLL("opus.dll")
|
||||||
|
|
||||||
dpg.create_context()
|
dpg.create_context()
|
||||||
dpg.create_viewport(title=f'IDRB Client v1.6.1 Beta', width=1280, height=720, large_icon="IDRBfavicon.ico", clear_color=(43, 45, 48)) # set viewport window
|
dpg.create_viewport(title=f'IDRB Client v1.6.2 Beta', width=1280, height=720, large_icon="IDRBfavicon.ico", clear_color=(43, 45, 48)) # set viewport window
|
||||||
dpg.setup_dearpygui()
|
dpg.setup_dearpygui()
|
||||||
# -------------- add code here --------------
|
# -------------- add code here --------------
|
||||||
noimage_texture_data = []
|
noimage_texture_data = []
|
||||||
@ -621,6 +628,7 @@ class App:
|
|||||||
output_devices.append(device_info['name'])
|
output_devices.append(device_info['name'])
|
||||||
|
|
||||||
dpg.configure_item("selectaudiooutputdevicecombo", items=output_devices, default_value=self.config["audio"]["device"])
|
dpg.configure_item("selectaudiooutputdevicecombo", items=output_devices, default_value=self.config["audio"]["device"])
|
||||||
|
dpg.configure_item("buffersizeintinput", default_value=int(self.config["network"]["buffersize"]))
|
||||||
|
|
||||||
# -------------------------------------------
|
# -------------------------------------------
|
||||||
dpg.show_viewport()
|
dpg.show_viewport()
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
[audio]
|
[audio]
|
||||||
device = Speakers (2- USB Audio DAC )
|
device = Speakers (2- USB Audio DAC )
|
||||||
|
|
||||||
|
[network]
|
||||||
|
buffersize = 128
|
||||||
|
|
||||||
[debug]
|
[debug]
|
||||||
hideconsole = true
|
hideconsole = true
|
||||||
|
|
||||||
|
@ -1,3 +1,20 @@
|
|||||||
|
"""
|
||||||
|
This file is part of IDRB Project.
|
||||||
|
|
||||||
|
IDRB Project is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
IDRB Project is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with IDRB Project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
from Crypto.Protocol.KDF import scrypt
|
from Crypto.Protocol.KDF import scrypt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
@ -15,10 +15,17 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with IDRB Project. If not, see <https://www.gnu.org/licenses/>.
|
along with IDRB Project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# To config Muxer you need to goto server.py and find "Config Muxer"
|
||||||
|
# To config RDS you need to goto RDS.py
|
||||||
|
# To config Encoder you need to goto Encoder.py
|
||||||
|
# Do not goto ThaiSDRDir.py and utils.py
|
||||||
|
|
||||||
# Server Settings
|
# Server Settings
|
||||||
protocol = "ZMQ_WS" # TCP ZMQ ZMQ_WS
|
protocol = "ZMQ_WS" # TCP ZMQ ZMQ_WS
|
||||||
server_port = ('*', 6980) # if use other protocol ZMQ please use 0.0.0.0
|
server_port = ('*', 6980) # if use other protocol ZMQ please use 0.0.0.0
|
||||||
compression_level = 9 # 0-9
|
compression_level = 9 # 0-9
|
||||||
|
buffersize = 32 # must be int (on working it use buffersize + (buffersize/2) to standby)
|
||||||
|
# low buffersize = low delay
|
||||||
|
|
||||||
# Server Info
|
# Server Info
|
||||||
ServerName = "DPCloudev"
|
ServerName = "DPCloudev"
|
||||||
@ -40,4 +47,4 @@ public = True
|
|||||||
ServerIP = "localhost"
|
ServerIP = "localhost"
|
||||||
#ServerPort = server_port[1]
|
#ServerPort = server_port[1]
|
||||||
ServerPort = 6980
|
ServerPort = 6980
|
||||||
ThaiSDRkey = "1N5LURICLIN1U9QNYZ4MHJ6FNXISFXFELZAX135CFM0HSD17O2.63E60BE9EEA2339C113A15EB"
|
ThaiSDRkey = ""
|
Binary file not shown.
147
Server/server.py
147
Server/server.py
@ -22,6 +22,8 @@ import threading
|
|||||||
import zmq
|
import zmq
|
||||||
import logging
|
import logging
|
||||||
import zlib
|
import zlib
|
||||||
|
import queue
|
||||||
|
import math
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s')
|
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s')
|
||||||
ServerLog = logging.getLogger("IDRBServer")
|
ServerLog = logging.getLogger("IDRBServer")
|
||||||
@ -61,7 +63,6 @@ _RDS.startRDSThread()
|
|||||||
ServerLog.info('starting audio encoding')
|
ServerLog.info('starting audio encoding')
|
||||||
Encoder.StartEncoder()
|
Encoder.StartEncoder()
|
||||||
|
|
||||||
|
|
||||||
if protocol == "TCP":
|
if protocol == "TCP":
|
||||||
connected_users = 0
|
connected_users = 0
|
||||||
elif protocol == "ZMQ":
|
elif protocol == "ZMQ":
|
||||||
@ -74,78 +75,98 @@ timestart = time.time()
|
|||||||
connectionlist = []
|
connectionlist = []
|
||||||
first = True
|
first = True
|
||||||
|
|
||||||
|
Buffer = queue.Queue(maxsize=math.trunc(Settings.buffersize + (Settings.buffersize/2)))
|
||||||
|
|
||||||
|
# ---------------------------------- Config Muxer ---------------------------------------
|
||||||
|
|
||||||
|
def Muxer():
|
||||||
|
while True:
|
||||||
|
# Get the encoded audio from the buffer
|
||||||
|
ENchannel1 = Encoder.channel1.get()
|
||||||
|
|
||||||
|
# encrypt data
|
||||||
|
# ENC1encrypted, ENC1salt, ENC1iv = utils.encrypt_data(ENchannel1, "password")
|
||||||
|
|
||||||
|
# ENchannel1 = ENC1encrypted + b'|||||' + ENC1salt + b'|||||' + ENC1iv
|
||||||
|
|
||||||
|
ENchannel2 = Encoder.channel2.get()
|
||||||
|
content = {
|
||||||
|
"first": False,
|
||||||
|
"mainchannel": 1,
|
||||||
|
"channel": {
|
||||||
|
1: {
|
||||||
|
"Station": "DPRadio+",
|
||||||
|
"StationDesc": "The best station in the world!",
|
||||||
|
"Encrypt": b'|||||' in ENchannel1, # check if encrypt
|
||||||
|
"ContentSize": len(ENchannel1),
|
||||||
|
"Content": ENchannel1,
|
||||||
|
"RDS": _RDS.RDS
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
"Station": "DPTest",
|
||||||
|
"StationDesc": "",
|
||||||
|
"Encrypt": b'|||||' in ENchannel2,
|
||||||
|
"ContentSize": len(ENchannel2),
|
||||||
|
"Content": ENchannel2,
|
||||||
|
"RDS": _RDS.RDS2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"serverinfo": {
|
||||||
|
"Listener": connected_users,
|
||||||
|
"Startat": timestart,
|
||||||
|
"RDS": _RDS.ServerRDS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ThaiSDRDir.content = content
|
||||||
|
|
||||||
|
compressedcontent = zlib.compress(pickle.dumps(content), level=Settings.compression_level)
|
||||||
|
|
||||||
|
Buffer.put(compressedcontent)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
def handle_client():
|
def handle_client():
|
||||||
global connected_users, first
|
global connected_users, first
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
# Get the encoded audio from the buffer
|
# Check if the buffer queue has enough data to send
|
||||||
ENchannel1 = Encoder.channel1.get()
|
if Buffer.qsize() >= Settings.buffersize: # Adjust the threshold as needed
|
||||||
|
if protocol == "TCP":
|
||||||
# encrypt data
|
for i in connectionlist:
|
||||||
#ENC1encrypted, ENC1salt, ENC1iv = utils.encrypt_data(ENchannel1, "password")
|
try:
|
||||||
|
# Send data from the buffer queue to connected clients
|
||||||
#ENchannel1 = ENC1encrypted + b'|||||' + ENC1salt + b'|||||' + ENC1iv
|
for _ in range(Settings.buffersize):
|
||||||
|
i.sendall(Buffer.get())
|
||||||
ENchannel2 = Encoder.channel2.get()
|
except Exception as e:
|
||||||
content = {
|
if i in connectionlist:
|
||||||
"first": False,
|
i.close()
|
||||||
"mainchannel": 1,
|
connectionlist.remove(i)
|
||||||
"channel": {
|
connected_users -= 1
|
||||||
1: {
|
if not connectionlist:
|
||||||
"Station": "DPRadio+",
|
first = True
|
||||||
"StationDesc": "The best station in the world!",
|
ServerLog.info('server is standby now')
|
||||||
"Encrypt": b'|||||' in ENchannel1, # check if encrypt
|
break
|
||||||
"ContentSize": len(ENchannel1),
|
elif protocol == "ZMQ":
|
||||||
"Content": ENchannel1,
|
# Send data from the buffer queue to ZMQ socket
|
||||||
"RDS": _RDS.RDS
|
for _ in range(Settings.buffersize):
|
||||||
},
|
s.send(Buffer.get())
|
||||||
2: {
|
|
||||||
"Station": "DPTest",
|
|
||||||
"StationDesc": "",
|
|
||||||
"Encrypt": b'|||||' in ENchannel2,
|
|
||||||
"ContentSize": len(ENchannel2),
|
|
||||||
"Content": ENchannel2,
|
|
||||||
"RDS": _RDS.RDS2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"serverinfo": {
|
|
||||||
"Listener": connected_users,
|
|
||||||
"Startat": timestart,
|
|
||||||
"RDS": _RDS.ServerRDS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ThaiSDRDir.content = content
|
|
||||||
|
|
||||||
compressedcontent = zlib.compress(pickle.dumps(content), level=Settings.compression_level)
|
|
||||||
|
|
||||||
#connection.sendall(pickle.dumps(content))
|
|
||||||
if protocol == "TCP":
|
|
||||||
for i in connectionlist:
|
|
||||||
try:
|
|
||||||
i.sendall(compressedcontent)
|
|
||||||
except Exception as e:
|
|
||||||
#print(f'Error sending data to {i.getpeername()}: {e}')
|
|
||||||
# Remove disconnected client from the list
|
|
||||||
if i in connectionlist:
|
|
||||||
i.close()
|
|
||||||
connectionlist.remove(i)
|
|
||||||
connected_users -= 1
|
|
||||||
# check if no user
|
|
||||||
if not connectionlist:
|
|
||||||
first = True
|
|
||||||
ServerLog.info('server is standby now')
|
|
||||||
break
|
|
||||||
elif protocol == "ZMQ":
|
|
||||||
s.send(compressedcontent)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'Error: {e}')
|
print(f'Error: {e}')
|
||||||
|
|
||||||
|
|
||||||
# Your main server logic using threading for handling connections
|
# Your main server logic using threading for handling connections
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if public:
|
if public:
|
||||||
ServerLog.info('starting ThaiSDR Directory')
|
ServerLog.info('starting ThaiSDR Directory')
|
||||||
ThaiSDRDir.run()
|
ThaiSDRDir.run()
|
||||||
ServerLog.info('server is running')
|
|
||||||
|
ServerLog.info('starting Muxer')
|
||||||
|
|
||||||
|
muxerthread = threading.Thread(target=Muxer)
|
||||||
|
muxerthread.start()
|
||||||
|
|
||||||
|
ServerLog.info('starting server')
|
||||||
|
|
||||||
if protocol == "TCP":
|
if protocol == "TCP":
|
||||||
while True:
|
while True:
|
||||||
connection, client_address = s.accept()
|
connection, client_address = s.accept()
|
||||||
@ -162,4 +183,6 @@ if __name__ == "__main__":
|
|||||||
elif protocol == "ZMQ":
|
elif protocol == "ZMQ":
|
||||||
client_thread = threading.Thread(target=handle_client)
|
client_thread = threading.Thread(target=handle_client)
|
||||||
# client_thread.daemon = True # Set the thread as a daemon so it exits when the main thread exits
|
# client_thread.daemon = True # Set the thread as a daemon so it exits when the main thread exits
|
||||||
client_thread.start()
|
client_thread.start()
|
||||||
|
|
||||||
|
ServerLog.info('server is running')
|
Loading…
x
Reference in New Issue
Block a user