전산쟁이의 카피질
뒤로
검색
글목록
댓글
트랙백
방명록
줏어온 윈도우즈용 소켓서버 소스
2009/06/12 11:37
server.cpp
정말 줏어온 서버소스-윈도우즈용
출처 :
http://hengki.net/37
//////////////////////////////////////////////////////////////////////// // // 비동기 소켓 서버 // 열혈강의 TCP/IP 21장의 예제를 클레스화 // 일단 에코 서버이며. 167 번째 줄에서 서버에서 해줄 코드를 입력하면 될듯.. // #define BUFSIZE 100 // 받아올 데이터 최대 크기 #define PORT 3000 // 포트번호 할당 // 해더파일 선언 #include <winsock2.h> #include <iostream> using namespace std; // ws2_32.lib 링크 #pragma comment(lib, "ws2_32.lib") class socketServer { private: // 변수 선언 WSADATA wsaData; SOCKET hServSock; SOCKADDR_IN servAddr; SOCKET hSockArray[WSA_MAXIMUM_WAIT_EVENTS]; //소켓 핸들배열 //- 연결 요청이 들어올 때마다 생성되는 소켓의 핸들을 이 배열에 저장. (최대64) SOCKET hClntSock; SOCKADDR_IN clntAddr; WSAEVENT hEventArray[WSA_MAXIMUM_WAIT_EVENTS]; // 이벤트 배열 WSAEVENT newEvent; WSANETWORKEVENTS netEvents; int clntLen; int sockTotal; int index, i; char message[BUFSIZE]; int strLen; void CompressSockets(SOCKET* hSockArray, int omitIndex, int total); void CompressEvents(WSAEVENT* hEventArray, int omitIndex, int total); void ErrorHandling(char *message); public: socketServer(); int StartServer(); }; socketServer::socketServer() { sockTotal=0; } int socketServer::StartServer() { // 윈속 초기화 (성공시 0, 실패시 에러 코드리턴) if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){ ErrorHandling("WSAStartup() error!"); } // 소켓 생성 (성공시 핸들을, 실패시 "INVALID_SOCKET" 반환) hServSock = socket(PF_INET, SOCK_STREAM, 0); // 소켓 생성 실패 처리 if(hServSock==INVALID_SOCKET){ ErrorHandling("socket() error"); } // 소켓 통신을 위한 기본 정보 servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = htonl(INADDR_ANY); servAddr.sin_port = htons(PORT); // 주소와 Port 할당 (바인드!!) if(bind(hServSock, (struct sockaddr *) &servAddr, sizeof(servAddr))==SOCKET_ERROR){ ErrorHandling("bind() error"); } // 이벤트 발생을 확인 (성공시 0, 실패시 "SOCKET_ERROR" 반환) newEvent = WSACreateEvent(); if(WSAEventSelect(hServSock, newEvent, FD_ACCEPT)==SOCKET_ERROR){ ErrorHandling("WSAEventSelect() error"); } // 연결 대기 요청 상태로의 진입 (신호가 들어올때까지 대기) if(listen(hServSock, 5)==SOCKET_ERROR){ ErrorHandling("listen() error"); } // 서버 소켓 핸들 정보 hSockArray[sockTotal]=hServSock; // 이벤트 오브젝트 핸들 정보 hEventArray[sockTotal]=newEvent; // 전체 소켓수 sockTotal++; // 루프 while(1) { // 이벤트 종류 구분하기(WSAWaitForMultipleEvents) index = WSAWaitForMultipleEvents(sockTotal, hEventArray, FALSE, WSA_INFINITE, FALSE); index = index-WSA_WAIT_EVENT_0; for(i=index; i<sockTotal; i++) { index = WSAWaitForMultipleEvents(1, &hEventArray[i], TRUE, 0, FALSE); if((index==WSA_WAIT_FAILED || index==WSA_WAIT_TIMEOUT)) continue; else { index = i; WSAEnumNetworkEvents(hSockArray[index], hEventArray[index], &netEvents); // 초기 연결 요청의 경우. if(netEvents.lNetworkEvents & FD_ACCEPT) { if(netEvents.iErrorCode[FD_ACCEPT_BIT] != 0) { puts("Accept Error"); break; } clntLen = sizeof(clntAddr); // 연결을 수락 (accept | 성공시 소켓핸들 실패시 "INVALID_SOCKET" 반환) hClntSock = accept(hSockArray[index], (SOCKADDR*)&clntAddr, &clntLen); // 이벤트 커널 오브젝트 생성(WSACreateEvent) newEvent=WSACreateEvent(); // 이벤트 발생 유무 확인(WSAEventSelect) WSAEventSelect(hClntSock, newEvent, FD_READ|FD_CLOSE); hEventArray[sockTotal]=newEvent; hSockArray[sockTotal]=hClntSock; sockTotal++; printf("새로 연결된 소켓의 핸들 %d \n", hClntSock); } // 데이터 전송해올 경우. if(netEvents.lNetworkEvents & FD_READ) { if(netEvents.iErrorCode[FD_READ_BIT] != 0) { puts("Read Error"); break; } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // // 서버 작업은 여기서 다하겠지.. // // 데이터를 받음 (message에 받은 데이터를 담음) strLen=recv(hSockArray[index-WSA_WAIT_EVENT_0],message, sizeof(message), 0); // 데이터 끝에 널값 입력 message[strLen]=0; // 에코(데이터를준 클라이언트에 다시 데이터쏘기) send(hSockArray[index-WSA_WAIT_EVENT_0], message, strLen,0); // 예의상 화면에도 한번 보여줘야지 cout<<message; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// } // 연결 종료 요청의 경우. if(netEvents.lNetworkEvents & FD_CLOSE) { if(netEvents.iErrorCode[FD_CLOSE_BIT] != 0) { puts("Close Error"); break; } WSACloseEvent(hEventArray[index]); // 소켓 종류 closesocket(hSockArray[index]); printf("종료 된 소켓의 핸들 %d \n", hSockArray[index]); sockTotal--; // 배열 정리. CompressSockets(hSockArray, index, sockTotal); CompressEvents(hEventArray, index, sockTotal); } }//else }//for }//while // 할당 받은 리소스 반환. WSACleanup(); return 0; } /************************************ /* /* CompressSockets /* */ void socketServer::CompressSockets(SOCKET* hSockArray, int omitIndex, int total) { int i; for(i=omitIndex; i<total; i++) { hSockArray[i]=hSockArray[i+1]; } } /************************************ /* /* CompressEvents /* */ void socketServer::CompressEvents(WSAEVENT* hEventArray, int omitIndex, int total) { int i; for(i=omitIndex; i<total; i++) { hEventArray[i]=hEventArray[i+1]; } } /************************************ /* /* ErrorHandling /* */ void socketServer::ErrorHandling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); } // 한번 실행해보는 메인함수!! /************************************ /* /* main /* */ int main(){ // 서버 인스턴트 socketServer server; // 서버시작 server.StartServer(); }
Tags
server
,
socket
,
windows
,
서버
,
소스
,
소켓
,
소켓 서버
이전 페이지
댓글 보기 (0)
트랙백 보기 (0)
다음 페이지
이 페이지는 Textcube 1.10.0 : beta 1 로 구동됩니다
데스크탑 화면