Как получить данные и использовать их в инструкции if()?

-9

Я попытался получить данные из моего соединения этим кодом на python 2.7:

    server = socket(AF_INET, SOCK_STREAM)
server.bind(('0.0.0.0', 21))
server.listen(1)
client , addr = server.accept()
data = client.recv(2048)

Когда мне нужно распечатать или отправить другому соединению мои данные, они работают, однако я хочу добавить эти строки:

if(data == "/disconnect") :
<disconnect blha blha... you know >
else :
<print the data and send it back blha blha... >

(я проверил без этого, если выражение и "отключить blha blha.." прекрасно работает)

он просто передает код, поэтому, когда мой клиент запрашивает отключение запроса, он отправляется на сервер как "оригинальные" сообщения.. (Север не пинает его)

что я должен делать? Спасибо !

спросил(а) 2021-01-28T01:14:16+03:00 2 месяца, 2 недели назад
1
Решение
106

У вас две проблемы, и вам нужно исправить их обоих.

Во-первых, TCP-сокет - это всего лишь поток байтов. Когда вы делаете recv, вы не получите ровно одно сообщение, отправленное send с другой стороны, в данный момент вы получите все, что в буфере, - это может быть два сообщения, или половина сообщения, или что-нибудь еще. Когда вы просто тестируете соединения localhost на компьютере, который не сильно загружен, на многих платформах он будет делать то, что вы надеетесь на> 99% времени, но это просто затрудняет отладку проблемы, это не исправляет это. И как только вы попытаетесь получить доступ к одному и тому же коду через Интернет, он начнет провал большую часть времени, а не редко.

К счастью, клиент, как представляется, отправка сообщений в виде текста, без каких - либо внедренных новых строк, с \r\n отслуживших строки Windows, стиль между каждым сообщением. Это отличный протокол; вам просто нужно написать код для обработки этого протокола на стороне приема.

Вторая проблема заключается в том, что, даже если вам случится, чтобы получить именно одно сообщение send, что сообщение содержит \r\n конца-строки. И '/disconnect\r\n' == '/disconnect' конечно, будет ложным. Итак, как часть вашего обработчика протокола, вам нужно снять строки с новой строки.

Как бы то ни было, вы могли бы решить обе проблемы, используя метод makefile чтобы дать вам объект файла, который вы можете выполнять итерации, или readline и т.д., Так же, как вы делаете с файлом, который вы open с диска, который вы, вероятно, уже знаете как обращаться.

Но стоит узнать, как это сделать, поэтому я покажу вам, как это сделать вручную. Ключ в том, что вы храните буфер вокруг, добавляете каждый recv в этот буфер, а затем разделяете его на строки, помещаете остаток обратно в буфер и обрабатываете каждую строку в виде сообщения. Есть более элегантные/лаконичные способы написать это, но пусть это будет просто:

buf = ''
while True:
data = client.recv(2048)
buf += data
lines = buf.split('\r\n')
buf = lines.pop()
for line in lines:
# line is now a single message, with the newline stripped
if line == "/disconnect":
# do disconnect stuff
else:
# do normal message stuff

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

    if not data: означает, что клиент выполнил чистое (на уровне TCP) выключение. Таким образом, вам необходимо отключить и выйти из цикла приема.
      В зависимости от вашего дизайна может быть законным закрыть только сторону отправки и дождаться окончательного ответа с сервера, поэтому вы хотите убедиться, что вы закончили отправлять все, что у вас есть. (Это распространено во многих интернет-протоколах.) Возможно, даже законно не отправлять окончательную новую строку перед закрытием; если вы хотите поддержать это, вы должны проверить, является if buf: и если да, обработайте buf как последнюю команду. (Это не часто встречается во многих протоколах, но является общей ошибкой в клиентах, поэтому, например, многие веб-серверы будут обрабатывать его.)
    try:/except Exception as e: поймает всевозможные ошибки. Эти ошибки означают, что сокет больше не используется (или, что, конечно, серьезная ошибка в вашем коде), поэтому вы хотите справиться с этим, выбрасывая соединение и вырываясь из цикла приема, без предварительной отправки какого-либо окончательного ответа или прочитав любое окончательное сообщение.
      Это почти всегда стоит записывать, что e в некотором роде (возможно, просто print 'Error from', addr, repr(e)), поэтому, если вы получаете неожиданные исключения, у вас есть что-то отлаживать.

ответил(а) 2021-01-28T01:14:16+03:00 2 месяца, 2 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема