Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 6, 2018 06:34:43

SirRis
Зарегистрирован: 2018-04-18
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

Сокеты

Всем привет! пишу свою первую прожку на питоне. Решил написать клиент-серверное приложение.
Вот это на сервере

 import socket
import sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1',8099))
s.listen(1)
conn, addr = s.accept()
data = conn.recv(1000000)
print ('client is at', addr , data)
conn.send(data)
conn.close()
Для клиента создал форму в QT Creator,для кнопки навесил обработчик
 self.pushButton.clicked.connect(self.send)
    def send(self):
         if self.lineEdit.text()!='':
             s.send(self.lineEdit.text().encode())
             try:
              # reactor.run()
              #  print(str(s.recv(1000000)))
              self.textEdit.setText(s.recv(1000000))
              s.close()
             except:
                 self.textEdit.setText('Ошибка!')
При нажатии на кнопку 2 раза клиент закрывается с ошибкой.Я бы понял,если он просто повисал бы,в ожидании ответа от сервера.Что я делаю не так?

Офлайн

#2 Июнь 6, 2018 07:47:08

SirRis
Зарегистрирован: 2018-04-18
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

Сокеты

Понял что байтовые строки и просто строки не есть одно и то же,поправил

 s.recv(1000000).decode('utf-8')
,вместо исключения в textedit записывается ответ сервера.
только после второго нажатия клиент все так же вылетает.Это из-за s.close() или conn.close(),да?

Офлайн

#3 Июнь 6, 2018 10:31:15

spikejke
Зарегистрирован: 2018-02-12
Сообщения: 42
Репутация: +  5  -
Профиль   Отправить e-mail  

Сокеты

Если необходимо держать соединение с сервером :

 import socket
with socket.socket() as sock:
    sock.bind(('127.0.0.1',8099))
    sock.listen(1)
    while True:
        conn, ip = sock.accept()
        with conn:
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                print(data.decode('utf-8'))
    

Офлайн

#4 Июнь 6, 2018 12:53:04

SirRis
Зарегистрирован: 2018-04-18
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

Сокеты

spikejke
Спасибо за ответ! Открыл для себя менеджеры контекста
Свою проблему решил так,кому интересно

  def send(self):
        if self.lineEdit.text() != '':
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect(('localhost', 8099))
            s.send(self.lineEdit.text().encode())
            try:
                self.textEdit.setText(s.recv(1024).decode('utf-8'))
                self.lineEdit.setText("")
                s.close()
            except:
                self.textEdit.setText('Ошибка!')
Перенес объявление переменной s в функцию и все взлетело.
Только я не очень понял,для чего вы написали этот цикл?
 while True:
        conn, ip = sock.accept()

Офлайн

#5 Июнь 6, 2018 13:09:04

SirRis
Зарегистрирован: 2018-04-18
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

Сокеты

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

Офлайн

#6 Июнь 6, 2018 20:57:48

spikejke
Зарегистрирован: 2018-02-12
Сообщения: 42
Репутация: +  5  -
Профиль   Отправить e-mail  

Сокеты

SirRis
И еще теоретический вопрос,если у меня,скажем,будет миллион клиентов,подключенных к серверу можно ли использовать алгоритм с сокетами? Или есть какой-нибудь более удачный вариант?
1. По поводу цикла - если не использовать акцепт в цикле при закрытие клиентской программы, сервер закрывает соеденение, а в цикле сервер продолжает ждать инициации.
2. Миллион соеденений
можно использовать потоки (глупо, всему виной GIL, но просто для примера)
 import threading
def process(conn, ip):
    with conn:
        while True:
             data = conn.recv(1024)
             if not data:
                 break
            print(data.decode('utf-8'))
with socke.socket() as sock:
    sock.bind(('127.0.0.1', 8099))
    sock.listen()
    while True:
        conn, ip = sock.accept()
        th = threading.Thread(target = process, args=(conn, ip))
        th.start()
Потоки + Процессы
 import socket
import threading
import multiprocessing
with socket.socket() as sock:
    sock.bind(("", 10001))
    sock.listen()
    
    workers_count = 3
    workers_list = [multiprocessing.Process(target=worker, args=(sock,))
                    for _ in range(workers_count)]
    
    for w in workers_list:
        w.start()
    
    for w in workers_list:
        w.join()
def worker(sock):
    while True:
        conn, addr = sock.accept()
        th = threading.Thread(target=process_request, args=(conn, addr))
        th.start()
def process_request(conn, addr):
    print("connected client:", addr)
    with conn:
        while True:
            data = conn.recv(1024)
            if not data:
                break
            print(data.decode("utf8"))

Отредактировано spikejke (Июнь 6, 2018 21:00:20)

Офлайн

#7 Июнь 6, 2018 21:17:06

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Сокеты

spikejke
(глупо, всему виной GIL, но просто для примера)
Вы думаете? Попробуйте запустить миллион тредов в C без gil. Если ничего не делать то надо порядка мегабайта на тред стекового пространства. У вас на машине терабайт оперативки?



Офлайн

#8 Июнь 6, 2018 21:28:58

spikejke
Зарегистрирован: 2018-02-12
Сообщения: 42
Репутация: +  5  -
Профиль   Отправить e-mail  

Сокеты

doza_and
К сожалению, с С не знаком , но считаю использовать 1 ядро не выход.

Офлайн

#9 Июнь 6, 2018 22:58:58

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Сокеты

spikejke
но считаю использовать 1 ядро не выход.
Да частично вы правы. Но тут масштаб другой. Ну будет у вас 4 ядра. Но пользователей миллион
будет по 200000 на поток все равно.



Офлайн

#10 Июнь 7, 2018 14:26:36

Slow
Зарегистрирован: 2017-07-26
Сообщения: 88
Репутация: +  4  -
Профиль   Отправить e-mail  

Сокеты

select спасёт отцов сетевого взаимодействия

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version