如何通过Socket获取Asterisk服务器状态 - Python

3 投票
2 回答
4853 浏览
提问于 2025-04-15 19:32

我正在尝试通过Python的socket来获取Asterisk服务器的状态,但什么都没有发生。

这是我的代码:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = '192.168.1.105'
PORT = 5038

s.connect((HOST, PORT))

params = """Action: login
Events: off
Username: admin
Secret: mypass

Action: status
Action: Logoff
"""

s.send(params)
data = s.recv(1024)
print data + '\n'
s.close()

我只收到一条消息,显示Asterisk的版本,其他的什么都没有。

希望有人能帮我解决这个问题。

提前谢谢大家。

2 个回答

1

处理这样简单的基于TCP的协议可能会变得有些棘手。

在这种情况下可能会遇到的问题:

  1. 每一行的结束符应该是'\r\n'(而不仅仅是'\n',就像你发送的那样)
  2. 你需要接收所有的输出,否则连接可能会被阻塞。请注意,输出可能会分成多个部分发送(虽然在这种情况下可能不会发生),你需要处理这些情况。

可以尝试这样做:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = '192.168.1.105'
PORT = 5038

s.connect((HOST, PORT))

params = ["Action: login",
          "Events: off",
          "Username: admin",
          "Secret: mypass"]

s.send("\r\n".join(params) + "\r\n")

# receive login response
data = ""
while "\r\n" not in data:
    data += s.recv(1024)

s.send("Action: status\r\n\r\n")

# receive action response
data = ""
while "\r\n" not in data:
    data += s.recv(1024)
print repr(data)

s.send("Action: Logoff\r\n\r\n")
s.close()
2

你的代码写得有点问题。Asterisk AMI(一个通信协议)要求命令之间要用\r\n来结束。

你需要把每个命令放在一个单独的数据包里:

params = """Action: login
Events: off
Username: admin
Secret: mypass"""

s.send(params + '\r\n')
data = s.recv(1024)
print data + '\n'

params = 'Action: status'
s.send(params + '\r\n')
data = s.recv(1024)
print data + '\n'

params = 'Action: Logoff'
s.send(params + '\r\n')
data = s.recv(1024)
print data + '\n'

这样就可以解决问题了。当然,你可能还想为这个写个函数或者其他的东西,但这样做就能让它正常工作。

记得把AMI命令分开哦!

撰写回答