티스토리 뷰
프로그램이 수행해야 할 일
서버
클라이언트로부터 메세지를 수신해서 다른 클라이언트들에게 뿌려주는 단순한 echo 기능을 수행한다.
클라이언트
콘솔 화면에서 메세지를 입력받아서 서버로 송신하며, 동시에 서버에서 수신받은 메세지를 화면에 출력한다.
서버
리눅스에도 있는 select를 사용해서 각 소켓의 메세지를 수신하고 송신할 수 있지만 winsock에서는 더 사용하기 편하고 강력한 기능을 제공하는 WSAEventSelect를 사용하기로 한다.
클라이언트
서버에서 WSAEventSelect를 사용하여 멀티플렉싱을 구현하였기 때문에 클라이언트에서도 해당 함수를 사용해서 stdin과 소켓의 멀티플렉싱을 구현하려 했으나 windows는 socket과 file을 다르게 관리하기 때문에 위 함수를 사용할 수 없었다.
아래는 멀티쓰레드로 문제를 해결하기까지의 과정이다.
결과적으로 너무 간단하게 해결되었지만 그동안 고생한게 아까우니 정리해보자.
원하는 결과
WSAWaitForMultipleEvent()가 stdin에서 발생하는 이벤트를 감지하는 것
정확히는 문자를 입력하고 enter를 입력했을 때 발생하는 이벤트를 감지해서 그동안 입력한 데이터를 읽어서 소켓으로 전송하는 것
시도해 본 방법
WSAWaitForMultipleEevents()가 STD_INPUT_HANDLE의 이벤트를 기다리도록 해보자
eventList에
hEvents[numSockets] = GetStdHandle(STD_INPUT_HANDLE);
위처럼 STD_INPUT_HANDLE을 넣고 대기시켜보니 키보드를 한번만 입력해도 마치 트리거가 켜진 것 처럼 이벤트가 계속 발생했다.
WSAResetEvent() 등으로 이벤트를 unsignal시켜보려 했지만 실패했다.
// 그냥 ResetEvent()로 리셋시켰더니 unsignal되긴 했지만 keydown, keyup 등 모든 키보드 이벤트에 동작해서 사용할 수 없었다.
루프 내에서 gets()로 입력을 받아보자
WSAWaitForMultipleEvents()의 대기가 끝나고 아래로 내려오면 메세지를 수신한 뒤 gets()를 만나게 되는데 gets는 입력이 완료될때 까지 block 되기 때문에 메세지를 하나 보낼 때 마다 그동안 쌓였던 메세지를 다 받게돼서 사용할 수 없다.
ioctlsocket이라는 함수가 있던데 입출력비동기소켓으로 만들어준다고 한다. 이게 뭘까
입출력 비동기 모드
서버로부터 수신이 있거나 송신을 하는 동안 프로세스를 일시정지 하도록 하는 것.
원하는 결과는 오히려 동기 모드에 가깝다
시도해 볼 수 있는 다른 방법
WSAWaitForMultipleEevnts가 1ms만 대기하다가 return하고 바로 _getch로 입력 버퍼에서 문자를 가지고 와보자
WSAWaitForMultipleEvents의 대기시간을 1로 설정하고 루프 내에서
if(_kbhit()){
c = _getch();
// do with c
...
}
문제를 너무 비벼서 해결하는 것 같다. 해보진 않았지만 이 방법이 끝까지 잘 동작할 거라는 보장을 못하겠다.
더 좋은 방법을 찾아보자
해결한 방법
_begintrhead로 thread를 새로 만들어서 해당 thread로는 입력을 받고 기존 thread에서는 서버로 부터 수신을 계속 받는다.
unsigned __stdcall SendThread(void *s);
void main(){
/*
...소켓을 생성하고 서버에 연결하는 등...
*/
// thread 생성
HANDLE sendThread = _beginthreadex(NULL, 0, SendThread, (void*)s, 0, NULL);
while(1){
// recv message
/*
...생략...
*/
}
CloseHandle(sendThread);
}
unsigned __stdcall SendThread(void *s){
/*
변수 정의 및 초기화 등...
*/
while(1){
// send message
/*
...생략...
*/
}
}
'Programming > Socket' 카테고리의 다른 글
socket : socket이란? (0) | 2017.01.30 |
---|---|
socket : TCP/IP란? (0) | 2017.01.30 |
윈속(Winsock) 멀티플렉싱(Multiplexing) 함수 WSAEventSelect() (0) | 2016.08.07 |
소켓 종료 명령 - close()와 shutdown() (2) | 2016.07.26 |
소켓 멀티플렉싱 함수 select() (0) | 2016.07.20 |
- Total
- Today
- Yesterday
- 운영체제
- Cocos2d-x
- Git
- C/C++
- Java
- C++
- mongoDB
- 국내여행
- rxswift
- 자료구조
- 데이터베이스
- game
- 드라마
- database
- SHADER
- winsock
- 수학
- SOCKET
- ios
- swift
- DesignPattern
- C
- machine learing
- OS
- JSP
- Spring
- ue4
- SwiftUI
- 알고리즘
- scala
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |