묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
TCP/IP vs UDP , 멀티 스레드에서의 병목 현상에 대한 질문이 있습니다!
안녕하세요! 항상 좋은 강의 감사합니다.강의를 듣다가 궁금한 점이 있어서 질문을 드립니다!Q1.TCP/IP 의 경우 서버 입장에서 사용자가 연결되어 있다는 착각에 빠지지 말라고 알려주셨습니다. 하트비트를 어차피 보내줄 것이라면 UDP 로 설계를 해도 상관없는 건가요?연결을 신뢰할 수 없음에도 TCP/IP를 사용하는 이유가 궁금합니다.Q2.멀티 스레드 환경에서 GQCS를 할 경우, 스레드들이 공유하는 큐에 락을 걸어서 적용해봤습니다. 하지만 이 경우 큐에 접근할 때 병목 현상이 우려됩니다. 해당 세션이 특정 스레드에서만 처리되도록 하여 락을 없애는 것과 락을 걸고 여러 스레드에서 접근할 수 있도록 하는 것 중 어느 것을 선호하시나요? Q3. 어쩌면 Q2와 거의 같은 질문일 수도 있겠습니다. 멀티-스레드 환경에서 락 에 대한 대안이 있나요?
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
메모리 관련 문제로 질문드립니다.
IOCP 서버를 클래스로 만들어 보려고 하고 있습니다.Thread 생성까지 오류 없이 되다가 Client가 접속되면 문제가 발생합니다.디버깅 결과 client_list는 메모리 할당이 되었으며 clientSocket이 정상적으로 도착한 상태입니다.하지만 위의 사진과 같이 push_back을 하려고하면 오류가 발생합니다. 해당 쓰레드의 함수는 class 내부의 메소드로 정의 및 구현되어있습니다.socket_list와 socket_cs를 class 외부에서 정의했을 때에도 같은 현상이 발생합니다.참고할만한 레퍼런스나 해결법이 있을까요?
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
테스트 환경 질문드립니다!
안녕하세요!아파트에 거주하고 있습니다.저희 세대로 들어오는 네트워크 신호를 담당하는 기기가 신발장 안쪽에 있고 굉장히 여러 케이블이 꽂혀 있습니다. 가끔씩 집 컴퓨터 인터넷이 안 될 때가 있는데 그 기기를 리부팅하곤 합니다. 각 방의 벽에 랜선 케이블을 꽂을 수 있게 되어 있습니다.PC는 전부 벽에 있는 랜선 포트에 랜선 케이블을 꽂습니다.거실에 있는 공유기는 거실 벽면에 있는 랜선 포트와 연결되어 있습니다.제가 파악한 걸 말씀드려보겠습니다.1. 세대로 들어오는 네트워크 신호는 신발장 안쪽에 있는 설비를 통해 집의 각 벽면의 랜선 포트로 전달한다공유기가 내보내는 신호 역시 벽면의 랜선 포트로 전달된 신호를 받아서 동작한다. PC가 랜선으로 수신하는 네트워크 신호와 공유기가 뿌리는 무선 신호는 같은 망에 속한다 이 상황에서, PC는 랜선으로 연결하고 노트북은 공유기에 연결하는 것이, 강의에서 말씀하신 하나의 공유기에 랜선으로 두 PC를 연결하는 것과 동일한 것처럼 느껴집니다. 맞을까요?이게 맞다면 영상에서 말씀하신 클라이언트 PC의 케이블 연결 해제가 노트북의 와이파이 연결 해제와 동일한 것 아닌가 하는 생각이 들었습니다.
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
ThreadAcceptLoop 의 우아한(?) 종료에 대해 질문드립니다.
안녕하십니까, TCP/IP, IOCP 개념을 배우는데 강사님의 강의가 큰 도움이 되었습니다. 다름이 아니라, IOCP 코드를 C++ Class 로 작성중에 소멸자에서 리소스들을 해제 하려고 작성 중에 있는데 ThreadAcceptLoop 스레드를 우아하게 종료하기 위한 방법이 있는지 궁금하여 질문을 하나 드려봅니다. g_hSocket : Server Listen SocketDWORD WINAPI ThreadAcceptLoop(LPVOID pParam)while ((hClient = ::accept(g_hSocket, &ClientAddr, &nAddrSize)) != INVALID_SOCKET){ // Do Something...} 보시다싶이 ThreadAcceptLoop 함수 내부에서 ::accept() 를 처리해주고 있고 accept 에 들어가는 순간 Blocking 이 되어버립니다. 저는 스레드의 완전 종료를 위해 accept 함수를 빠져나가기 위한 방법을 찾아보니 g_hSocket = NULL 또는 INVALID_SOCKET 을 할당 해주는것 말고는 Accept 함수를 빠져나갈 수 있는 방법이 없는 것 처럼 보이더라구요. 하지만 이런식으로 NULL 할당하여 accept 를 빠져나가도록 하고 WSAGetLastError 를 호출해보면 "WSACancelBlockingCall를 호출하여 차단 작업이 중단되었습니다." 라는 에러를 확인할 수 있었습니다. g_hSocket = NULL 호출 후 해당 오류를 무시해도 지나가도 되는 코드인지, 아니면 accept Blocking 상태를 빠져나가기 위한 "우아한 방법" 이 있는지 궁금합니다. 현재 작성한 코드 순서는 아래와 같습니다. 스레드는 _beginthreadex 로 호출해서 핸들을 가지고 있습니다. ::shutdown(g_hSocket, SD_BOTH); if (g_hSocket!= INVALID_SOCKET) { ::closesocket(g_hSocket); g_hSocket= INVALID_SOCKET; // 이 시점에 accept blocking 이 풀린다! } // Accept Thread 종료를 대기하자 WaitForSingleObject(IOCPAcceptThreadHandle._threadHandle, INFINITE); CloseHandle(IOCPAcceptThreadHandle._threadHandle); 감사합니다.
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
하트비트 시 서버에서의 연결 종료
안녕하세요 좋은 강의감사합니다.소켓연결 종료 시 클라이언트가 먼저 끊게 유도하라고 하셨는데만약 서버에서 주기적으로 N초마다 하트비트를 보내고 클라이언트에서 응답이 없을 경우 서버에서 연결을 종료해야 하지 않나요??? 혹시 이 상황에선 보편적으로 어떻게 하는지 궁금합니다.
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
강사님 질문 드립니다.
제공해주신 멀티스레드 소켓 프로그램에 LPVOID 형을 가지는 매개변수에 일반 변수를 지정하셨는데 LPVOID 는 포인터와 일반변수 모두 가능 한 건지요?주신 프로그램을 보면 SOCKET hClient = 0; // SOCKET 형 변수를 선언 hThread = ::CreateThread( NULL, 0,ThreadFunction, (LPVOID)hClient, // 주소가 아닌 값을 지정0, &dwThreadID); 만약 가능하다면 내부적으로 어떻게 가능한지 확인 부탁드려봅니다. 늘 좋은 강의 감사합니다. 강사님
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
소켓 입/출력 설계 정리
안녕하세요. 선생님!프로토콜 설계관련 큰 흐름을 정리 해보고 있습니다. 주요 포인트는 서버에서 관리(TCP로 연결된 소켓)하고있는 클라이언트들의요청을 어떤 구조로 처리할지?총 3가지 형태로 정리되었습니다.1. 블록강의 : 멀티쓰레드 채팅서버 구조(블록 소켓)2. 논블록강의에는 없지만, 하나의 쓰레드에서 여러 논블록 소켓들 돌며 Receive를 확인하는 구조3. 비동기강의 : IOCP기반 채팅서버(클라이언트 수신처리를 OS에 등록하여 콜백 받는구조)궁금한 부분은다양한 프로토콜 설계를 "큰 주제"로 나눈다면블록/ 논블록/ 비동기 이렇게 3가지 형태로 나누어도 크게 문제가 없을 지 궁금합니다.
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
멀티스레드 기반 서버 관련 질문..!
안녕하세요 널널한 개발자님, 덕분에 수업 잘 듣고 있습니다. :)현재 멀티스레드 채팅 클라이언트, 서버 기반 수업을 듣고 해당 구조를 변경해서 작은 빙고 게임을 만들어 보고 있습니다. 해당 게임의 큰 틀을 짧게 요약하자면클라 - 연결 요청 -> 서버 - 확인 후 번호 전달3번째 클라 - 연결 요청 -> 서버 - 확인 후 모든 클라에게 보드판 및 게임 순서를 전달클라 - 게임 순서에 맞는 클라가 빙고판 번호를 입력 -> 서버 - 확인 후 보드판 정보 업데이트 및 다시 모든 클라에게 전달 .... 이런 식으로 게임이 진행됩니다, 2번 동작까지는 잘 진행이 되는데 '문제'는 3번 순서에서 클라가 빙고판 번호를 입력했을 때 서버로 전달이 되지 않아 보드판 정보 업데이트가 되지 않고 있습니다..클라에서 서버로 메시지를 전달할 때 버퍼의 내용은 문제가 없었는데, 이상하게 서버로 전달만 하면 빈 버퍼가 전달이 되네요..혹시나 서버 버퍼에서 소켓 입출력 버퍼가 Nagle 알고리즘에 의해 서버 프로세스로 전달이 되지 않은 건가 싶어서 소켓의 TCP_NODELAY 옵션도 설정해보았는데, 해결이 되지 않았습니다. whireShark를 이용해서 확인을 하고 있긴 한데, 아직 제 수준에서는 내용을 파악하기 힘드네요.. 널널한 개발자님이라면 이런 상황에서 어떻게 문제를 해결하실 건가요??
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
TIME_WAIT 관련 문의드립니다.
안녕하세요."에코 클라이언트/서버 테스트 및 Wireshark로 확인" 강의에서 제공해 주신 예제 프로그램을 실행해 보다가 TIME_WAIT 관련하여 몇 가지 궁금한 것이 있어 문의드립니다. (1) Client 쪽에서 여러 번 접속을 하고 종료를 할 경우, 아래 이미지처럼 생성된 Port 별로 TIME_WAIT 상태로 있고, 어느 정도 시간이 지나면 모두 없어지던데 이건 CLOSED 상태로 된 것으로 보면 되는 건가요? (2) 제공해 주신 수업 자료에서의 TCP 상태 전이도에서 TIME_WAIT에서 CLOSED 상태로 가는 화살표에 있는 Timeout은 운영체제에서 관리하는 건가요? 아니면 예제 프로그램에서 사용된 Socket 관련 함수에서 제어가 되는 건가요? 감사합니다.
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
강사님 강의자료 인쇄용으로 부탁드립니다.
강사님 강의자료 인쇄용으로 부탁드립니다!
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
bind 함수 관련 궁금증
안녕하세요.강의 수강 중 궁금한 점이 있어서 질문드립니다! TCP 에코 서비스 전체 흐름 수업 중에 서버에서 bind 함수가 필요한 이유를 듣고 문득 궁금해졌습니다. bind 함수가 소켓이라는 추상적인 객체에 TCP 프로토콜을 붙여서 구체화를 시켜주는 함수로 이해했습니다. 그렇다면, 클라이언트도 bind라는 함수가 필요하지 않나 생각이 들었습니다.서버와 통신을 한다면 결국 클라이언트도 IP와 port 정보가 필요하다고 생각하는데 왜 클라이언트는 따로 bind 함수를 호출하지 않는지 궁금합니다!
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
스마트포인터 사용여부 및 가능성
안녕하십니까 선생님. 훌륭한 강좌 잘 들었습니다. 비동기 콜백 부분에서 버퍼와 오버랩드구조체를 동적할당하고 콜백함수에 주소를 주고 다쓴후에 딜리트를 하는 방식을 유니크나 쉐어드포인터 같은 스마트포인터로 대체가 가능할까요?특히 쉐어드는 잘만쓰면 정말유용할것 같긴한데 서버개발할때 레퍼런스 카운팅에 대한 아토믹연산의 오버헤드에 대해 감당할만하다고 생각하시는지요?또한 스마트포인터를 쓰고싶어도 콜백함수로 등록가능한 함수형태가 정해져있어서 스마트포인터 그 자체를 넘겨줄순없는것같은데혹시 방법이있다면 조언좀 부탁드리겠습니다.감사합니다.
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
CreateThread()를 사용하여 클래스의 멤버함수를 실행할 수 는 없나요?
수업을 듣고 따로 서버코드를 만들어 보려는 중 잘 안돼서 질문 드립니다.class Server { private: SOCKET listenSocket; std::list<SOCKET> listClients; SOCKADDR_IN serverAddr; public: Server(); Server(USHORT port, IN_ADDR addr); void Bind(); void Listen(); DWORD WINAPI ThreadAcceptLoop(LPVOID pParam); void AcceptClient(); void ReleaseServer(); ~Server(); };main 함수에서 Server클래스의 객체를 만들어서 서버를 실행하는 로직을 구현하고 있습니다.Server클래스의 AccpetClient()에서 CraeteThread()를 사용하여 ThreadAcceptLoop()를 실행하는 쓰레드를 만들어서 클라이언트의 요청을 Accept()하려고 합니다.하지만 CreateThread()함수에서 E0167 DWORD (__stdcall Server::*)(LPVOID pParam) 형식의 인수가 LPTHREAD_START_ROUTINE 형식의 매개 변수와 호환되지 않습니다. 라는 오류와 함께 컴파일이 되지 않습니다.찾아본 결과 함수를 static으로 선언하던지 전역함수를 사용하라고 합니다. 제가 하려던것처럼 클래스의 멤버함수를 실행할 수는 없나요??
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
0강 Win32 작업자 스레드 동기화 9:33~
DWORD WINAPI ThreadFunction(LPVOID pParam) { puts("*** Begin Thread ****"); for (int i = 0; i < 5; ++i) { printf("[Worker thread] %d\n", i); ::Sleep(1); } //스레드가 끝나기 전에 이벤트를 세트한다. puts("종료 이벤트 세트 전"); //이 함수를 호출하면 _tmain() 함수의 //WaitForSingleObject() 함수가 반환한다! ::SetEvent((HANDLE)pParam); puts("종료 이벤트 세트 후"); puts("**** End Thread ****"); return 0; }for (int i = 0; i < 5; i++) { printf("[Main thread] %d\n", i); //i값이 3이면 이벤트가 세트되기를 무한정 기다린다! if (i == 3 && ::WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0) { puts("종료 이벤트를 감지했습니다!"); ::CloseHandle(hEvent); hEvent = NULL; } }3일 때 worker 스레드가 실행되는 조건문 하에서Main함수가 2일 때도 반환되고 0일 때도 반환됩니다.말씀해주신대로 3일 때 반환되는 경우도 있지만 보장되지 않고 빈번하게 아래 케이스처럼 반환되는 경우가 있습니다.(디버그 모드, 릴리즈 모드 모두에서)이는 무슨 이유 때문인지 궁금합니다. case1[Main thread] 0[Main thread] 1[Main thread] 2*** Begin Thread ****[Worker thread] 0[Main thread] 3[Worker thread] 1[Worker thread] 2[Worker thread] 3[Worker thread] 4종료 이벤트 세트 전종료 이벤트 세트 후**** End Thread ****종료 이벤트를 감지했습니다![Main thread] 4 case2[Main thread] 0*** Begin Thread ****[Main thread] 1[Main thread] 2[Worker thread] 0[Main thread] 3[Worker thread] 1[Worker thread] 2[Worker thread] 3[Worker thread] 4종료 이벤트 세트 전종료 이벤트 세트 후**** End Thread ****종료 이벤트를 감지했습니다![Main thread] 4
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
이벤트 기반 비동기 파일 입/출력 (예제 포함)
안녕하세요 선생님 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; 이런식으로 마지막에 비교할때 쓰이는건가요?
-
미해결Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
파일 송수신 테스트
안녕하세요 선생님 질문이 있습니다. 4:17에서client에서 File List를 요구한 다음 server에서 보내는 패킷에서 사이즈가 796인게 MYCMD cmd; cmd.nCode = CMD_SND_FILELIST; cmd.nSize = sizeof(g_flist)+sizeof(g_aFInfo);MYCMD의 사이즈가 맞나요....?
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
파일 송신 서버 제작 (예제 포함)
안녕하세요 선생님 질문이 있습니다. 파일 송신을 할때 server가 100을 보내도 client가 빠르게 처리 못하는 경우 50정도 만간다는 예시에서나머지 50은 tcp buffer(OS쪽) 에 남겨져 있다고 봐야하는건가요? 어디서 머무르고 있는것인가요?
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
iocp 모델 설명과정에서 궁금한 부분이 있습니다.
강의 중 os가 vms 메모리에 lock을 걸어 커널에서 다루는 것이다라고 말씀하신 이후 "유저 모드 어플리케이션을 논 페이즈드 풀 메모리로 바꾸고... " 라는 식으로 표현하신 부분이 있는데 이 부분이 잘 이해되지 않습니다. (11분 10초)이 부분은 유저 모드의 메모리 영역을 커널과 공유하여 불필요한 메모리 복사를 방지한다. 라고 이해하면 될까요?
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
프로토콜이 없는 파일 송신, 수신 예제에서 같은 오류가 발생하고 있습니다.
FileSenderCRLFileReceiver 수업자료에서 이런 오류가 발생 합니다.별도로 수정한 부분은 없습니다..
-
해결됨Windows 소켓 프로그래밍 입문에서 고성능 서버까지!
recv() 함수가 아무 응답도 보내지 않는 이유는 무엇인가요?
break point를 통해 echo server 과정을 조정하던 중 send()를 보낼 때 ack 응답이 돌아온다는 것을 알게되었습니다.저는 recv()로 데이터를 받아 ack 응답을 보내는 줄만 알았는데 아니였더군요...recv()로 응답하지 않는다면 데이터가 제대로 전송되어 버퍼에 저장되었음을 알 수 없는 것 아닌가요?send()에서만 응답 받았음을 알리는 이유가 궁금합니다.