신입 개발자가 작성한 연구일지입니다. 이때 오해하고 있던 잘못된 정보가 포함되어 있습니다.
System.Net.Sockets.SocketException (54): Connection reset by peer
이 에러 해결한거 아니었어 ? 처리 저번에 했었는데 또 뜨네 왜 뜨는걸까
멀티스레드 환경에서 에러를 잡는 것은 너무 복잡해서 로그를 추가해도 타이밍이 맞이 않아 어느 시점에서 누구까지 연결을 하고 에러가 발생했는지 잘 모르겠다.
reset by peer 에러는 서버가 response 를 보내기 전에 연결을 끊어버리는 에러라고 한다.
서버가 감당하기에는 너무 큰 로드를 부하할 때 발생한다고 한다.
이런 에러는 클라이언트 잘못이 아니라니, 서버를 계속 확인해보아야겠다.
특이한 점은, 이러한 작업을 시간의 텀을 두고 하면 아무 에러가 나지 않는다는 점이다.
클라이언트가 500개가 동시에 연결하면 문제가 생기지만, 0.05 초의 딜레이를 두고 차례로 입장하면 문제가 생기지 않는다.
어디까지 되나 싶어서 2만개를 더 추가했는데, 10151개까지만 연결이 되고, 에러가 출력된다. (좋아 올 것이 왔다!)
위 문제는 나중에 해결하도록 하고, 우선 동시 연결시 에러가 발생하는 것부터 해결해 보겠다.
디버깅을 해 보니 "" 를 보내는 클라이언트가 있는 것을 발견했다.
"" 를 받으면 연결이 끊어지게 해 두었는데, 이것 때문에 계속 이웃친구가 초기화했다고 그러는 것 같다.
클라이언트가 어떤 데이터를 보냈는지부터 확인을 해 보아야 할 것 같다.
'이 클라이언트'를 특정하기 위해서 그동안 보류해왔던 소켓 Id 작업을 추가해야겠다.
아이디를 결정하는 타이밍을 잘 정해야 할것 같다. 아이디를 클라이언트가 정하면 여러 클라이언트는 서로의 아이디를 알지 못하니 중복된 Id를 사용하게 될 수 있을것 같다.
일반적으로 Id발급만이 주 목적이라면, 그저 연결이 들어왔을 때 Id 를 부여하면 되겠지만, 지금은 클라이언트가 서버에 연결을 시도할 때, 어떤 클라이언트가 문제를 일으키는지 찾아야 하므로 클라이언트가 처음 연결을 시도할 때에 이미 Id 가 있는 상태여야 한다.
ㄴ 혹시 소켓 별로 아이디를 가지고 있나 ? 싶지만 내 구글링 실력이 부족한 것인지 나는 찾지 못했다 ... 당연히 가지고있을것같은데
내가 설정한 구조는 아래와 같다.
클라이언트에서 0~999 번의 아이디를 가지고 서버에 접근하면,
서버가 "너 처음 왔구나?" 하며 새로 1000번 이상의 아이디를 발급해 준다.
아이디를 발급해주려고 하는데,
생각보다 아이디를 발급하는것도 문제가 많습니다.
아래 경우는 왜 에러가 뜨는 걸까요 ? ㅠㅠ
로그를 출력해 보니, 첫 for문은 순서가 잘 돌지만, for문이 다 돌아야지 CreateClient 가 실행되어, 어느샌가 모두가 500번 클라이언트가 되어있는 모습을 확인했습니다.
이유는 잘 모르겠지만 await 키워드를 추가하니 해결되었습니다.
아무래도 i 를 모두가 공유하던 모양입니다. 왜 공유했지?
잠시만....! 코드를 이렇게 바꾸니 갑자기 Perr 에러가 발생하지 않고 있습니다 ........................
아니이런 세상에 뒷걸음치다 쥐 잡은 격이네요
공식 문서에서 찾은 지식같이 멋들어진 자료로 문제를 해결한게 아니라 이렇게 원인을 찾다니 ... (다들 그러고 살죠?)
스스로에게 조금 실망했습니다만 어쨌든 힌트를 찾았으니 문제를 해결해보면 좋을것 같습니다!
await 를 사용하지 않으면 반복 변수 i 에 노란 밑줄로 이런 에러가 출력됩니다.
Capture Variable 이란 무엇일까요 ?
람다식을 사용할 때, 외부에서 가져온 변수가 있으면 해당 변수를 복사해서 가져오는데, 그렇게 복사된 변수를 Captured Variable 이라고 한다고 합니다.
참고: https://geukggom.tistory.com/240
[C#] 캡처(Capture feat. 람다식)
표현식 본문(Expresstion Lambda) : 본문의 코드를 한 줄로 단순화하여 쓴 경우 (input-parameters) => expression 문장 본문(Statement Lambda) : 중괄호를 포함한 경우 (input-parameters) => { } : 람다식으로 델리게이트
geukggom.tistory.com
위 블로그에서 보아하니 캡쳐한 변수를 저장할 클래스를 작성해야 하는데, 해당 클래스의 작성이 메인 스레드의 for문이 모두 종료된 후에 실행되어서 같은 값이 복사되었던 것 같습니다. C# 정말 어렵네요. 타이밍 맞추기
오늘의 일지 끝 !
목표
30000명이 동시에 접속할 수 있는 TCP 서버 만들기
30000명의 클라이언트는 전송 - 수신 - 전송 - 수신 을 반복한다.
30000명의 클라이언트를 켜 놓고, 다음날 서버가 에러 없이 살아 있는 것을 목표한다.
목표를 성취한 후에는 평균 응답 시간을 줄여보도록 하겠다.
프로젝트 Git Hub Repository 링크
https://github.com/MatorMirne/SocketCommunicate-TCP
'Side Project > 안양시장 프로젝트 - TCP 서버개발' 카테고리의 다른 글
[프로젝트 김필여 - 14일차] 대규모 동시접속 TCP C# 서버 제작기 (0) | 2023.11.07 |
---|---|
[프로젝트 김필여 - 13일차] 대규모 동시접속 TCP C# 서버 제작기 (2) | 2023.11.06 |
[프로젝트 김필여 - 11일차] 대규모 동시접속 TCP C# 서버 제작기 (1) | 2023.10.30 |
[프로젝트 김필여 - 10일차] 대규모 동시접속 TCP C# 서버 제작기 (0) | 2023.10.13 |
[프로젝트 김필여 - 9일차] 대규모 동시접속 TCP C# 서버 제작기 (0) | 2023.10.11 |