SignalR

web socket

소켓 프로그램처럼 한번 연결하고 서버와 연결된 커넥션으로 데이터를 주고 받을수 있음.

연결이 끊겻을때 다시 재접속 하게 하는 방법

var connection = new HubConnectionBuilder()
              .WithUrl("https://localhost:7001/chathub")
              .WithAutomaticReconnect() //이부분을 넣어주면 자동으로 재접속을 시도해서 연결한다.
              .Build();

초기 연결 재시도

위처럼 하면 연결이 되있다가 끊기면 다시 연결을 해주지만 처음부터 연결이 안되는경우는 재시도를 하지 않는다.

public async Task<bool> ConnectWithRetryAsync(HubConnection connection, CancellationToken token)
{
  // Keep trying to until we can start or the token is canceled.
  while (true)
  {
    try
    {
      await connection.StartAsync(token);
      _logger.LogInformation("Worker connected");
      return true;
    }
    catch when (token.IsCancellationRequested)
    {
      return false;
    }
    catch
    {
      // Failed to connect, trying again in 5000 ms.
      _logger.LogInformation("first connect fail. try 5 sec lator");
      await Task.Delay(5000);
    }
  }
}

이함수를 호출해주면 된다.

연결이 끊기거나 연결될때 이벤트 발생

//auto reconnect event 등록
connection.Reconnecting += error =>
{
  _logger.LogInformation("signalr reconnection : {error}", error);
  //여기서 필요한거 처리
  return Task.CompletedTask;
};

//disconnect event 등록
connection.Closed += error =>
{
  _logger.LogInformation("signal disconnected");
  //여기서 필요한거 처리
  return Task.CompletedTask;
};

수동으로 재연결 구현

connection.Closed += async (error) =>
{
    await Task.Delay(new Random().Next(0,5) * 1000);
    await connection.StartAsync();
};

그냥 이벤트 잡아서 기다렷다가 재시도 하면된다.

클라이언트에서 서버 함수를 실행하는 법

SendMessage : 함수명

함수명 다음에 아규먼트를 쭉 적어주면된다. 컴마로 구분하면서 적어주자.

await connection.InvokeAsync("SendMessage", "aaa", "bbb");
await connection.SendAsync("SendMessage", "aaa", "bbb");

실제 서버코드는 다음과 같다.

public class ChatHub : Hub
{
    public Task SendMessage(string user, string message)
    {
      Console.WriteLine("RUN");
    }
}

InvokeAsync : 메세지가 서버로 전송될때 서버메소드가 완료될때 Task반환. await를 쓰면 서버 내용을 기다리고 try catch도 됩니다.

SendAsync : 메세지가 서버로 전송될때 완료되는 task 반환. 서버메소드가 완료될때가지 기다리지 않아서 반환값이 제동되지 않음. await try catch 사용가능

서버에서 클라이언트 함수를 실행하는 법

connection.On 에 등록을 해두고 서버에서 호출하면된다.

클라이언트에서 method를 정의하는데 connection.On을 사용해서 만들어야한다. building 다음에 넣고 start connection앞에 넣어야한다. (Define methods the hub calls using connection.On after building, but before starting the connection.)

connection.On<string, string>("ReceiveMessage", (user, message) =>
{
  Console.WriteLine("request from server {user} {message}",user,message);
});

서버에서는 SendAsync 를 통해서 호출하면된다. 함수명이 첫번째 아규먼트 나머지는 아규먼트들

await Clients.All.SendAsync("ReceiveMessage", user,message);

클라이언트에서 서버함수실행후 그 결과를 받아서 뭔가를 처리해야하는경우

리턴값을 받는 예제를 못 찾겟다. 조금 확인해본결과 클라이언트는 서버 함수를 실행하고 서버 함수에서 모든 처리를 다하고 마지막에 클라언트에 함수를 호출해서 처리 내용을 아규먼트로 넘겨준다.

이렇게 하면 된다.

정리하면 클라이언트는 서버에서 결과값을 보내올 listener를 등록하고 난후 서버에 메세지를 보내면 끝

connection.On<string>("ReceiveMessage", (message) =>
{
  Console.WriteLine("request from server {message}",message);
});

await connection.SendAsync("SendMessage", "aaa", "bbb");

이러면 서버에 sendmessage함수가 실행될것인데 그 함수 안에서 다시 클라이언트의 listener를 실행

public Task SendMessage(string message)
{
  Console.WriteLine("Received Message");
  //처리
  var result = message + "!";
  await Clients.All.SendAsync("ReceivedMessage",result);
}

이러면 result를 클라에 보내준다.

try catch

try
{
  await connection.InvokeAsync("SendMessage",aaa, bbb);
}
catch (Exception ex)
{
  Console.WriteLine(ex.Message);
}
teamsmiley's profile image

teamsmiley

2021-02-19 00:00

Read more posts by this author