1

这是我连接到 Asterisk Manager 界面的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text.RegularExpressions;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.IO;


namespace WindowsFormsApplication1
{

public partial class Form1 : Form
{

    private Socket clientSocket;
    private byte[] data = new byte[1024];
    private int size = 1024;
    //------------------------------------------------------------------------------------------
    public Form1()
    {
        InitializeComponent();            
    }

    //------------------------------------------------------------------------------------------
    [STAThread]
    private void BtnConnect_Click(object sender, EventArgs e)
    {
        try
        {
            AddItem("Connecting...");
            clientSocket = new Socket(AddressFamily.InterNetwork,
                                  SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint iep = new IPEndPoint(IPAddress.Parse("192.168.1.155"), 5038);
            clientSocket.BeginConnect(iep, new AsyncCallback(Connected), clientSocket);
        }
        catch (Exception exp)
        {

            AddItem(exp.Message);
        }
    }

    //------------------------------------------------------------------------------------------
    private void BtnDisconnect_Click(object sender, EventArgs e)
    {
        clientSocket.Close();
    }

    //------------------------------------------------------------------------------------------
    void Connected(IAsyncResult iar)
    {
        clientSocket = (Socket)iar.AsyncState;
        try
        {
            clientSocket.EndConnect(iar);
            AddItem("Connected to: " + clientSocket.RemoteEndPoint.ToString());                
            clientSocket.BeginReceive(data, 0, size, SocketFlags.None,
                          new AsyncCallback(OnDataReceive), clientSocket);
        }
        catch (Exception exp)
        {
            AddItem("Error connecting: " + exp.Message);
        }
    }
    //------------------------------------------------------------------------------------------

    private void OnDataReceive(IAsyncResult result)
    {
        Socket remote = (Socket)result.AsyncState;
        int recv = remote.EndReceive(result);
        string stringData = Encoding.ASCII.GetString(data, 0, recv);
        AddItem(stringData);
    }

    //------------------------------------------------------------------------------------------
    private delegate void stringDelegate(string s);
    private void AddItem(string s)
    {
        if (ListBoxEvents.InvokeRequired)
        {
            stringDelegate sd = new stringDelegate(AddItem);
            this.Invoke(sd, new object[] { s });
        }
        else
        {
            ListBoxEvents.Items.Add(s);
        }
    }

    //------------------------------------------------------------------------------------------
    private void BtnLogin_Click(object sender, EventArgs e)
    {
        clientSocket.Send(Encoding.ASCII.GetBytes("Action: Login\r\nUsername: admin\r\nSecret: lastsecret\r\nActionID: 1\r\n\r\n"));
    }

    //------------------------------------------------------------------------------------------


}
}

问题是当我连接到服务器时,我收到“Asterisk Call Manager/1.1”消息。连接到服务器后,我登录到服务器,但没有收到任何消息。我想从星号获取事件。使用网络Socket有问题吗?我是否应该使用特殊命令告诉星号我想接收事件。

4

1 回答 1

3

[编辑]

是的。所以这不是 AMI 配置的问题。

当您的连接完成时您启动一个 BeginReceive - 但是一旦您收到一次数据,您就不会启动一个新的 BeginReceive。

您需要在 OnDataReceive 中再次调用 BeginReceive,以便它再次尝试从套接字读取。

clientSocket.BeginReceive(data, 0, size, SocketFlags.None,
                          new AsyncCallback(OnDataReceive), clientSocket);

我将原始答案保留在下面,因为您仍然应该检查该信息。我将再次重申我的“仅供参考”——除非你这样做是出于教育目的,否则你应该真正使用现有的 AMI 库——特别是如果你不熟悉 TCP。

[原来的]

您要发送什么用户名和密码?您确定该帐户已正确配置为发送事件吗?

一旦你通过登录验证了你与 Asterisk 的连接,你应该开始自动接收事件。但是请记住,您需要适当的读取授权类权限才能接收某些类型的事件。从示例 manager.conf 中:

; Authorization for various classes
;
; Read authorization permits you to receive asynchronous events, in general.
; Write authorization permits you to send commands and get back responses.  The
; following classes exist:
;
; all       - All event classes below (including any we may have missed).
; system    - General information about the system and ability to run system
;             management commands, such as Shutdown, Restart, and Reload.
; call      - Information about channels and ability to set information in a
;             running channel.
; log       - Logging information.  Read-only. (Defined but not yet used.)
; verbose   - Verbose information.  Read-only. (Defined but not yet used.)
; agent     - Information about queues and agents and ability to add queue
;             members to a queue.
; user      - Permission to send and receive UserEvent.
; config    - Ability to read and write configuration files.
; command   - Permission to run CLI commands.  Write-only.
; dtmf      - Receive DTMF events.  Read-only.
; reporting - Ability to get information about the system.
; cdr       - Output of cdr_manager, if loaded.  Read-only.
; dialplan  - Receive NewExten and VarSet events.  Read-only.
; originate - Permission to originate new calls.  Write-only.
; agi       - Output AGI commands executed.  Input AGI command to execute.
; cc        - Call Completion events.  Read-only.
; aoc       - Permission to send Advice Of Charge messages and receive Advice
;           - Of Charge events.
; test      - Ability to read TestEvent notifications sent to the Asterisk Test
;             Suite.  Note that this is only enabled when the TEST_FRAMEWORK
;             compiler flag is defined.

因此,假设我想使用密码“bar”以用户“foo”身份进行身份验证,没有定义 ACL,并且我想接收所有事件。我也只想能够执行“系统”和“调用”类命令。我需要在 manager.conf 中将我的用户设置为:

[foo]
secret = bar
read = all
write = system,call

作为一个仅供参考 - 你可能在这里重新发明轮子。除非您将创建自己的 AMI 库作为练习,否则您可能需要考虑使用Asterisk .NET

于 2012-07-19T13:28:12.420 回答