class SignUp(QtWidgets.QWidget, Ui_MainWindow): def __init__(self): super(SignUp, self).__init__() self.setupUi(self) self.db = ConnetMysql() self.pushButton.clicked.connect(self.sign_up) def sign_up(self): if self.lineEdit_2.text() != self.lineEdit_3.text(): return id = self.lineEdit.text() password = self.lineEdit_2.text() users = self.db.search("select id from users") for user in users: if user[0] == id: QtWidgets.QMessageBox.information(self, "提示", "该用户已存在,请直接登录") return self.db.insert("insert into users values(%s, %s, '0', 0, 0)", (id, password)) create_record_sql = "create table {}_record(" \ "date char(10) not null," \ "time char(15) not null," \ "record varchar(500) not null)engine = InnoDB".format(id) self.db.create_table(create_record_sql) QtWidgets.QMessageBox.information(self, "提示", "账号注册成功") self.close()
class Login(QtWidgets.QWidget, Ui_MainWindow): def __init__(self, chat_window, signup_window): super(Login, self).__init__() self.setupUi(self) self.pushButton.clicked.connect(self.login) self.pushButton_2.clicked.connect(self.sign_up) self.chat_window = chat_window self.signup_window = signup_window self.db = ConnetMysql() def login(self): id, password = self.lineEdit.text(), self.lineEdit_2.text() is_user = False ids_and_passwords = self.db.search("select id, password from users") for i, p in ids_and_passwords: if i == id and p == password: is_user = True break if is_user: self.db.update( "update users set alive = 1 where id = %s and password = %s", [id, password]) self.chat_window.show() self.chat_window.login(id) self.setHidden(True) else: QtWidgets.QMessageBox.information(self, "警告", "账号或密码错误") def sign_up(self): self.signup_window.show()
def __init__(self, chat_window, signup_window): super(Login, self).__init__() self.setupUi(self) self.pushButton.clicked.connect(self.login) self.pushButton_2.clicked.connect(self.sign_up) self.chat_window = chat_window self.signup_window = signup_window self.db = ConnetMysql()
def __init__(self, host='127.0.0.1', port=50000): self.host = host self.port = port self.sel = selectors.DefaultSelector() self.lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.id_to_sock = dict() self.db = ConnetMysql() self.start()
def __init__(self): super(Chat, self).__init__() self.setupUi(self) self.db = ConnetMysql() self.id = None self.client = None self.chat_record = [] self.saved_record_row = 0 self.pushButton.clicked.connect(self._send) self.pushButton_2.clicked.connect(self._save_chat_record) self.pushButton_3.clicked.connect(self._send_file) self.pushButton_4.clicked.connect(self._choose_directory)
class Chat(QtWidgets.QWidget, Ui_MainWindow): def __init__(self): super(Chat, self).__init__() self.setupUi(self) self.db = ConnetMysql() self.id = None self.client = None self.chat_record = [] self.saved_record_row = 0 self.pushButton.clicked.connect(self._send) self.pushButton_2.clicked.connect(self._save_chat_record) self.pushButton_3.clicked.connect(self._send_file) self.pushButton_4.clicked.connect(self._choose_directory) def login(self, id): self.id = id result = self.db.search( "select id from users where alive = 1 and id != %s", self.id) print(result) if result != (): users_alive = list(zip(*result))[0] self.listWidget.addItems(users_alive) self.client = Client(self) self._init_browser() def _send(self): msg = self.textEdit.toPlainText() users = self._get_users() if users == []: QtWidgets.QMessageBox.information(self, "警告", "请在右栏选择发送对象") return if msg == "": QtWidgets.QMessageBox.information(self, "警告", "输入栏为空") return for user in users: byte_msg = Message("transmit", self.id, user, msg).content_bytes self.client.socket.send(byte_msg) browser_msg = "({} to {}): {}".format(datetime.datetime.now(), user, msg).rstrip() self.textBrowser.append(browser_msg + "\n") self.chat_record.append(browser_msg) self.textEdit.clear() def _send_file(self): file_path = self.lineEdit.text() if not os.path.isfile(file_path): QtWidgets.QMessageBox.information(self, "错误", "文件不存在,请检查文件路径是否正确") return file_name = file_path.split("/")[-1] file_size = os.path.getsize(file_path) users = self._get_users() if users == []: QtWidgets.QMessageBox.information(self, "警告", "请在右栏选择发送对象") return f = open(file_path, "rb") content = f.read() f.close() for user in users: byte_file_header = Message("file", self.id, user, file_size, file_name).content_bytes self.client.socket.send(byte_file_header) self.client.socket.sendall(content) def _get_file_path_and_name(self): return "/home/agwave/PycharmProjects/socket/debug/libserver.py", "libserver.py" def _choose_directory(self): get_directory_path = QtWidgets.QFileDialog.getExistingDirectory( self, "选取文件所在文件夹", "/home/agwave/PycharmProjects/socket") if str(get_directory_path) != "": self.lineEdit.setText(str(get_directory_path)) QtWidgets.QMessageBox.information(self, "提示", "文件夹地址已输入,请继续输入文件名") def _sign_out(self): self.client.sign_out() self.close() def _save_chat_record(self): if len(self.chat_record) == self.saved_record_row: QtWidgets.QMessageBox.information(self, "警告", "当前保存记录已是最新") else: self.saved_record_row = self.db.save_chat_record( self.chat_record, self.saved_record_row, self.id) QtWidgets.QMessageBox.information(self, "信息", "已成功保存聊天记录") def _init_browser(self): self.textBrowser.append("---------过往聊天记录---------") sql = "select record from {} order by 'date', 'time'".format(self.id + "_record") record = self.db.search(sql) for r in record: self.textBrowser.append(r[0]) self.textBrowser.append("----------------------------") def _get_users(self): users = [] items = self.listWidget.selectedItems() for item in items: users.append(item.text()) return users def closeEvent(self, QCloseEvent): reply = QtWidgets.QMessageBox.question( self, '退出', "是否要退出系统?", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) if reply == QtWidgets.QMessageBox.Yes: self._sign_out() else: QCloseEvent.ignore()
def __init__(self): super(SignUp, self).__init__() self.setupUi(self) self.db = ConnetMysql() self.pushButton.clicked.connect(self.sign_up)
class Server(): def __init__(self, host='127.0.0.1', port=50000): self.host = host self.port = port self.sel = selectors.DefaultSelector() self.lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.id_to_sock = dict() self.db = ConnetMysql() self.start() def start(self): self.lsock.bind((self.host, self.port)) self.lsock.listen() print("listening on", (self.host, self.port)) self.lsock.setblocking(False) self.sel.register(self.lsock, selectors.EVENT_READ, data=None) def main(self): try: while True: events = self.sel.select(timeout=None) for key, mask in events: if key.data is None: self.accept_wrapper(key.fileobj) else: self.service_connection(key, mask) except KeyboardInterrupt: print("caught keyboard interrupt, exiting") finally: self.sel.close() def accept_wrapper(self, sock): conn, addr = sock.accept() # Should be ready to read print("accepted connection from", addr) conn.setblocking(False) data = types.SimpleNamespace(addr=addr, inb=b"", outb=b"") events = selectors.EVENT_READ | selectors.EVENT_WRITE self.sel.register(conn, events, data=data) self.db.update( "update users set ip = %s, port = %s where alive = 1 and ip = '0' and port = 0", addr) id = self.db.search( "select id from users where ip = %s and port = %s and alive = 1", addr) print("id: ", id) if id != (): self.id_to_sock[id[0][0]] = conn self._send_login_message_to_other_clients(id[0][0]) def service_connection(self, key, mask): try: sock = key.fileobj data = key.data if mask & selectors.EVENT_READ: recv_data = sock.recv(2048) # Should be ready to read if recv_data: self._process_recv(recv_data, data) else: self._process_client_sign_out(sock, data) except Exception as e: print(e) def _json_decode(self, json_bytes, encoding="utf-8"): tiow = io.TextIOWrapper(io.BytesIO(json_bytes), encoding=encoding, newline="") obj = json.load(tiow) tiow.close() return obj def _process_recv(self, recv_data, data): try: print("recv", repr(recv_data), "from", data.addr) data_dict = self._json_decode(recv_data) if recv_data is not None: action = data_dict.get("action") if action == "transmit": to_id = data_dict.get("to_id") sock = self.id_to_sock.get(to_id) sock.send(recv_data) print("send successfully") elif action == "file": self._trainsmit_file(recv_data, data_dict) elif action == "login" or action == "out": pass else: print(f'Error: invalid action "{action}".') except Exception as e: print(e) def _send_login_message_to_other_clients(self, id): message = Message("login", id, "", "").content_bytes for i in self.id_to_sock.keys(): if i != id: self.id_to_sock[i].send(message) def _process_client_sign_out(self, sock, data): print("closing connection to", data.addr) id = self.db.sign_out(data.addr) self.id_to_sock.pop(id) self.sel.unregister(sock) sock.close() for i in self.id_to_sock.keys(): self.id_to_sock[i].send(Message("out", id, "", "").content_bytes) def _trainsmit_file(self, recv_data, data_dict): to_id = data_dict.get("to_id") from_id = data_dict.get("from_id") from_sock = self.id_to_sock.get(from_id) sock = self.id_to_sock.get(to_id) file_size = data_dict.get("value") sock.send(recv_data) time.sleep(0.5) ready_msg = sock.recv(2048) if ready_msg.decode() == "ready": total_recv = 0 res = b"" while total_recv < file_size: file_data = from_sock.recv(2048) res += file_data total_recv += len(file_data) sock.sendall(res) time.sleep(0.5)