TCP聊天服务器套接字v1.5
所有版本记录:
v1.0
: TCP聊天服务器套接字|PyQt5+socket(TCP端口映射+端口放行)+logging+Thread(含日志,html)+anaconda打包32位exe(3.4万字)|python高阶
v1.1
: python TCP套接字服务器v1.1-新增服务端命令功能及修改bug(socket+PyQt5)
v1.2
: python TCP服务器v1.2 - 服务端新增用户登录注册(json, md5加密)
v1.3
: python TCP服务器v1.3 - 服务器抗压测试及关闭套接字处理
v1.4
: python TCP服务器v1.4 - 客户端连接服务器异常(异常情况分类)处理
文章目录
| ip格式
dicts = {f"103.46.128.21:51203 (公网)" : "103.46.128.21:51203",
f"{get_host_ip()}:429 (私网)" : f"{get_host_ip()}:429",
"EXAM-41:429 (微机室)" : "EXAM-41:429"}
def address_split(address):
def func(ip="",port=0) -> (str, int):
return ip,int(port)
ip, port = func(*address.strip().split(':')[:2])
return {"ip":ip,
"port":port}
| 客户端连接界面增加自定义参数(设置超时, 连接地址可选(editable))
(1). 可编辑下拉框comboBox
(2).连接界面
python代码(pyuic5)
class Ui_Dialog(object):
def __init__(self):
Dialog = QtWidgets.QDialog()
self.Dialog = Dialog
Dialog.setObjectName("Dialog")
Dialog.resize(532, 239)
font = QtGui.QFont()
font.setFamily("Consolas")
Dialog.setFont(font)
Dialog.setAutoFillBackground(True)
Dialog.setStyleSheet("")
self.gridLayout_3 = QtWidgets.QGridLayout(Dialog)
self.gridLayout_3.setObjectName("gridLayout_3")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_3 = QtWidgets.QLabel(Dialog)
self.label_3.setText("")
self.label_3.setPixmap(QtGui.QPixmap("link.png"))
self.label_3.setObjectName("label_3")
self.horizontalLayout.addWidget(self.label_3)
self.label_4 = QtWidgets.QLabel(Dialog)
self.label_4.setObjectName("label_4")
self.horizontalLayout.addWidget(self.label_4)
self.gridLayout_3.addLayout(self.horizontalLayout, 0, 0, 1, 1)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_3.addItem(spacerItem, 0, 1, 1, 1)
self.progressBar = QtWidgets.QProgressBar(Dialog)
self.progressBar.setMaximum(3)
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
self.gridLayout_3.addWidget(self.progressBar, 2, 0, 1, 1)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_3.addItem(spacerItem1, 2, 1, 1, 1)
self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setObjectName("pushButton")
self.gridLayout_3.addWidget(self.pushButton, 2, 2, 1, 1)
self.groupBox = QtWidgets.QGroupBox(Dialog)
self.groupBox.setObjectName("groupBox")
self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox)
self.gridLayout_2.setObjectName("gridLayout_2")
self.label_2 = QtWidgets.QLabel(self.groupBox)
font = QtGui.QFont()
font.setFamily("Consolas")
self.label_2.setFont(font)
self.label_2.setTextFormat(QtCore.Qt.AutoText)
self.label_2.setObjectName("label_2")
self.gridLayout_2.addWidget(self.label_2, 2, 0, 1, 1)
self.horizontalSlider = QtWidgets.QSlider(self.groupBox)
self.horizontalSlider.setAutoFillBackground(False)
self.horizontalSlider.setMinimum(1)
self.horizontalSlider.setMaximum(10)
self.horizontalSlider.setProperty("value", 3)
self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
self.horizontalSlider.setInvertedAppearance(False)
self.horizontalSlider.setInvertedControls(False)
self.horizontalSlider.setTickPosition(QtWidgets.QSlider.TicksBelow)
self.horizontalSlider.setObjectName("horizontalSlider")
self.gridLayout_2.addWidget(self.horizontalSlider, 4, 2, 1, 1)
self.label = QtWidgets.QLabel(self.groupBox)
font = QtGui.QFont()
font.setFamily("Consolas")
self.label.setFont(font)
self.label.setObjectName("label")
self.gridLayout_2.addWidget(self.label, 3, 0, 1, 1)
self.comboBox = QtWidgets.QComboBox(self.groupBox)
self.comboBox.setEditable(True)
self.comboBox.setObjectName("comboBox")
self.gridLayout_2.addWidget(self.comboBox, 3, 1, 1, 3)
self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox)
font = QtGui.QFont()
font.setFamily("Consolas")
self.lineEdit_2.setFont(font)
self.lineEdit_2.setAccessibleDescription("")
self.lineEdit_2.setInputMask("")
self.lineEdit_2.setObjectName("lineEdit_2")
self.gridLayout_2.addWidget(self.lineEdit_2, 2, 1, 1, 3)
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.label_5 = QtWidgets.QLabel(self.groupBox)
self.label_5.setObjectName("label_5")
self.gridLayout.addWidget(self.label_5, 0, 0, 1, 1)
self.lcdNumber = QtWidgets.QLCDNumber(self.groupBox)
self.lcdNumber.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(0, 255, 223, 255), stop:0.631841 rgba(255, 255, 255, 255));\n"
"")
self.lcdNumber.setFrameShadow(QtWidgets.QFrame.Raised)
self.lcdNumber.setLineWidth(1)
self.lcdNumber.setMidLineWidth(0)
self.lcdNumber.setSegmentStyle(QtWidgets.QLCDNumber.Filled)
self.lcdNumber.setProperty("intValue", 3)
self.lcdNumber.setObjectName("lcdNumber")
self.gridLayout.addWidget(self.lcdNumber, 0, 1, 1, 1)
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem2, 0, 2, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 4, 0, 1, 1)
self.label_6 = QtWidgets.QLabel(self.groupBox)
self.label_6.setStyleSheet("color:rgb(154, 154, 154);\n"
"font-size:13px")
self.label_6.setObjectName("label_6")
self.gridLayout_2.addWidget(self.label_6, 0, 0, 1, 1)
self.gridLayout_3.addWidget(self.groupBox, 1, 0, 1, 3)
self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setReadOnly(True)
self.lineEdit.setObjectName("lineEdit")
self.gridLayout_3.addWidget(self.lineEdit, 3, 0, 1, 3)
self.pushButton.setEnabled(False)
self.retranslateUi(Dialog)
self.pushButton.clicked.connect(self._connect)
self.horizontalSlider.valueChanged['int'].connect(self.lcdNumber.display)
self.horizontalSlider.valueChanged['int'].connect(self.set_timeout)
QtCore.QMetaObject.connectSlotsByName(Dialog)
self.lineEdit_2.textChanged.connect(lambda t: self.pushButton.setEnabled(bool(t.strip())))
self.running = False
self.timer = threading(True, target=self.add_bar)
def add_bar(self):
while True:
if self.running and self.progressBar.value() < TIMEOUT:
self.progressBar.setValue(self.progressBar.value() + 1)
time.sleep(1)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowIcon(QtGui.QIcon('login.ico'))
Dialog.setWindowTitle(_translate("Dialog", "connect"))
self.label_4.setText(_translate("Dialog", f"{socket.gethostname()}"))
self.progressBar.setFormat(_translate("Dialog", "%v / %m s"))
self.pushButton.setText(_translate("Dialog", "Connecting"))
self.groupBox.setTitle(_translate("Dialog", "Parameter Setup"))
self.label_2.setText(_translate("Dialog", "用户名:"))
self.horizontalSlider.setWhatsThis(_translate("Dialog", "set time out"))
self.label.setText(_translate("Dialog", "Select Socket Connect Address:"))
self.comboBox.addItems(dicts.keys())
self.lineEdit_2.setPlaceholderText(_translate("Dialog", "≤8个字符,多余自动删去"))
self.label_5.setText(_translate("Dialog", "最大超时秒数:"))
self.label_6.setText(_translate("Dialog", "[i] 未注册的用户将自动注册"))
self.lineEdit.setText(_translate("Dialog", "No return value."))
Dialog.show()
def set_timeout(self,t):
global TIMEOUT
TIMEOUT = int(t)
self.progressBar.setMaximum(TIMEOUT)
def set_text(self, m):
self.lineEdit.setText(QtCore.QCoreApplication.translate("Dialog", str(m)))
self.lineEdit.update()
@to_logging
def _connect(self, i):
texts = self.comboBox.currentText()
addr = address_split(dicts.get(texts, texts))
global TIMEOUT
TIMEOUT = self.horizontalSlider.value()
global Username
Username = self.lineEdit_2.text().strip()
self.groupBox.setEnabled(False)
self.progressBar.setValue(0)
self.running = True
self.set_text("[{}]: 尝试连接服务器[{}],最大超时报错 {}s".format(datetime.now().strftime('%Y %m %d %H:%M:%S'),addr["ip"],TIMEOUT))
if s.connect(**addr, show=self.set_text):
global main
main = Ui_MainWindow()
main.show()
def close(widget):
sleep(1)
widget.close()
threading(False, target=close, args=(self.Dialog, ))
self.groupBox.setEnabled(True)
self.running = False
.ui(xml)
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>532</width>
<height>239</height>
</rect>
</property>
<property name="font">
<font>
<family>Consolas</family>
</font>
</property>
<property name="windowTitle">
<string>connect</string>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap>link.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>绑定主机{socket.gethostname()}</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QProgressBar" name="progressBar">
<property name="maximum">
<number>3</number>
</property>
<property name="value">
<number>0</number>
</property>
<property name="format">
<string>%p / %m s</string>
</property>
</widget>
</item>
<item row="2" column="1">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Connecting</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Parameter Setup</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<family>Consolas</family>
</font>
</property>
<property name="text">
<string>用户名:</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QSlider" name="horizontalSlider">
<property name="whatsThis">
<string>set time out</string>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>10</number>
</property>
<property name="value">
<number>3</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
<property name="invertedControls">
<bool>false</bool>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="font">
<font>
<family>Consolas</family>
</font>
</property>
<property name="text">
<string>Select Socket Connect Address:</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="3">
<widget class="QComboBox" name="comboBox">
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>192.168.1.10</string>
</property>
</item>
<item>
<property name="text">
<string>localhost</string>
</property>
</item>
</widget>
</item>
<item row="2" column="1" colspan="3">
<widget class="QLineEdit" name="lineEdit_2">
<property name="font">
<font>
<family>Consolas</family>
</font>
</property>
<property name="accessibleDescription">
<string/>
</property>
<property name="inputMask">
<string/>
</property>
<property name="placeholderText">
<string>≤8个字符,多余自动删去</string>
</property>
</widget>
</item>
<item row="4" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>最大超时秒数:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLCDNumber" name="lcdNumber">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(0, 255, 223, 255), stop:0.631841 rgba(255, 255, 255, 255));
</string>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<property name="segmentStyle">
<enum>QLCDNumber::Filled</enum>
</property>
<property name="intValue" stdset="0">
<number>3</number>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="styleSheet">
<string notr="true">color:rgb(154, 154, 154);
font-size:13px</string>
</property>
<property name="text">
<string>[i] 未注册的用户将自动注册</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QLineEdit" name="lineEdit">
<property name="text">
<string>No return value.</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>pushButton</sender>
<signal>clicked()</signal>
<receiver>lineEdit</receiver>
<slot>selectAll()</slot>
<hints>
<hint type="sourcelabel">
<x>437</x>
<y>24</y>
</hint>
<hint type="destinationlabel">
<x>247</x>
<y>57</y>
</hint>
</hints>
</connection>
<connection>
<sender>pushButton</sender>
<signal>clicked()</signal>
<receiver>groupBox</receiver>
<slot>hide()</slot>
<hints>
<hint type="sourcelabel">
<x>380</x>
<y>139</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>81</y>
</hint>
</hints>
</connection>
<connection>
<sender>horizontalSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>lcdNumber</receiver>
<slot>display(int)</slot>
<hints>
<hint type="sourcelabel">
<x>319</x>
<y>123</y>
</hint>
<hint type="destinationlabel">
<x>378</x>
<y>131</y>
</hint>
</hints>
</connection>
</connections>
</ui>
| 全部代码
user.pyw
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui files 'USER.ui', 'Connect.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
import time
from PyQt5 import QtCore, QtGui, QtWidgets
import socket, sys, logging
from traceback import format_exc
from datetime import datetime
from time import sleep
from threading import Thread
from random import randint as rand
import logging # 引入logging模块
logging.basicConfig(level=logging.DEBUG,format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
TIMEOUT = 3
def get_host_ip() -> str:
"""get current IP address"""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 80))
ip = s.getsockname()[0]
finally:
s.close()
return ip
Username = str()
bytecount = 1024
dicts = {f"103.46.128.21:51203 (公网)" : "103.46.128.21:51203",
f"{get_host_ip()}:429 (私网)" : f"{get_host_ip()}:429",
"EXAM-41:429 (微机室)" : "EXAM-41:429"}
def address_split(address):
def func(ip="",port=0) -> (str, int):
return ip,int(port)
ip, port = func(*address.strip().split(':')[:2])
return {"ip":ip,
"port":port}
get_time = lambda: datetime.now().strftime('%H:%M:%S')
def threading(Daemon, **kwargs):
thread = Thread(**kwargs)
thread.setDaemon(Daemon)
thread.start()
return thread
def to_logging(command):
def logs(*args, **kwargs):
try:
command(*args, **kwargs)
except ConnectionResetError:
if "s" in dir():
s._connect = False
except Exception as e:
if "main" in dir():
main.Show_Message(format_exc())
else:
logging.exception(str())
return False
else:
return True
return logs
class Socket:
def __init__(self,Function=lambda i:None,code='utf-8'):
self.socket = socket.socket()
self.code = code
self._logger = Function
self.socket.settimeout(TIMEOUT)
self._connect = False
def set_func(self, f):
self._logger = f
def retry(self):
del self.socket
self.socket = socket.socket()
self.socket.settimeout(TIMEOUT)
def socket_connect(self):
if hasattr(self, "_socc"):
self.retry() #socket多次连接不同地址会出现 `OSError: [WinError 10022] 提供了一个无效的参数.`
else:
self._socc = True
try:
self.socket.connect(self.addr)
except socket.gaierror:
return f"获取地址信息失败.请确保{self.addr[0]}是有效地址或ipv4/ipv6"
except socket.timeout:
return f"连接超时({TIMEOUT}s).服务器[{self.addr[0]}:{self.addr[1]}]连接失败."
except OverflowError:
return f"输入的端口号为{self.addr[1]},端口号必须在0~65535间."
except ConnectionResetError:
pass
except OSError as e:
if int(self.addr[1]) == 0:
return "[WinError 10049] 在其上下文中,该请求的地址无效"
return str(e.args[1]).rstrip('。')
except TypeError:
return f"网络地址格式错误: 格式[ip:port] port必须为整型变量0~65535间."
except:
logging.exception(msg=str())
else:
return True
def connect(self, ip = None,port:int=0000, show=lambda: None):
if ip is None:
assert hasattr(self,"addr"), "ip address is empty."
else:
self.addr = (ip, port)
result = self.socket_connect()
if result is True:
show("[{}]: 连接成功".format(get_time()))
s._connect = True
return True
else:
show(f"[{get_time()}]: {result}")
s._connect = False
return False
def _handler(self):
self.socket.send(Username.encode(self.code))
while True:
try:
byte = self.socket.recv(bytecount **2)
if len(byte) == 0:
break
kb = len(byte) / bytecount
self._logger(f'{byte.decode(encoding=self.code)} {"<font size=1>%0.2f kb</font>" % kb}')
except Exception as e:
if not type(e) == socket.timeout:
for n in ["","ERROR".center(20,"-")]+format_exc().split('\n')+["".center(20,"-"),""]:
self._logger(f"<font color='red'>{n}</font>")
self.socket.close()
return
def run(self): #线程
self._connect = True
self.thread = threading(False, target=self._handler)
class Ui_Dialog(object):
def __init__(self):
Dialog = QtWidgets.QDialog()
self.Dialog = Dialog
Dialog.setObjectName("Dialog")
Dialog.resize(532, 239)
font = QtGui.QFont()
font.setFamily("Consolas")
Dialog.setFont(font)
Dialog.setAutoFillBackground(True)
Dialog.setStyleSheet("")
self.gridLayout_3 = QtWidgets.QGridLayout(Dialog)
self.gridLayout_3.setObjectName("gridLayout_3")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_3 = QtWidgets.QLabel(Dialog)
self.label_3.setText("")
self.label_3.setPixmap(QtGui.QPixmap("link.png"))
self.label_3.setObjectName("label_3")
self.horizontalLayout.addWidget(self.label_3)
self.label_4 = QtWidgets.QLabel(Dialog)
self.label_4.setObjectName("label_4")
self.horizontalLayout.addWidget(self.label_4)
self.gridLayout_3.addLayout(self.horizontalLayout, 0, 0, 1, 1)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_3.addItem(spacerItem, 0, 1, 1, 1)
self.progressBar = QtWidgets.QProgressBar(Dialog)
self.progressBar.setMaximum(3)
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
self.gridLayout_3.addWidget(self.progressBar, 2, 0, 1, 1)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout_3.addItem(spacerItem1, 2, 1, 1, 1)
self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setObjectName("pushButton")
self.gridLayout_3.addWidget(self.pushButton, 2, 2, 1, 1)
self.groupBox = QtWidgets.QGroupBox(Dialog)
self.groupBox.setObjectName("groupBox")
self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox)
self.gridLayout_2.setObjectName("gridLayout_2")
self.label_2 = QtWidgets.QLabel(self.groupBox)
font = QtGui.QFont()
font.setFamily("Consolas")
self.label_2.setFont(font)
self.label_2.setTextFormat(QtCore.Qt.AutoText)
self.label_2.setObjectName("label_2")
self.gridLayout_2.addWidget(self.label_2, 2, 0, 1, 1)
self.horizontalSlider = QtWidgets.QSlider(self.groupBox)
self.horizontalSlider.setAutoFillBackground(False)
self.horizontalSlider.setMinimum(1)
self.horizontalSlider.setMaximum(10)
self.horizontalSlider.setProperty("value", 3)
self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
self.horizontalSlider.setInvertedAppearance(False)
self.horizontalSlider.setInvertedControls(False)
self.horizontalSlider.setTickPosition(QtWidgets.QSlider.TicksBelow)
self.horizontalSlider.setObjectName("horizontalSlider")
self.gridLayout_2.addWidget(self.horizontalSlider, 4, 2, 1, 1)
self.label = QtWidgets.QLabel(self.groupBox)
font = QtGui.QFont()
font.setFamily("Consolas")
self.label.setFont(font)
self.label.setObjectName("label")
self.gridLayout_2.addWidget(self.label, 3, 0, 1, 1)
self.comboBox = QtWidgets.QComboBox(self.groupBox)
self.comboBox.setEditable(True)
self.comboBox.setObjectName("comboBox")
self.gridLayout_2.addWidget(self.comboBox, 3, 1, 1, 3)
self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox)
font = QtGui.QFont()
font.setFamily("Consolas")
self.lineEdit_2.setFont(font)
self.lineEdit_2.setAccessibleDescription("")
self.lineEdit_2.setInputMask("")
self.lineEdit_2.setObjectName("lineEdit_2")
self.gridLayout_2.addWidget(self.lineEdit_2, 2, 1, 1, 3)
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.label_5 = QtWidgets.QLabel(self.groupBox)
self.label_5.setObjectName("label_5")
self.gridLayout.addWidget(self.label_5, 0, 0, 1, 1)
self.lcdNumber = QtWidgets.QLCDNumber(self.groupBox)
self.lcdNumber.setStyleSheet("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(0, 255, 223, 255), stop:0.631841 rgba(255, 255, 255, 255));\n"
"")
self.lcdNumber.setFrameShadow(QtWidgets.QFrame.Raised)
self.lcdNumber.setLineWidth(1)
self.lcdNumber.setMidLineWidth(0)
self.lcdNumber.setSegmentStyle(QtWidgets.QLCDNumber.Filled)
self.lcdNumber.setProperty("intValue", 3)
self.lcdNumber.setObjectName("lcdNumber")
self.gridLayout.addWidget(self.lcdNumber, 0, 1, 1, 1)
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem2, 0, 2, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 4, 0, 1, 1)
self.label_6 = QtWidgets.QLabel(self.groupBox)
self.label_6.setStyleSheet("color:rgb(154, 154, 154);\n"
"font-size:13px")
self.label_6.setObjectName("label_6")
self.gridLayout_2.addWidget(self.label_6, 0, 0, 1, 1)
self.gridLayout_3.addWidget(self.groupBox, 1, 0, 1, 3)
self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setReadOnly(True)
self.lineEdit.setObjectName("lineEdit")
self.gridLayout_3.addWidget(self.lineEdit, 3, 0, 1, 3)
self.pushButton.setEnabled(False)
self.retranslateUi(Dialog)
self.pushButton.clicked.connect(self._connect)
self.horizontalSlider.valueChanged['int'].connect(self.lcdNumber.display)
self.horizontalSlider.valueChanged['int'].connect(self.set_timeout)
QtCore.QMetaObject.connectSlotsByName(Dialog)
self.lineEdit_2.textChanged.connect(lambda t: self.pushButton.setEnabled(bool(t.strip())))
self.running = False
self.timer = threading(True, target=self.add_bar)
def add_bar(self):
while True:
if self.running and self.progressBar.value() < TIMEOUT:
self.progressBar.setValue(self.progressBar.value() + 1)
time.sleep(1)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowIcon(QtGui.QIcon('login.ico'))
Dialog.setWindowTitle(_translate("Dialog", "connect"))
self.label_4.setText(_translate("Dialog", f"{socket.gethostname()}"))
self.progressBar.setFormat(_translate("Dialog", "%v / %m s"))
self.pushButton.setText(_translate("Dialog", "Connecting"))
self.groupBox.setTitle(_translate("Dialog", "Parameter Setup"))
self.label_2.setText(_translate("Dialog", "用户名:"))
self.horizontalSlider.setWhatsThis(_translate("Dialog", "set time out"))
self.label.setText(_translate("Dialog", "Select Socket Connect Address:"))
self.comboBox.addItems(dicts.keys())
self.lineEdit_2.setPlaceholderText(_translate("Dialog", "≤8个字符,多余自动删去"))
self.label_5.setText(_translate("Dialog", "最大超时秒数:"))
self.label_6.setText(_translate("Dialog", "[i] 未注册的用户将自动注册"))
self.lineEdit.setText(_translate("Dialog", "No return value."))
Dialog.show()
def set_timeout(self,t):
global TIMEOUT
TIMEOUT = int(t)
self.progressBar.setMaximum(TIMEOUT)
def set_text(self, m):
self.lineEdit.setText(QtCore.QCoreApplication.translate("Dialog", str(m)))
self.lineEdit.update()
@to_logging
def _connect(self, i):
texts = self.comboBox.currentText()
addr = address_split(dicts.get(texts, texts))
global TIMEOUT
TIMEOUT = self.horizontalSlider.value()
global Username
Username = self.lineEdit_2.text().strip()
self.groupBox.setEnabled(False)
self.progressBar.setValue(0)
self.running = True
self.set_text("[{}]: 尝试连接服务器[{}],最大超时报错 {}s".format(datetime.now().strftime('%Y %m %d %H:%M:%S'),addr["ip"],TIMEOUT))
if s.connect(**addr, show=self.set_text):
global main
main = Ui_MainWindow()
main.show()
def close(widget):
sleep(1)
widget.close()
threading(False, target=close, args=(self.Dialog, ))
self.groupBox.setEnabled(True)
self.running = False
class Ui_MainWindow(object):
def __init__(self):
MainWindow = QtWidgets.QMainWindow()
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 619)
font = QtGui.QFont()
font.setFamily("Consolas")
MainWindow.setFont(font)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.lineEdit_3 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_3.setReadOnly(True)
self.lineEdit_3.setObjectName("lineEdit_3")
self.gridLayout.addWidget(self.lineEdit_3, 7, 3, 1, 1)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setStyleSheet("background-color:rgb(44, 176, 13);\n"
"color:rgb(255, 255, 255);\n"
"font: 200 10pt \"Consolas\";")
self.pushButton.setObjectName("pushButton")
self.gridLayout.addWidget(self.pushButton, 8, 6, 1, 1)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem, 8, 5, 1, 1)
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 6, 1, 1, 1)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem1, 8, 3, 1, 1)
self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_2.setReadOnly(True)
self.lineEdit_2.setObjectName("lineEdit_2")
self.gridLayout.addWidget(self.lineEdit_2, 6, 3, 1, 1)
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 5, 1, 1, 1)
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
self.lineEdit.setDragEnabled(False)
self.lineEdit.setReadOnly(True)
self.lineEdit.setObjectName("lineEdit")
self.gridLayout.addWidget(self.lineEdit, 5, 3, 1, 1)
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 7, 1, 1, 1)
self.line = QtWidgets.QFrame(self.centralwidget)
self.line.setFrameShape(QtWidgets.QFrame.VLine)
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line.setObjectName("line")
self.gridLayout.addWidget(self.line, 5, 4, 3, 1)
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setObjectName("textEdit")
self.gridLayout.addWidget(self.textEdit, 5, 5, 3, 2)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem2, 1, 1, 1, 1)
self.textEdit_2 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_2.setObjectName("textEdit_2")
self.textEdit_2.setReadOnly(True)
self.gridLayout.addWidget(self.textEdit_2, 0, 3, 2, 4)
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setObjectName("pushButton_2")
self.gridLayout.addWidget(self.pushButton_2, 8, 1, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 24))
self.menubar.setObjectName("menubar")
self.menu = QtWidgets.QMenu(self.menubar)
self.menu.setObjectName("menu")
self.menulanguage = QtWidgets.QMenu(self.menu)
self.menulanguage.setObjectName("menulanguage")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.actionsocket_connet = QtWidgets.QAction(MainWindow)
self.actionsocket_connet.setObjectName("actionsocket_connet")
self.actionChinese = QtWidgets.QAction(MainWindow)
self.actionChinese.setObjectName("actionChinese")
self.actionip_socket_gethostbyname_socket_gethostname = QtWidgets.QAction(MainWindow)
self.actionip_socket_gethostbyname_socket_gethostname.setObjectName("actionip_socket_gethostbyname_socket_gethostname")
self.menulanguage.addSeparator()
self.menulanguage.addAction(self.actionChinese)
self.menu.addSeparator()
self.menu.addAction(self.menulanguage.menuAction())
self.menu.addAction(self.actionip_socket_gethostbyname_socket_gethostname)
self.menubar.addAction(self.menu.menuAction())
self.socket_peername = s.addr[0]
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.MainWindow = MainWindow
self.pushButton.clicked.connect(self.send)
self.pushButton_2.clicked.connect(self.re_connect)
self.connectEnabled(True)
@to_logging
def sendmsg(self):
data = self.textEdit.toPlainText().strip()
if data:
s.socket.send(data.encode('utf8'));self.textEdit.clear()
@to_logging
def send(self, _):
if hasattr(s,"_connect") and s._connect:
if not self.sendmsg():
QtWidgets.QMessageBox.information(self.MainWindow, 'TraceBack',f'Socket Server<{self.socket_peername}> 断开连接')
self.connectEnabled(False)
s._connect = False
else:
self.Show_Message("<font color='red'>发送异常. 未连接至服务器.请点击[重新连接服务器]按钮尝试重新连接.</font>")
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Socket"))
self.lineEdit_2.setText(socket.gethostname())
self.lineEdit.setText(socket.gethostbyname(socket.gethostname()))
self.lineEdit_3.setText(self.socket_peername)
self.pushButton.setText(_translate("MainWindow", "send"))
self.label_2.setText(_translate("MainWindow", "主机名:"))
self.label.setText(_translate("MainWindow", "本地端口:"))
self.label_3.setText(_translate("MainWindow", "连接端口:"))
self.pushButton_2.setText(_translate("MainWindow", "重新连接服务器"))
self.menu.setTitle(_translate("MainWindow", "设置"))
self.menulanguage.setTitle(_translate("MainWindow", "language"))
self.actionsocket_connet.setText(_translate("MainWindow", "socket connect"))
self.actionChinese.setText(_translate("MainWindow", "Chinese"))
self.actionip_socket_gethostbyname_socket_gethostname.setText(_translate("MainWindow", "ip: "+socket.gethostbyname(socket.gethostname()) ))
s.set_func(self.Show_Message)
s.run()
def show(self):
self.MainWindow.show()
@to_logging
def re_connect(self, _):
self.Show_Message("[{}]: 尝试连接服务器[{}],最大超时报错 {}s".format(datetime.now().strftime('%Y %m %d %H:%M:%S'),s.addr[0],TIMEOUT))
status = s.connect(show=self.Show_Message)
self.connectEnabled(status)
if status:
s.run()
def connectEnabled(self, status):
self.pushButton_2.setEnabled(not status)
def Show_Message(self, data):
if data:
for i in data.split('\n'):
if i:
sleep(0.06 / len(data.split('\n'))) #防止信息过快使Textedit刷新空白
self.textEdit_2.append(i)
self.textEdit_2.moveCursor(QtGui.QTextCursor.End)
if __name__ == "__main__":
if len(sys.argv) > 1:
dicts[f"{IP} (公网)"]["port"] = sys.argv[1]
app = QtWidgets.QApplication(sys.argv)
s = Socket()
conn = Ui_Dialog()
sys.exit(app.exec_())
| 图片链接
link.png
login.png(应该为.ico格式,直接将.png改为.ico即可,我已经换好了,但csdn平台不能传ico,所以改为了.png).