Добавил:
unit_man
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Курсовая / client
.pyimport sys, socket, time, threading
from PyQt5 import QtWidgets
from GUI.client_gui import Ui_MainWindow # импорт сгенерированного файла
HOST = "127.0.0.1"
PORT = [5400, 9999]
BUF_SIZE = 256 # Размер буфера для получения сообшения
clientSocket = [None, None]# Сокеты
sockStatus = [0, 0]# Статусы подключения к серверам
reconnect = False# Флаг для переподключения при падении клиента
# Этот класс представляет главное окно приложения.
class mywindow(QtWidgets.QMainWindow):
def __init__(self):
super(mywindow, self).__init__() #Вызов конструктора класса-родителя, QtWidgets.QMainWindow, для инициализации окна приложения.
self.ui = Ui_MainWindow()
self.ui.setupUi(self)# настраивает пользовательский интерфейс, определенный в классе Ui_MainWindow, и связывает его с текущим экземпляром главного окна.
# Обработка нажатий кнопок
self.ui.sendToServer_1.clicked.connect(self.send_coords_Button)
self.ui.sendToServer_3.clicked.connect(self.send_names_Button)
self.ui.sendToServer_4.clicked.connect(self.get_priority_Button)
self.ui.sendToServer_2.clicked.connect(self.get_thread_id_Button)
# Вспомогательная функция для проверки подключения перед отправкой
def sendToServer(self, data, serverType):
global clientSocket, sockStatus
print(data)
# Проверка типа сервера. Если тип равен 0, то следующий к первому серверу, в противном случае - ко второму серверу
if(serverType == 0):
self.ui.listWidget.addItem('Клиент: ' + data)
else:
self.ui.listWidget_2.addItem('Клиент: ' + data)
# Если сервер уже подключен
if(sockStatus[serverType] != 0):
try:
# Отправка данных на сервер с использованием соответствующего сокета
clientSocket[serverType].sendall(data.encode())
except OSError:
data = 'Ошибка! Сервер не подключен!'
print(data)
sockStatus[serverType] = 0
self.ui.listWidget.addItem('Клиент: ' + data)
# Если сервер еще не подключен
else:
# Пробуем подключиться
if(check_server(HOST, PORT[serverType]) == True):
threading.Thread(None, runClient, args= [serverType]).start()
time.sleep(0.5)
self.send_coords_Button()
# Если не удалось подключиться
else:
data = 'Ошибка! Сервер не подключен!'
print(data)
# Вывод в графический интерфейс
self.ui.listWidget.addItem('Клиент: ' + data)
# Отправка координат окна
def send_coords_Button(self):
if(len(self.ui.lineEdit.text()) > 0 and len(self.ui.lineEdit_2.text()) > 0):
data = self.ui.lineEdit_2.text() + ' x ' + self.ui.lineEdit.text()
self.ui.lineEdit.clear()
self.ui.lineEdit_2.clear()
self.sendToServer(data, 0)
# Отправка имен компьютера и пользователя
def send_names_Button(self):
data = 'send names'
self.sendToServer(data, 0)
# Отправка запроса на получение приоритета процесса сервера
def get_priority_Button(self):
data = 'get process id'
self.sendToServer(data, 1)
# Отправка запроса на получение id потоков
def get_thread_id_Button(self):
data = 'get thread ids'
self.sendToServer(data, 1)
# Вывод текста в графический интерфейс
def addItem(self, serverType, data):
if(serverType == 0):
self.ui.listWidget.addItem('Сервер: ' + data)
else:
self.ui.listWidget_2.addItem('Сервер: ' + data)
print(data)
# Запуск клиента
def runClient(serverType):
global HOST, PORT, clientSocket, sockStatus
is_started = False
'''socket.AF_INET - это константа, которая указывает на использование сокета семейства IPv4.
socket.SOCK_STREAM - это константа, которая указывает на использование потокового (TCP) сокета.
socket.SOL_SOCKET - это уровень сокета, который указывает, что опция применяется к сокету в целом.
socket.SO_REUSEADDR - это опция сокета, которая позволяет повторно использовать локальный адрес для привязки на серверной стороне,
даже если он все еще находится в состоянии TIME_WAIT после закрытия предыдущего соединения.
'''
# Проверка возможности повторного подключения или на то, что клиент еще не запущен.
while reconnect or not is_started:
is_started = True
print("\nКлиент создан")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as clientSocket[serverType]:
# устанавливает соединение с сервером
clientSocket[serverType].connect((HOST, PORT[serverType]))
sockStatus[serverType] = 1
print(f"Сервер {serverType + 1} подключен")
try:
receiveFunc(serverType)
except KeyboardInterrupt:
print(f"Сервер {serverType + 1} отключен")
finally:
clientSocket[serverType].close()
# Получение сообщения
def receiveFunc(serverType):
global clientSocket
while True:
# Получение ответа от сервера
data_bytes = clientSocket[serverType].recv(BUF_SIZE)
data = data_bytes.decode()
# Если данные пусты
if not data:
print("Сервер закрыл соединение")
break
if(data.find(" x ") != -1):
data = data.split(" x ")
window.addItem(serverType, data[0])
window.addItem(serverType, data[1])
else:
window.addItem(serverType, data)
# Проверка доступности сервера
def check_server(ip, port):
'''socket.AF_INET - это константа, которая указывает на использование сокета семейства IPv4.
socket.SOCK_STREAM - это константа, которая указывает на использование потокового (TCP) сокета.
socket.SHUT_RDWR - это константа, которая указывает на полное закрытие (чтение и запись) соединения в сокете'''
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Создание сокета
try:
s.connect((ip, port)) # Подключение к серверу
s.shutdown(socket.SHUT_RDWR) # Закрытие соединения
return True
except:
return False
finally:
s.close()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = mywindow() # Создание экземпляра класса mywindow
# Подключение к серверу 1
# Проверка доступности сервера 1
if(check_server(HOST, PORT[0]) == True):
# Запуск клиента в отдельном потоке для сервера 1
threading.Thread(None, runClient, args= [0]).start()
# Подключение к серверу 2
# Проверка доступности сервера 2
if(check_server(HOST, PORT[1]) == True):
# Запуск клиента в отдельном потоке для сервера 2
threading.Thread(None, runClient, args= [1]).start()
window.show()
# Запуск основного цикла приложения
sys.exit(app.exec_())