Найти - Пользователи
Полная версия: Сокеты
Начало » Python для новичков » Сокеты
1
SirRis
Всем привет! пишу свою первую прожку на питоне. Решил написать клиент-серверное приложение.
Вот это на сервере
 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 раза клиент закрывается с ошибкой.Я бы понял,если он просто повисал бы,в ожидании ответа от сервера.Что я делаю не так?
SirRis
Понял что байтовые строки и просто строки не есть одно и то же,поправил
 s.recv(1000000).decode('utf-8')
,вместо исключения в textedit записывается ответ сервера.
только после второго нажатия клиент все так же вылетает.Это из-за s.close() или conn.close(),да?
spikejke
Если необходимо держать соединение с сервером :
 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'))
    
SirRis
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()
SirRis
И еще теоретический вопрос,если у меня,скажем,будет миллион клиентов,подключенных к серверу можно ли использовать алгоритм с сокетами? Или есть какой-нибудь более удачный вариант?
spikejke
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"))
doza_and
spikejke
(глупо, всему виной GIL, но просто для примера)
Вы думаете? Попробуйте запустить миллион тредов в C без gil. Если ничего не делать то надо порядка мегабайта на тред стекового пространства. У вас на машине терабайт оперативки?
spikejke
doza_and
К сожалению, с С не знаком , но считаю использовать 1 ядро не выход.
doza_and
spikejke
но считаю использовать 1 ядро не выход.
Да частично вы правы. Но тут масштаб другой. Ну будет у вас 4 ядра. Но пользователей миллион
будет по 200000 на поток все равно.
Slow
select спасёт отцов сетевого взаимодействия
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB