SignalR handshake was canceled 질문

안녕하세요.

ASP.NET Core Web API 서비스를
UseKestrel 통해 셀프 호스팅으로 사용하 고 있습니다. (IIS 사용 X)

Web API에 SignalR 서비스를 추가하기 위해서 다음과 같이 서비스를 등록하고
Hub구성을 하였는데요..

[Startup.cs]

services.AddSignalR(option =>
{
                option.HandshakeTimeout = new TimeSpan(0, 1, 0);
                option.KeepAliveInterval = new TimeSpan(0, 1, 0);
                option.EnableDetailedErrors = true;
});
app.UseEndpoints(endpoints =>
{
                endpoints.MapControllers();
                endpoints.MapHub<PlaceHub>("/placeHub");
);

위와 같이 설정 후 웹소켓 서버가 Open된 것을 확인 할 수 있습니다.

웹소켓 클라이언트는 일반 C# Console 환경에서 사용하기 위해
signalR 클라이언트가 아닌 System.Net.WebSockets 을 이용해서 직접
ASP.NET Core Web API 웹소켓 서버에 접속 시켰습니다.

참고 : aspnetcore/Program.cs at main · dotnet/aspnetcore (github.com)

웹서버에 접속 까지는 가능하나 Receiving에서 ReceiveAsync()호출을 하면
위에 서버에서 설정한 핸드쉐이크 타임아웃 시간 이후에

서버측으로 부터 handshake was canceled 오류가 메세지가 전달 됩니다.

  • 콘솔 클라이언트가 아닌 자바스크립트로는 정상 통신이 됩니다.,
  • wss 사용이 아닌 ws로 사용하고 있습니다.

혹시 해당 이슈에 대해 원인과 해결방법을 알고 계신분 계시면 답변 부탁드립니다.

혹시나 하여 Web API 서버측 Hub 코드도 올립니다.

public class PlaceHub : Hub
{
        public override Task OnConnectedAsync()
        {
            return Clients.All.SendAsync("ServerMsg", "Connected");
        }

        public override Task OnDisconnectedAsync(Exception exception)
        {
            return Clients.All.SendAsync("ServerMsg", "Disconnecte");
        }

        public Task SendToOthers(string senderID, string tickerCode, string ticker, double price, double units, double weight, string type, string kind)
        {
            return Clients.Others.SendAsync("Place", senderID, tickerCode, ticker, price, units, weight, type, kind);
        }
}
1개의 좋아요

SignalR을 안쓴지 좀되어서 잘못된 물음일 수 도 있는데,

SignalR.Client를 안쓴 이유가 Console 환경이라는게 이해가 되지 않고, WebSocket을 이용해 직접 SignalR 프로토콜을 구현하셨다는 말씀인가요?

지금 재현해보지 않았기 때문에 잘못된 정보일 수도 있지만 제 경험으로는 Console에서도 SignalR.Client를 이용해 WebSocket를 썼던 기억입니다.

2개의 좋아요

콘솔 환경이라서 SignalR.Client을 안쓴건 아니고

이전에 간단하게 System.Net.WebSockets 클래스를 사용해서 웹소켓 클라이언트로 사용했던 코드가 있어

재사용 하려고 했던 거였어요

지금 생각해보니

시그널R은 자체적인 프로토콜로 핸드쉐이크 과정이 들어가야 정상 통신이 되는 것 같습니다.
이와 같은 행위를 내부적으로 자체 구현되어 있는것이
SignalR.Client 인거 같구요

이 부분을 제가 생각하지 못하고 단순히 서버에 접속해서 메세지만 전송/수신 만 하면 되겠구나 하고 착각 했던 것 같습니다.

말씀해주신 것 처럼 SignalR.Client로 대체 하던가

시그널R을 쓰지 않고 직접 웹소켓 서버를 Open해서 사용하는것이 좋을 것 같습니다.
ASP.NET Core에서 WebSocket 지원 | Microsoft Docs

답변 감사드립니다.

2개의 좋아요

너무 예전 글이긴 한데…

말씀하신 것 처럼 SignalR 서버에 직접 WebSocket으로 붙기 위해서는
WebSocket 연결 이후에 어떤 프로토콜로 통신을 할 것인지 지정해주셔야 합니다.

{“protocol”:“json”,“version”:1}

를 보내주시면 SignalR 연결이 완료되며 그 다음부터 하트비트를 받으실 수 있을 겁니다.

1개의 좋아요