Чат на Python 3 Sockets

Мой первый топик, не знаю куда обратиться, проблемы с проектом, никто не знает как помочь, может тут кто-то будет в курсе?

Чат на сокетах, после добавления системы регистрации/логина перестает работать адекватно.

import socket
import threading
import sys
import pickle
import serveroperations

class Server():
	def __init__(self, host="localhost", port=4000):

		self.clients = []
		self.wwclients = {}
		self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.sock.bind((str(host), int(port)))
		self.sock.listen(10)
		self.sock.setblocking(False)

		aceptar = threading.Thread(target=self.acceptingConns)
		procesar = threading.Thread(target=self.recievingMsgs)
		
		aceptar.daemon = True
		aceptar.start()

		procesar.daemon = True
		procesar.start()

		while True:
			msg = input('->')
			if msg == 'exit':
				self.sock.close()
				sys.exit()
			else:
				pass


	def msg_to_all(self, msg, cliente):
		for c in self.clients:
			try:
				if c != cliente and self.wwclients[c.getpeername()][0] == 2:
					c.send(msg)
			except:
				del self.wwclients[c.getpeername()]
				self.clients.remove(c)

	def acceptingConns(self):
		print("Ожидание подключений")
		while True:
			try:
				conn, addr = self.sock.accept()
				conn.setblocking(False)
				self.clients.append(conn)
				self.wwclients[conn.getpeername()] = [0,'']
			except:
				pass

	def recievingMsgs(self):
		print("Ожидание сообщений")
		while True:
			if len(self.clients) > 0:
				for c in self.clients:
					try:
						data = c.recv(1024)
						sdata = repr(data)
						print(sdata)
						print(self.wwclients)
						if data:
							if self.wwclients[c.getpeername()][0] == 2:
								self.msg_to_all(data,c)
							elif self.wwclients[c.getpeername()][0] == 0:
								if serveroperations.check_name_exists(sdata):
									found = 0
									for b in self.wwclient:
										if b[1] == sdata:
											c.send('Такой пользователь уже залогинен')
											print('Пользователь {} попытался войти под '+\
												'уже залогиненым именем'.format(c.getpeername()))
											found = 1
									if not found:
										self.wwclient[c.getpeername()] = [1, sdata]
										c.send('Вы ввели логин')
										print('Пользователь {} ввел логин'.format(c.getpeername()))
								else:
									serveroperations.create_user(sdata)
									self.wwclients[c.getpeername()] = [1,sdata]
									c.send('Вы создали учетную запись')
									print('Пользователь {} создал учетную запись'.format(c.getpeername()))
							elif self.wwclients[c.getpeername()][0] == 1:
								if serveroperations.get_user_password() == '':
									serveroperations.set_user_password(self.wwclients[c.getpeername()][1],sdata)
									self.wwclients[c.getpeername()][0] = 2
									c.send('Вы залогинились')
									print('Пользователь {} залогинился'.format(c.getpeername()))
								elif serveroperations.get_user_password(self.wwclients[c.getpeername()][1]) == sdata:
									self.wwclients[c.getpeername()][0] = 2
									c.send('Вы залогинились')
									print('Пользователь {} залогинился'.format(c.getpeername()))
								else:
									self.wwclients[c.getpeername()] = [0,'']
									c.send('Вы ввели неверный пароль')
									print('Пользователь {} разлогинился'.format(c.getpeername()))

					except:
						pass


s = Server()
👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Изучай глубже. Поймешь больше. Чем больше в код войдешь тем независемее станешь.)

не знаю куда обратиться

на ru.stackoverflow.com обращайся, там будут помогать намного охотнее

1. receivingMsgs() лучше перевести на select.

2. Вы не умеете работать с TCP. Первейшая ошибка: считать, что посланное одним send будет получено одним recv. TCP — это поток _байтов_ (формально — октетов). Каждое сообщение должно иметь свою собственную длину, а не один ответ recv(). Где-то перед сообщением — длина в двоичном виде, где-то — сообщение заканчивается переводом строки, но какой-то из методов указать длину или терминацию обязан быть.
Без этого — могут быть любые варианты — послано 3 раза send, 4, 5, и 6 байт, но recv() отдаёт одну порцию на 15 байт; или послано 2000 байт, а recv() сначала выдал 1000, потом ещё 1000.
Очень вероятно, что ошибка связана с этим — если посылать логин и пароль одновременно, без задержки. Поставьте задержку между их отправкой в 5 секунд, если полечится — значит, это было; но писать так всё равно нельзя! Лучше уж перейдите на SCTP, если не хотите явно возиться с границами сообщений. Он поддерживается на всех нормальных ОС.

3. Что за имена типа wwclients? Почему не назвать это как-то понятнее, вроде conn_phase?

Тут ещё долго можно копаться, но вначале разберитесь с этими вопросами.

Не хочу использовать селект, с потоками лучше

Тогда receivingMsgs() в главном треде надо перевести на вариант, когда конкретный тред раздаёт всем остальным. Сейчас же он у Вас греет процессор.

у кого-то проблемы с тестовым

Тестовое у меня было лишь однажды и я его сделал нормально, сейчас учу питон и хочу сделать нормальный чат, типа обучение такое

Одно тестовое не сделал, но это лишь 33% из всего

перестает работать адекватно

Попробуйте сформулировать вопрос еще раз :)

Не регистрирует пользователя в базу данных, соответственно не доходит до статуса пассвординга, если выбрать статус 2 когда принимается соединение, тогда все нормально отсылает

Підписатись на коментарі