2017-04-10 9 views
1

봇과 웹 소켓을 사용하여 서버와 통신하려고합니다. 그러나 런타임에 System.NullReferenceException을 throw합니다. 다른 스레드에서 백그라운드로 소켓을 실행하여 봇과 상호 작용하지 않도록합니다.소켓, Null 참조 예외

WebsocketSharp 라이브러리를 사용하고 있습니다.

첫 번째 메시지는 잘 전달되지만 두 번째 메시지에서는 HumanCollaboratorDialog 클래스의 다음 줄에서 예외가 발생합니다.

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"); 

     }; 
    } 
} 

내가 응용 프로그램 수준

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

    } 
} 

내 HumanCollaboratorDialog 클래스에서 실행하는 Global.asx에서 initializeSocket() 메서드를 호출 오전 :

await context.PostAsync(e.Data); 

내 소켓 스트림 클래스는 다음과 같습니다 다음과 같습니다 :

[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; 
    } 

Neithet e.Data을하거나 컨텍스트가 비어 있습니다. 문제는 소켓 연결로 생각하거나 SocketStream 클래스에서 뭔가 잘못하고 있습니다. 이미지가되어 다음

Exception-Image enter image description here

+0

웹 API에서 소켓을 실행하는 이유가 확실하지 않습니다 ... –

+0

@EzequielJadib 서버에서 무언가 변경되면 봇에 알릴 수 있도록 백그라운드에서 소켓을 계속 실행하고 싶습니다. 이 시나리오에서 더 나은 솔루션은 무엇입니까? –

+2

한 쪽에서'catch (Exception ex) {throw ex; }'. [악의] (http://stackoverflow.com/questions/881473/why-catch-and-rethrow-an-exception-in-c) – Default

답변

1

귀하의 로봇은 웹 서비스입니다. 메시지는 클라이언트 (웹 페이지, 응용 프로그램, 다른 서비스 등)에 의해 서비스로 보내지고 MessagesController의 Post 메서드에서 수신됩니다. 서버에서 소켓 코드를 수행 할 필요가 없습니다. 웹 소켓은 직접 회선 연결을 통해 클라이언트에서 봇의 메시지를 수신하는 데 유용합니다.


다음은 Bot Framework의 Direct Line Client를 사용하고 웹 소켓 연결을 만드는 예제입니다. 웹 소켓이 대화의 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); 
    } 
} 

이것은 봇와 통신하기 위해 직통 전화를 사용하는 콘솔 응용 프로그램이며, 여기에 웹 소켓을 사용하여 메시지를 수신 대기 : https://github.com/Microsoft/BotBuilder-Samples/tree/master/CSharp/core-DirectLineWebSockets