【问题标题】:Sockets, Nullreference Exception套接字,空引用异常
【发布时间】:2017-04-10 18:40:04
【问题描述】:

我正在尝试将 Web 套接字与我的机器人一起使用来与服务器通信。但是在运行时它会抛出 System.NullReferenceException。我在不同线程的后台运行套接字,这样它就不会干扰机器人。

我正在使用 WebsocketSharp 库。

第一条消息很好,但第二条消息在 HumanCollaboratorDialog 类的下一行抛出异常。

await  context.PostAsync(e.Data);

我的套接字流类如下:

public static class SocketStream
{
    public static WebSocket ws;
    private static List<string> serverMsg = new List<string>();

    public static void initializeSocket()
    {

        ws = new WebSocket("ws://Some IP:8080/human-collaborator/data");
        Debug.WriteLine("****** INITIALIZED SOCKET (should happen only once) *****");
        Task.Run(() => startSocketStream());

    }

    private static void startSocketStream()
    {
        int attempts = 0;
        while (!ws.IsAlive)
        {
            try
            {
                attempts++;
                ws.Connect();
            }
            catch (WebSocketException)
            {

                Debug.WriteLine("Connection attempts: " + attempts.ToString());
            }

        }

        ws.OnOpen += (sender, args) =>
        {
            Debug.WriteLine("# SOCKET OPENED");

        };

        ws.OnError += (sender, args) =>
        {
            Debug.WriteLine("# SOME ERROR OCCURED");
        };

        ws.OnClose += (sender, args) =>
       {
           Debug.WriteLine("# SOCKET CLOSED");

        };
    }
}

我正在调用 Global.asx 中的 initializeSocket() 方法以在应用程序级别运行它

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);
        SocketStream.initializeSocket();

    }
}

我的 HumanCollaboratorDialog 类如下:

[Serializable]
public class HumanCollaboratorDialog : IDialog<object>
{

    public async Task StartAsync(IDialogContext context)
    {

        context.Wait(this.MessageReceivedAsync);

    }

    private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
    {

        var message = await result;

        SocketStream.ws.OnMessage += async (sender, e) =>
        {
            try
            {
                await  context.PostAsync(e.Data);
            }
            catch (HttpRequestException ex)
            {
                throw ex;
            }
        };

            Thread.Sleep(500);
            string output = message.Text;
            SocketStream.ws.Send(output);
            Thread.Sleep(500);

        context.Wait(MessageReceivedAsync);

    }
}

我的 MessagesController 有以下 POST 方法:

public virtual async Task<HttpResponseMessage> Post([FromBody]Activity activity)
    {
        if (activity.Type == ActivityTypes.Message)
        {
            await Conversation.SendAsync(activity, () => new HumanCollaboratorDialog());
        }
        else
        {
            HandleSystemMessage(activity);
        }
        var response = Request.CreateResponse(HttpStatusCode.OK);
        return response;
    }

e.Data 和 context 都不是空的。我认为问题出在套接字连接上,或者可能是我在 SocketStream 类中做错了什么。以下是图片

【问题讨论】:

  • 我不知道你为什么要在 Web API 中运行一个套接字...
  • @EzequielJadib 我想在后台连续运行套接字,这样如果服务器发生变化,它可以通知机器人。在这种情况下,更好的解决方案是什么?
  • 在旁注中,不要做catch(Exception ex){ throw ex; }It's evil
  • 那么在异常发生时什么是 null 呢?上下文? e 参数?
  • @EzequielJadib,没有一个。第一条消息很好,但之后它不起作用并引发异常。

标签: c# .net sockets botframework websocket-sharp


【解决方案1】:

您的机器人是一项网络服务。消息由客户端(网页、应用程序、另一个服务等)发送到服务,并在 MessagesController 的 Post 方法中接收。对于您要执行的操作,无需在服务器上使用套接字代码。 Web 套接字对于通过 Direct Line 连接从机器人接收客户端消息非常有用。


以下是使用 Bot Framework 的 Direct Line Client 并创建 Web 套接字连接的示例。请注意 Web 套接字是如何从对话的 StreamUrl 创建的:

DirectLineClientCredentials creds = new DirectLineClientCredentials(directLineSecret);
DirectLineClient directLineClient = new DirectLineClient(creds);
Conversation conversation = await directLineClient.Conversations.StartConversationAsync();

using (var webSocketClient = new WebSocket(conversation.StreamUrl))
{
    webSocketClient.OnMessage += WebSocketClient_OnMessage;
    webSocketClient.Connect();
    while (true)

    {
        string input = Console.ReadLine().Trim();

        if (input.ToLower() == "exit")
        {
            break;
        }
        else
        {
            if (input.Length > 0)
            {
                Activity userMessage = new Activity
                {
                    From = new ChannelAccount(fromUser),
                    Text = input,
                    Type = ActivityTypes.Message
                };

                await directLineClient.Conversations.PostActivityAsync(conversation.ConversationId, userMessage);
            }
        }
    }
}
private static void WebSocketClient_OnMessage(object sender, MessageEventArgs e)
{
    // avoid null reference exception when no data received
    if (string.IsNullOrWhiteSpace(e.Data))
    {
        return;
    }

    var activitySet = JsonConvert.DeserializeObject<ActivitySet>(e.Data);
    var activities = from x in activitySet.Activities
                        where x.From.Id == botId
                        select x;

    foreach (Activity activity in activities)
    {
        Console.WriteLine(activity.Text);
    }
}

这是来自一个控制台应用程序,该应用程序使用 Direct Line 与 Bot 通信,并在此处使用 Web 套接字侦听消息: https://github.com/Microsoft/BotBuilder-Samples/tree/master/CSharp/core-DirectLineWebSockets

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    • 2011-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多