TCP聊天+传输文件服务器服务器套接字v2.6 - 登录注册界面更新 - loading界面应用
TCP聊天+传输文件服务器服务器套接字v2.6
更改的地方:
主要是客户端界面更改
- 注册, 登录界面 (都知道啊,
v1.8
的改进后输入用户名, 到了主界面的时候才能输入密码, 但现在是直接输入用户名和密码, 然后转为json, 等待回复) - 转到注册 (我用了
commandLink
) - 记住密码 (
checkBox
, 如果记住报存到config.json
, 下次直接转入登录, 设置为默认) - 两大堡垒 (客户端与服务端两次堡垒, 防止更改客户端数据直接发送的[
不符合规范的json数据包
], 所以在服务端在识别[用户是否存在
] + [账户密码是否正确
]的前提下 又增加了[检测用户名密码长度
]的规则) - 界面淡入淡出
文章目录
- 客户端更改
- 服务端更改
- server.pyw
- data.py
- 客户端与服务端两次堡垒, 防止更改客户端数据直接发送的[不符合规范的json数据包], 所以在服务端在识别用户[是否存在] + [账户密码是否正确]的前提下 又增加了[检测用户名密码长度]的规则
- 资源
- gitcode
所有版本记录:
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 - 客户端连接服务器异常(异常情况分类)处理
v1.5
: PyQt5可编辑下拉框(comboBox):editable - python TCP服务器v1.5 - 客户端连接界面增加自定义参数(设置超时, 连接地址可选)
v1.6
: Python TCP服务器v1.6 - multiprocessing多进程及Ctrl-c(SIGINT)退出
v1.7
: Python TCP服务器v1.7 - PyQt5 server服务端来临
v1.8
: python TCP服务器v1.8 - PyQt5登录界面美化+淡入淡出
v1.9
: socketTCP协程文件+信息传递 - TCP聊天文件服务器v1.9 - 划时代的版本更新(4.6万字)
v2.0
: TCP聊天文件服务器v2.0 - 重大bug修复+PyQt5文件传输可视化
v2.1
: TCP聊天文件服务器v2.1 - 服务端线程管理(threading.enumerate)
v2.2
: TCP聊天文件服务器v2.2 - 服务端客户端套接字解决分包/粘包问题 - SocketQueue继承以及减少冗余
v2.3
: gzip的使用 - TCP聊天文件服务器v2.3 - 文件传输建立缓存制度和.gz的解压缩/压缩解决运行内存过大
v2.4
: 网络传输测速 - TCP聊天+传输文件服务器服务器套接字v2.4 - socket协程文件传送测速
v2.5
: TCP聊天+传输文件服务器服务器套接字v2.5 - socket测速规范已经gzip的弃用
loading界面参见 我的csdn博客 - pyqt5 等待界面 (QMovie 加载 gif)
客户端更改
class Socket(SocketClient):def __init__(self, Function=lambda i: None, code='utf-8'):super(Socket, self).__init__(codec=code)self.handler = message_handle(self.send)def parse_argument(self, arg: str) -> str:return self.handler.handle(arg.strip())def receive_text(self):return super(Socket, self).recv()def recv(self):result = super(Socket, self).recv()if isinstance(result, str) and result:self._traceback(f'{result} <font size=1>{convert(len(result))}</font>')return self.isOpen()def forever_receive(self) -> None:self.handler.send_text(self.header)while True:if not self.recv():returndef Check_info(self, *args, **kwargs):threading(True, target = lambda: self.__Check_info(*args, **kwargs))def __Check_info(self, info, emit, return_func, err_func):if not self.is_connect():res, trace = self.connect()emit(bool(res))if not res:return err_func(trace)self.handler.send_text(json.dumps(info))emit(True)data = self.receive_text()emit(True)try:data = json.loads(data)except (ValueError, KeyError):return err_func("解析异常!")else:emit(True)return_func(data)def run(self): # 线程threading(True, target=self.forever_receive)def quitEvent(self):self.__is_connect = Falseif main.is_setup:main.ConnectionError_signal.emit()LOGIN_INFO_FILE = "config.json"
LOGIN_INFO = {"type": 0,"username": "","password": ""}if os.path.isfile(LOGIN_INFO_FILE):with open(LOGIN_INFO_FILE, "r") as f:LOGIN_INFO = json.load(f)def json_dump():with open(LOGIN_INFO_FILE, "w") as f:json.dump(LOGIN_INFO, f, indent=4)def Animation(parent, type=b"windowOpacity", from_value=0, to_value=1, ms=1000, connect=None):anim = QPropertyAnimation(parent, type)anim.setDuration(ms)anim.setStartValue(from_value)anim.setEndValue(to_value)if connect:anim.finished.connect(connect)anim.start()return animclass LoadingProgress(QtWidgets.QDialog):update_signal = QtCore.pyqtSignal(bool)def __init__(self, parent=None):super(LoadingProgress, self).__init__(parent)self.value = 0self.update_signal.connect(self.update_progress)vbox = QtWidgets.QVBoxLayout(self)self.steps = [f"连接服务器中({TIMEOUT}s)...","发送数据中...","接收数据中...","解析数据中..."]self.movie_label = QtWidgets.QLabel()self.movie = QtGui.QMovie("images/loading.gif")self.movie_label.setMovie(self.movie)self.movie.start()self.progress_label = QtWidgets.QLabel()self.label_update()vbox.addWidget(self.movie_label)vbox.addWidget(self.progress_label)self.setLayout(vbox)# self.exec_()def label_update(self):self.progress_label.setText(self.steps[self.value])def update_progress(self, boolean: bool) -> None:self.value += 1if boolean and self.value < len(self.steps):self.label_update()else:self.close()class User_Setup(QtWidgets.QDialog):end_anim, start_anim = None, Nonelog_progress_signal = QtCore.pyqtSignal(str)reg_progress_signal = QtCore.pyqtSignal(str)handle_signal = QtCore.pyqtSignal(dict)err_signal = QtCore.pyqtSignal(str)loading_dialog = Nonesuccessful = Falsedef closeEvent(self, event: QtGui.QCloseEvent) -> None:if not self.end_anim:self.end_anim = Animation(self, ms=2000, from_value=1, to_value=0, connect=self.close)event.ignore()else:if self.successful:main.SetupUi()def __init__(self, parent=None):super().__init__(parent)self.start_anim = Animation(self, ms=2000)self.setObjectName("Dialog")self.resize(362, 394)font = QtGui.QFont()font.setFamily("Consolas")font.setPointSize(12)self.setFont(font)icon = QtGui.QIcon()icon.addPixmap(QtGui.QPixmap("images/user.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)self.setWindowIcon(icon)self.setAutoFillBackground(True)self.gridLayout = QtWidgets.QGridLayout(self)self.gridLayout.setObjectName("gridLayout")self.label = QtWidgets.QLabel(self)self.label.setFocusPolicy(QtCore.Qt.StrongFocus)self.label.setStyleSheet("")self.label.setText("")self.label.setPixmap(QtGui.QPixmap("images/zmh.png"))self.label.setObjectName("label")self.gridLayout.addWidget(self.label, 0, 0, 1, 1)self.tabWidget = QtWidgets.QTabWidget(self)self.tabWidget.setAccessibleName("")self.tabWidget.setAutoFillBackground(True)self.tabWidget.setObjectName("tabWidget")self.log = QtWidgets.QWidget()self.log.setObjectName("login")self.gridLayout_2 = QtWidgets.QGridLayout(self.log)self.gridLayout_2.setObjectName("gridLayout_2")self.lineEdit_5 = QtWidgets.QLineEdit(self.log)self.lineEdit_5.setStyleSheet(" QLineEdit\n"" {border:0px;\n"" border-radius:0;\n"" font: 12pt \"Consolas\";\n"" margin:15px;\n"" border-bottom: 2px solid #B3B3B3;}\n"" QLineEdit:hover{\n"" border-bottom:3px solid #66A3FF;\n"" }\n"" QLineEdit:focus{\n"" border-bottom:3px solid #E680BD\n"" }")self.lineEdit_5.setText("")self.lineEdit_5.setEchoMode(QtWidgets.QLineEdit.Password)self.lineEdit_5.setClearButtonEnabled(True)self.lineEdit_5.setObjectName("lineEdit_5")self.gridLayout_2.addWidget(self.lineEdit_5, 2, 0, 1, 2)self.lineEdit_4 = QtWidgets.QLineEdit(self.log)self.lineEdit_4.setStyleSheet(" QLineEdit\n"" {border:0px;\n"" border-radius:0;\n"" font: 12pt \"Consolas\";\n"" margin:15px;\n"" border-bottom: 2px solid #B3B3B3;}\n"" QLineEdit:hover{\n"" border-bottom:3px solid #66A3FF;\n"" }\n"" QLineEdit:focus{\n"" border-bottom:3px solid #E680BD\n"" }")self.lineEdit_4.setClearButtonEnabled(True)self.lineEdit_4.setObjectName("lineEdit_4")self.gridLayout_2.addWidget(self.lineEdit_4, 1, 0, 1, 2)self.pushButton_2 = QtWidgets.QPushButton(self.log)icon1 = QtGui.QIcon()icon1.addPixmap(QtGui.QPixmap("images/login.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)self.pushButton_2.setIcon(icon1)self.pushButton_2.setObjectName("pushButton_2")self.gridLayout_2.addWidget(self.pushButton_2, 6, 1, 1, 1)self.checkBox_2 = QtWidgets.QCheckBox(self.log)self.checkBox_2.setChecked(True)self.checkBox_2.setObjectName("checkBox_2")self.gridLayout_2.addWidget(self.checkBox_2, 6, 0, 1, 1)self.label_3 = QtWidgets.QLabel(self.log)font = QtGui.QFont()font.setFamily("Comic Sans MS")font.setPointSize(11)font.setBold(False)font.setItalic(False)font.setWeight(50)self.label_3.setFont(font)self.label_3.setStyleSheet("color: rgb(255, 1, 39);\n""font: 11pt \"宋体\";")self.label_3.setObjectName("label_3")self.gridLayout_2.addWidget(self.label_3, 4, 0, 1, 2)self.commandLinkButton = QtWidgets.QCommandLinkButton(self.log)font = QtGui.QFont()font.setFamily("Segoe UI")font.setPointSize(12)self.commandLinkButton.setFont(font)self.commandLinkButton.setObjectName("commandLinkButton")self.gridLayout_2.addWidget(self.commandLinkButton, 3, 0, 1, 2)self.tabWidget.addTab(self.log, "")self.reg = QtWidgets.QWidget()self.reg.setObjectName("reg")self.gridLayout_3 = QtWidgets.QGridLayout(self.reg)self.gridLayout_3.setObjectName("gridLayout_3")self.pushButton = QtWidgets.QPushButton(self.reg)icon2 = QtGui.QIcon()icon2.addPixmap(QtGui.QPixmap("images/register.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)self.pushButton.setIcon(icon2)self.pushButton.setObjectName("pushButton")self.gridLayout_3.addWidget(self.pushButton, 5, 1, 1, 1)self.checkBox = QtWidgets.QCheckBox(self.reg)self.checkBox.setChecked(True)self.checkBox.setTristate(False)self.checkBox.setObjectName("checkBox")self.gridLayout_3.addWidget(self.checkBox, 5, 0, 1, 1)self.lineEdit_3 = QtWidgets.QLineEdit(self.reg)self.lineEdit_3.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)self.lineEdit_3.setAccessibleName("")self.lineEdit_3.setStyleSheet(" QLineEdit\n"" {border:0px;\n"" border-radius:0;\n"" font: 12pt \"Consolas\";\n"" margin:15px;\n"" border-bottom: 2px solid #B3B3B3;}\n"" QLineEdit:hover{\n"" border-bottom:3px solid #66A3FF;\n"" }\n"" QLineEdit:focus{\n"" border-bottom:3px solid #E680BD\n"" }")self.lineEdit_3.setEchoMode(QtWidgets.QLineEdit.Password)self.lineEdit_3.setDragEnabled(False)self.lineEdit_3.setClearButtonEnabled(True)self.lineEdit_3.setObjectName("lineEdit_3")self.gridLayout_3.addWidget(self.lineEdit_3, 2, 0, 1, 2)self.lineEdit_2 = QtWidgets.QLineEdit(self.reg)font = QtGui.QFont()font.setFamily("Consolas")font.setPointSize(12)font.setBold(False)font.setItalic(False)font.setWeight(50)self.lineEdit_2.setFont(font)self.lineEdit_2.setStyleSheet(" QLineEdit\n"" {border:0px;\n"" border-radius:0;\n"" font: 12pt \"Consolas\";\n"" margin:15px;\n"" border-bottom: 2px solid #B3B3B3;}\n"" QLineEdit:hover{\n"" border-bottom:3px solid #66A3FF;\n"" }\n"" QLineEdit:focus{\n"" border-bottom:3px solid #E680BD\n"" }")self.lineEdit_2.setInputMask("")self.lineEdit_2.setEchoMode(QtWidgets.QLineEdit.Password)self.lineEdit_2.setDragEnabled(False)self.lineEdit_2.setCursorMoveStyle(QtCore.Qt.LogicalMoveStyle)self.lineEdit_2.setClearButtonEnabled(True)self.lineEdit_2.setObjectName("lineEdit_2")self.gridLayout_3.addWidget(self.lineEdit_2, 1, 0, 1, 2)self.lineEdit = QtWidgets.QLineEdit(self.reg)font = QtGui.QFont()font.setFamily("Consolas")font.setPointSize(12)font.setBold(False)font.setItalic(False)font.setWeight(50)self.lineEdit.setFont(font)self.lineEdit.setStyleSheet(" QLineEdit\n"" {border:0px;\n"" border-radius:0;\n"" font: 12pt \"Consolas\";\n"" margin:15px;\n"" border-bottom: 2px solid #B3B3B3;}\n"" QLineEdit:hover{\n"" border-bottom:3px solid #66A3FF;\n"" }\n"" QLineEdit:focus{\n"" border-bottom:3px solid #E680BD\n"" }")self.lineEdit.setEchoMode(QtWidgets.QLineEdit.Normal)self.lineEdit.setClearButtonEnabled(True)self.lineEdit.setObjectName("lineEdit")self.gridLayout_3.addWidget(self.lineEdit, 0, 0, 1, 2)self.label_6 = QtWidgets.QLabel(self.reg)self.label_6.setStyleSheet("color: rgb(255, 1, 39);\n""font: 11pt \"宋体\";")self.label_6.setObjectName("label_6")self.gridLayout_3.addWidget(self.label_6, 3, 0, 1, 2)self.tabWidget.addTab(self.reg, "")self.gridLayout.addWidget(self.tabWidget, 2, 0, 1, 3)self.label_2 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setFamily("Comic Sans MS")font.setPointSize(14)self.label_2.setFont(font)self.label_2.setObjectName("label_2")self.gridLayout.addWidget(self.label_2, 0, 1, 1, 1)spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)self.gridLayout.addItem(spacerItem, 0, 2, 1, 1)self.comboBox = QtWidgets.QComboBox(self)font = QtGui.QFont()font.setFamily("Prestige Elite Std")font.setPointSize(13)font.setBold(False)font.setItalic(False)font.setWeight(50)self.comboBox.setFont(font)self.comboBox.setStyleSheet("")self.comboBox.setEditable(True)self.comboBox.setObjectName("comboBox")self.gridLayout.addWidget(self.comboBox, 1, 0, 1, 2)self.tabWidget.setCurrentIndex(LOGIN_INFO["type"])QtCore.QMetaObject.connectSlotsByName(self)self.commandLinkButton.clicked.connect(lambda: self.tabWidget.setCurrentIndex(1))_translate = QtCore.QCoreApplication.translateself.setWindowTitle(_translate("Dialog", "登录 - 注册"))self.lineEdit_5.setPlaceholderText(_translate("Dialog", "密码(4-10字符)"))self.lineEdit_4.setPlaceholderText(_translate("Dialog", "用户名(2-12字符)"))self.pushButton_2.setText(_translate("Dialog", "登录"))self.checkBox_2.setText(_translate("Dialog", "记住密码"))self.label_3.setText(_translate("Dialog", ""))self.commandLinkButton.setText(_translate("Dialog", "没有账号? 注册一个"))self.tabWidget.setTabText(self.tabWidget.indexOf(self.log), _translate("Dialog", "登录"))self.pushButton.setText(_translate("Dialog", "注册"))self.checkBox.setText(_translate("Dialog", "记住密码"))self.lineEdit_3.setPlaceholderText(_translate("Dialog", "再次输入密码(4-10字符)"))self.lineEdit_2.setPlaceholderText(_translate("Dialog", "密码(4-10字符)"))self.lineEdit.setPlaceholderText(_translate("Dialog", "用户名(2-12字符)"))self.label_6.setText(_translate("Dialog", ""))self.tabWidget.setTabText(self.tabWidget.indexOf(self.reg), _translate("Dialog", "注册"))self.label_2.setText(_translate("Dialog", "Socketserver"))self.comboBox.addItems(ip_list)self.log_progress_signal.connect(self.label_3.setText)self.reg_progress_signal.connect(self.label_6.setText)self.handle_signal.connect(self.handle)self.err_signal.connect(self.err_handle)if LOGIN_INFO["type"] == 0:# loginself.lineEdit_4.setText(LOGIN_INFO["username"])self.lineEdit_5.setText(LOGIN_INFO["password"])elif LOGIN_INFO["type"] == 1:self.lineEdit.setText(LOGIN_INFO["username"])self.lineEdit_2.setText(LOGIN_INFO["password"])self.lineEdit_3.setText(LOGIN_INFO["password"])self.pushButton.clicked.connect(self.register)self.pushButton_2.clicked.connect(self.login)self.show()def Enable(self, boolean):self.pushButton.setEnabled(boolean)self.pushButton_2.setEnabled(boolean)def get_ip(self) -> str:return self.comboBox.currentText()def clear(self):self.label_3.setText("")self.label_6.setText("")def login(self, *args):self.clear()self.Enable(False)self._login()def err_handle(self, string):self.label_3.setText(string)self.label_6.setText(string)self.Enable(True)def handle(self, dictionary: (dict, str)):if isinstance(dictionary, dict):result = dictionary.get("result", False)reason = dictionary.get("reason", False)if not result:self.err_handle(reason)else:self.successful = Trueself.close()self.Enable(True)def login_trace(self, res: bool, reason: str):self.label_3.setText(reason)self.Enable(True)def loading(self) -> callable:self.loading_dialog = LoadingProgress(self)return self.loading_dialog.update_signal.emitdef exec_loading_dialog(self):if isinstance(self.loading_dialog, LoadingProgress):self.loading_dialog.exec_() # 直接使用造成阻塞, 为此单独调用.def _login(self):username = self.lineEdit_4.text().strip()password = self.lineEdit_5.text().strip()if not username:return self.login_trace(False, "未填写用户名!")if not password:return self.login_trace(False, "未填写密码!")if not 2 <= len(username) <= 12:return self.login_trace(False, "用户名需在2~12位之间!")if not 4 <= len(password) <= 10:return self.login_trace(False, "密码需在4~10位之间!")try:addr, port = self.get_ip().split(":")assert isinstance(addr, str)port = int(port)except (ValueError, AssertionError):return self.login_trace(False, "ipv4地址不正确! 结构:[host:port]")s.change_address(addr, port)s.Check_info({"type": 0, "username": username, "password": password}, self.loading(),self.handle_signal.emit, self.err_signal.emit) # self.log_progress_signalself.exec_loading_dialog()global LOGIN_INFOLOGIN_INFO["username"] = usernameLOGIN_INFO["password"] = passwordif self.checkBox_2.isChecked():json_dump()return True, ""def register(self, *args):self.Enable(False)self.clear()self._register()def register_trace(self, res: bool, reason: str):self.label_6.setText(reason)self.Enable(True)def _register(self):username = self.lineEdit.text().strip()password = self.lineEdit_2.text().strip()password_check = self.lineEdit_3.text().strip()if not password_check == password:return self.register_trace(False, "两次输入密码不同!")if not username:return self.register_trace(False, "未填写用户名!")if not password:return self.register_trace(False, "未填写密码!")if not 2 <= len(username) <= 12:return self.register_trace(False, "用户名需在2~12位之间!")if not 4 <= len(password) <= 10:return self.register_trace(False, "密码需在4~10位之间!")try:addr, port = self.get_ip().split(":")assert isinstance(addr, str)port = int(port)except (ValueError, AssertionError):return self.register_trace(False, "ipv4地址不正确! 结构:[host:port]")s.change_address(addr, port)s.Check_info({"type": 1, "username": username, "password": password}, self.loading(),self.handle_signal.emit, self.err_signal.emit) # self.reg_progress_signalself.exec_loading_dialog()global LOGIN_INFOLOGIN_INFO["username"] = usernameLOGIN_INFO["password"] = passwordif self.checkBox.isChecked():json_dump()return True, ""
服务端更改
server.pyw
class Client(...):...@ignoredef forever_receive(self):while self.isOpen():result, reason, uname = self.server.user_record.handler(**self.json_data())self.send(json.dumps({"result": result, "reason": reason}))if result:self.username = unamebreakself._login = Trueself.server.login(self.username, self.addr)while self.isOpen():string = self.recv()if string is None:continueelif self.com.iscommand(string):self.send(self.com.handler(string))else:self.server.UserMessage(self.addr, self.username, string)
data.py
file = r'.\clients\data.json'
folder = r'.\clients'
if not path.exists(folder):mkdir(folder)class data:def __init__(self):if path.exists(file):with open(file, 'r') as f:self.data = load(f)else:self.data = {}def __get__(self, username, default=None) -> tuple:return self.data.get(username, default)def __in__(self, username) -> bool:return username in self.data.keys()def __write__(self) -> None:with open(file, 'w') as f:dump(self.data, f, indent=4)def __register__(self, username, password, time: (int, float) = time()) -> None:self.data[username] = (encode(password), int(time))self.__write__()def __login__(self, username, password) -> bool:return self.data[username][0] == encode(password)def get_time(self, username):return self.data[username][1]def handler(self, type: int, username: str, password: str):username = username.strip()if not username:return False, "未填写用户名!", ""password = password.strip()if not password:return False, "未填写密码!", ""if not 2 <= len(username) <= 12:return False, "用户名需在2~12位之间!", ""if not 4 <= len(password) <= 10:return False, "密码需在4~10位之间!", ""if type == 0: # loginif not self.__in__(username):return False, "用户不存在!", ""if not self.__login__(username, password):return False, "用户名 / 密码错误!", ""return True, "欢迎回来, " + username, usernameelif type == 1: # registerif self.__in__(username):return False, "已存在用户!", ""self.__register__(username, password)return True, "初来乍到, " + username, username
客户端与服务端两次堡垒, 防止更改客户端数据直接发送的[不符合规范的json数据包], 所以在服务端在识别用户[是否存在] + [账户密码是否正确]的前提下 又增加了[检测用户名密码长度]的规则
资源
resource
gitcode
zmh-program / Python套接字Socket服务器
TCP聊天+传输文件服务器服务器套接字v2.6 - 登录注册界面更新 - loading界面应用相关推荐
- python 数据库性能提升 - TCP聊天+传输文件服务器服务器套接字v2.7
TCP聊天+传输文件服务器服务器套接字v2.7 刚创建服务器的时候为了后期便于管理, 主要也是MySQL对我不适合, 跨平台使用, 一打包还有得装, 所以直接自己做了个 这是我写的服务器的数据库代码, ...
- MFC基于TCP协议的CSocket类套接字服务器端代码示范
MFC基于TCP协议的CSocket类套接字服务器端代码示范 https://blog.csdn.net/txwtech/article/details/93417667 转载于:https://ww ...
- 前端学习(1856)vue之电商管理系统电商系统之安装mysql出现mysql报错:Can’t start server: Bind on TCP/IP port: 通常每个套接字地址(协议/网络地址
2020-07-26T11:44:29.778919Z 0 [ERROR] [MY-010262] [Server] Can't start server: Bind on TCP/IP port: ...
- svnserve: 不能绑定服务器套接字: 地址已在使用
[root@host conf]# svnserve -d -r /var/svn svnserve: 不能绑定服务器套接字: 地址已在使用 说明该进程正在使用可以用命令 ps -aux 查看进程 用 ...
- 网络协议OSI、TCP/IP协议、Socket套接字和第三方AsyncSock的使用等解析
一.网络协议定义 1.OSI参考模型:全称(Open System Interconnection), 开放式系统互联参考模型.是一个逻辑上的定义,一个规范,它把网络协议从逻辑上分为七层,只要目的是为 ...
- 网络七层协议 五层模型 TCP连接 HTTP连接 socket套接字
socket(套接字)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程 ...
- Mac用Xcode建立TCP和UDP Socket(套接字)编程
TCP和UDP均采用自己电脑,既做服务器端又做客户端,当然Xcode无法同时运行两个Target,所以可以选择一个在终端,一个在Xcode,或者两个都在终端. TCP服务器端: #include< ...
- TCP聊天文件服务器v2.2 - 服务端客户端套接字解决分包/粘包问题 - SocketQueue继承以及减少冗余
TCP聊天+传输文件服务器服务器套接字v2.2 整个图当封面吧 所有版本记录: v1.0 : TCP聊天服务器套接字|PyQt5+socket(TCP端口映射+端口放行)+logging+Thread ...
- TCP聊天文件服务器v2.0 - 重大bug修复+PyQt5文件传输可视化
TCP聊天+传输文件服务器服务器套接字v2.0 所有版本记录: v1.0 : TCP聊天服务器套接字|PyQt5+socket(TCP端口映射+端口放行)+logging+Thread(含日志,htm ...
最新文章
- 计算机基础及应用笔试,计算机基础及应用测试笔试题
- 桌面计算机安全策略,设置组策略实现Windows桌面显示计算机信息
- oracle 还原归档,ORACLE RMAN 还原归档日志
- HUSD审计报告:托管账户储备超7.87亿美元
- Android软件安全开发实践(下)
- (@WhiteTaken)设计模式学习——代理模式
- 数据库系统教程第三版施伯乐
- Java Web实战详细教程(一)系列介绍+环境搭建
- eclipse如何装php插件,Eclipse PHP插件(PHPEclipse)安装与配置图解
- 华为解锁刷机root教程详解
- javascript 字符串分割的方法总结区分
- 笔记本插入耳机,声音依然外放怎么办?
- Python3正则匹配re.split,re.serach,re.sub,re.finditer及re.findall函数用法详解
- iOS 9 spotlight搜索 3DTouch
- GCF(4)----手机认证相关知识
- Ubuntu20.04安装CUDA+CUDNN+Conda+PyTorch
- dnf搬砖代码Python_让搬砖变得轻松——python操作excel用的脚本
- 大学生计算机装机配置作业,不愧是计算机专业的大学生,自己写配置来装机,万元电脑真霸气...
- AD设计PCB从入门到精通(学习思路总结)
- 模拟舵机、数字舵机、总线舵机的区别