Как получить данные и использовать их в инструкции if()?
Я попытался получить данные из моего соединения этим кодом на 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.." прекрасно работает)
он просто передает код, поэтому, когда мой клиент запрашивает отключение запроса, он отправляется на сервер как "оригинальные" сообщения.. (Север не пинает его)
что я должен делать? Спасибо !
У вас две проблемы, и вам нужно исправить их обоих.
Во-первых, 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)
), поэтому, если вы получаете неожиданные исключения, у вас есть что-то отлаживать.