안녕하세요 선생님 DWORD dwRead; OVERLAPPED aOl[3] = { 0 }; HANDLE aEvt[3] = { 0 }; //세 번의 비동기 쓰기 완료를 확인하기 위한 이벤트 객체를 생성한다. for (int i = 0; i < 3; ++i) { aEvt[i] = ::CreateEvent(NULL, FALSE, FALSE, NULL); aOl[i].hEvent = aEvt[i]; } //비동기 쓰기가 시작될 지점을 기술한다. //두 번째 쓰기는 세 번째 쓰기보다 나중에 이루어질 가능성이 높다. aOl[0].Offset = 0; //파일의 시작. aOl[1].Offset = 1024 * 1024 * 128; //5MB aOl[2].Offset = 16; //16바이트 //세 번의 비동기 쓰기를 순차적으로 수행한다. for (int i = 0; i < 3; ++i) { printf("%d번째 중첩된 쓰기 시도.\n", i); ::WriteFile(hFile, "0123456789", 10, &dwRead, &aOl[i]); //정상적인 경우 쓰기 시도는 지연(보류)된다! if (::GetLastError() != ERROR_IO_PENDING) exit(0); } 여기서 dwRead가 얼마나 쓰였는지 확인하는 바이트수를 나타낸다고 하는데 만약 쓰고 싶다면 //세 번의 비동기 쓰기가 완료되기를 대기한다. DWORD dwResult = 0; for (int i = 0; i < 3; ++i) { dwResult = ::WaitForMultipleObjects(3, aEvt, FALSE, INFINITE); printf("-> %d번째 쓰기 완료.\n", dwResult - WAIT_OBJECT_0); } sizeof("0123456789") == dwRead; 이런식으로 마지막에 비교할때 쓰이는건가요?
안녕하세요. 저는 백엔드 개발을 하고 있는 2년차 꼬꼬마 개발자입니다. 강의를 듣던중 궁금증이 있습니다. 제가 진행하는 프로젝트의 경우 AWS 환경에서 백엔드를 개발하다보니 제공되는 모니터링 서비스?들이 있는데, 그럼에도 별도의 APM같은 것들이 필요한 경우는 어떤 경우가 있을까요? (예를 들어 더 디테일한 모니터링이 필요한 경우라던지?) 제 짧은 경력과 식견으로는 모르겠어서 질문드립니다! 아 다음 강의에서 설명이 나오는군요! 감사합니다. 😂 온프레미스 환경에서 클라우드로 전환 시 고려사항은 무엇일까?
강의 중 os가 vms 메모리에 lock을 걸어 커널에서 다루는 것이다라고 말씀하신 이후 "유저 모드 어플리케이션을 논 페이즈드 풀 메모리로 바꾸고... " 라는 식으로 표현하신 부분이 있는데 이 부분이 잘 이해되지 않습니다. (11분 10초) 이 부분은 유저 모드의 메모리 영역을 커널과 공유하여 불필요한 메모리 복사를 방지한다. 라고 이해하면 될까요?
break point를 통해 echo server 과정을 조정하던 중 send()를 보낼 때 ack 응답이 돌아온다는 것을 알게되었습니다. 저는 recv()로 데이터를 받아 ack 응답을 보내는 줄만 알았는데 아니였더군요... recv()로 응답하지 않는다면 데이터가 제대로 전송되어 버퍼에 저장되었음을 알 수 없는 것 아닌가요? send()에서만 응답 받았음을 알리는 이유가 궁금합니다.
char buf[] = "data"; int sendSize = 0; int total = 0; while ((sendSize = send(socket, buf + total, sizeof(buf) - total, 0) > 0 && total < sizeof(buf)) { total += sendSize; } 데이터를 송수신할 때 송수신 함수는 주고받고 싶은 만큼의 데이터가 모두 전달되지 않더라도 완료될 수 있으니까 데이터를 송수신할 때는 한 번의 함수호출이 아닌 위와 같이 여러 번의 함수호출로 완전한 데이터 송수신을 하는 게 맞나요?? (코드는 송신할때의 상황이지만 수신도 서로 약속한 길이의 데이터를 주고받을 때 마찬가지인지 궁금합니다.)
강사님. 항상 강의 잘 보고 있습니다. 궁금한게 있어서 질문 드립니다. 제가 이해하기론 클라이언트가 하나 연결될 때마다 서버는 새로운 소켓을 만들고 거기에 클라이언트를 연결한다?로 이해하고 있는데요. 만약 제가 이해한 것이 맞다면 새로 만들어진 소켓에 새 포트번호가 매핑되서 클라이언트랑 통신을 해야할 것 같은데 wireshark로 확인해보면 25000로 클라이언트와 통신을 하고 있어서요. 제가 놓친 것이 무엇인가요?
클라이언트가 만약 소켓 연결을 정상 종료하지 않고 프로그램을 끄게 되는 경우 예컨데 정전으로 인해 클라이언트 PC가 종료됐다면 서버는 알턱이 없으니 결국 TimeOut을 체크해서 서버가 연결을 종료해야할 것 같은데 맞을까요? 제 생각엔 위와 같은 흐름으로 진행되고 다른 방법은 떠오르지 않는데 혹시 대응할 수 있는 방법이 있을까요?
채팅 서버 코드 상에서 쓰레드를 생성한 직후 바로 CloseHandle함수를 호출하여 쓰레드 핸들을 해제해주는 부분이 있는데 쓰레드의 동작이 완료되기 전에 CloseHandle을 해줘도 문제가 없나요?? 리스닝 소켓과 accept함수로 생성된 소켓의 포트 번호가 25000으로 netstat와 wireshark 상으로 보면 동일하게 나오는데 여러 개의 소켓이 하나의 포트 번호를 공유할 수 있나요?? 아니면 netstat와 wireshark의 편의 기능인가요?? accept하면 랜덤한 포트번호를 할당받아서 소켓에 부여한다고 알고 있어서 질문드립니다 ㅠ 리스닝 소켓도 버퍼가 있나요?? shutdown(hSocket, SD_BOTH);로 리스닝 소켓을 shutdown해주고 나서 accept를 해봤는데 클라이언트의 접속이 잘 되더군요. 리스닝 소켓의 shutdown은 아무런 효과가 없는 건가요?? 클라이언트와 연결돼있는 상태에서 closesocket(hSocket);을 해서 리스닝 소켓을 해제해봤더니 서버에 연결돼있는 모든 클라이언트에게 RST가 보내졌습니다. 그럼 서버가 종료될 때 클라이언트 연결을 끊으려고 모든 클라이언트 소켓들을 순회하면서 closesocket을 해주는 대신 리스닝 소켓하나만 closesocket을 해주는 방식을 써도 될까요??
1. send()함수는 패킷을 보내는 함수가 아니라 소켓의 출력 버퍼에 데이터를 쓰는 것이고, recv()함수는 소켓의 입력버퍼에서 데이터를 읽어들이는 거라고 보면 될까요?? 데이터를 모아서 한번에 패킷을 보내는 것이 패킷의 갯수를 줄여서 성능 상의 이점이 있다는 건 알겠지만 데이터를 받을 때도 입력 버퍼에서 모아놓았다가 한번에 읽어들이는 것이 좋다는 것은 잘 모르겠네요...ㅠㅠ 데이터를 받을 때 패킷을 보낼 때와 마찬가지로 일정 시간 대기해서 데이터가 쌓이도록 한 다음 읽어들인다는 건가요??
먼저 좋은 강의 감사드립니다. IOCP를 사용 시 채팅서버에서 수신의 경우는 WSARecv를 사용하였으나, 송신은 일반 send 함수를 사용하고 있습니다. 송신의 경우 WSASend를 사용하는 것이 send를 사용하는것 대비 장점이 없는 것인지요? WSASend 사용 관련하여 해당 함수를 사용해야 하는 상황에 대해 설명 부탁드립니다. 추가로 IOCP의 thread (GQCS)에서 처리하는 일이 시간이 소요되는 처리를 해야 하는 시나리오 (파일 송신 등)에서, 사용자 수가 증가하는 경우 할당할 수 있는 thread가 없어, 동시 접속이 늘어나는 경우 문제가 발생할 수 있을 것으로 판단됩니다. 이런 경우 어떻게 설계를 하는 것이 타당한지 의견을 구하고자 합니다. 감사합니다.
안녕하세요 IOCP 관련 자료를 찾아보던 중 WSARecv/WSASend 할 때 넣어주는 WSAOVERLAPPED 구조체를 상속한 사용자 구조체를 넘겨주는 경우를 봤습니다. 이렇게도 사용이 가능하다면 WSAOVERLAPPED 를 상속받았으니 호환 될 것이고 추가적인 데이터도 담을 수 있어 도움이 되겠다는 생각입니다. 하나 궁금한 것이 있는데요 IOCP를 이용해서 넘긴 WSABUFF의 메모리영역은 커널에 의해 보호 받는다고 알고 있습니다. 마찬가지로 WSAOVERLAPPED 구조체도 커널에 의해 메모리 관리가 되는지 만약 관리가 된다면 상속을 통해 추가적으로 들어가는 정보도 관리에 포함이 되는지 궁금합니다 감사합니다~