2016-05-26 1 views
0

Я пишу сценарий python TCP, который будет действовать как клиент и получить считывание температуры с контроллера температуры LakeShore336 (который действует как сервер). Мне нужно передать команду на сервер с клиента и вывести ответ. Я получаю выходы до «Spot 2» после отправки команды, но когда вызывается s.recv, я остаюсь висящим. (Python 2.7)Ответ сервера TCP

Client.py

import socket 

ip = '192.168.62.233' 
port = 7777    # The same port as used by the server/machine 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect((ip, port)) 

print 'Spot 1' 
s.send('KRDG? A[term]') 
print 'Spot 2' 
data = s.recv(4096) 
print 'Spot 3' 
s.close() 
print 'Received', repr(data) 

EDIT: В конце концов, мне просто нужно добавить

s.send('KRDG? A\r\n') 

Так что было терминатором. Спасибо за помощь.

+0

Правильно, 'recv()' является блокирующим вызовом. Он будет блокироваться до тех пор, пока сервер не отправит ответ до 4096 байт или не закроет соединение (это сложнее, но это простая история). Бьюсь об заклад, вы не закрываете соединение на сервере после отправки ответа. – grochmal

ответ

1

Причина, по которой ваш код «застревает», заключается в том, что recv() является блокирующим вызовом. Ваш процесс ожидает входящего пакета TCP, и вы выделили буфер из 4096 байт (что означает, что он может обрабатывать до такого количества байтов).

После того как этот пакет будет принят, ваш код продолжит работу и соединение будет закрыто, а затем распечатайте данные.

0

Вы отправляете литеральную строку [term] вместо отправки терминатора сообщений. Протокольная документация использует строку «[term]» для обозначения терминатора сообщений, это не означает буквенную строку «[term]»!

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

См. Раздел 6.3.4.1 из protocol specification для списка поддерживаемых терминаторов сообщений. Возвращение каретки, сопровождаемое новой строкой, должно работать.

Вы также получаете код. Вы вызываете функцию TCP recv и ожидаете, что она получит сообщение. Но он не знает, что такое сообщение, так как это просто функция TCP и не имеет понятия, какой протокол сообщений вы используете для связи с этим устройством. Вы должны написать свою собственную функцию приема, чтобы получить сообщение, так же, как вы должны были убедиться, что ваш код отправки действительно отправил сообщение.

Поскольку протокол сообщений этого устройства полностью соответствует общему понятию линии, использование функций, отправляющих и принимающих линии, сделает вашу жизнь намного проще. Просто используйте функцию «отправить строку» и скажите ей отправить «KRDG? A». Затем используйте функцию «приемная линия», чтобы получить ответ устройства.

+0

Да, я понимаю, что вы имеете в виду [термин] Я переключил это на s.send ('KRDG? ACR 0DHALF 0AH') включить терминатор. Разве у меня нет функции линии отправки и не получаю функцию линии, которая должна выполнить это? Или мне нужно написать их явно и удалить recv() –

+0

@ScottMacdonald Это зависит от вас. Один из способов - вызвать 'makefile()' в сокете, чтобы дать вам объект, на который вы можете называть 'readline'. –