13. 6. 13.

C++(Windows) TCP 서버

#include <WinSock2.h>
#include <WS2tcpip.h>
#include <stdio.h>

#pragma comment(lib,"wsock32.lib")

#define PORT 2020

int main(void){

 // WSAStartup
 
 // 소켓버전을 받음
 WSADATA wsaData;

 if(WSAStartup(WINSOCK_VERSION, &wsaData) != 0 ){
  printf("WSAStartup 실패, 에러코드 = %u\n",WSAGetLastError());
  return false;
 }else{
  printf("WSAStartup 성공\n");
 }


 // socket

 // 소켓디스크립터
 SOCKET s;

 // TCP/IP용 소켓생성
 s=socket(AF_INET,SOCK_STREAM,0);

 if(s==INVALID_SOCKET){
  printf("소켓 생성 실패, 에러코드 : %u\n",WSAGetLastError());
  WSACleanup();
  return false;
 }else{
  printf("소켓 생성 성공\n");
 }


 // setsockopt (SO_RCVBUF)

 // 1Mbytes 의 수신버퍼
 int nBufLen = 1048576;
 // 옵션 변수의 길이
 int size =sizeof(int);

 if( setsockopt(s, SOL_SOCKET,SO_RCVBUF, (char*)&nBufLen, size) != 0){
  printf("소켓 수신 버퍼 크기 설정 실패, 에러코드 = %u\n",WSAGetLastError());
  //소켓제거
  closesocket(s);
  WSACleanup();
  return false;
 }else{
  printf("소켓 수신 버퍼 크기 설정 성공\n");
 }


 // bind

 SOCKADDR_IN addr_bind;
 
 // AF_INET 체계임을 명시
 addr_bind.sin_family = AF_INET;
 // 설정된 포트를 사용
 addr_bind.sin_port = htons(PORT);
 // 기본네트워크 카드 설정
 addr_bind.sin_addr.s_addr = htons(ADDR_ANY);

 if( bind(s, (LPSOCKADDR)&addr_bind, sizeof(addr_bind)) == SOCKET_ERROR){
  printf("바인드 실패, 에러코드 = %u\n",WSAGetLastError());
  // 소켓제거
  closesocket(s);
  WSACleanup();
  return false;
 }else{
  printf("바인드 성공\n");
 }


 // listen

 if( listen(s, SOMAXCONN) == SOCKET_ERROR){
  printf("접속 대기 큐 설정 실패, 에러코드 = %u\n",WSAGetLastError());
  // 소켓제거
  closesocket(s);
  WSACleanup();
  return false;
 }else{
  printf("접속 대기 큐 설정 성공\n");
 }


 // accept

 struct sockaddr_in cli_addr;
 size = sizeof(cli_addr);

 printf("수신 대기 중...\n");

 SOCKET cs = accept(s,(sockaddr*)&cli_addr,&size);

 if(cs==INVALID_SOCKET){
  printf("접속 승인 실패, 에러코드 = %u\n",WSAGetLastError());
  // 소켓제거
  closesocket(s);
  WSACleanup();
  return false;
 }else{
  printf("접속 승인 성공\n");
 }

 printf("클라이언트 접속 ! \n클라이언트 IP : %s, 포트 : %d\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));


 // getpeername

 if( getpeername(s, (LPSOCKADDR)&cli_addr, &size) == SOCKET_ERROR){
  printf("클라이언트 정보 얻기 실패, 에러코드 = %u\n",WSAGetLastError());
  // 클라이언트 접속 소켓 제거
  closesocket(cs);
  // 대기소켓제거
  closesocket(s);
  WSACleanup();
  return false;
 }else{
  printf("클라이언트 정보 얻기 성공\n");
 }

 printf("클라이언트 IP : %s, 포트 : %d\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));


 // select

 FD_SET fd = {1,cs};
 // 타임아웃 3초 {3,0}
 TIMEVAL tv = {3,0};

 int ret;

 ret = select(0,&fd,NULL,NULL,&tv);

 if(ret == 0){
  printf("3초 동안 버퍼에 수신된 패킷이 없습니다.\n");
  // 클라이언트 접속 소켓 제거
  closesocket(cs);
  // 대기소켓제거
  closesocket(s);
  WSACleanup();
  return false;
 }

 if(ret == SOCKET_ERROR){
  printf("소켓 통신 오류 발생, 에러코드 = %u\n",WSAGetLastError());
  // 클라이언트 접속 소켓 제거
  closesocket(cs);
  // 대기소켓제거
  closesocket(s);
  WSACleanup();
  return false;
 }


 // recv

 char buf[10] = {0,};
 int len = 5;

 ret = recv(cs,buf,len,0);
 if(ret == SOCKET_ERROR){
  printf("소켓 통신 오류 발생, 에러코드 = %u\n",WSAGetLastError());
  // 클라이언트 접속 소켓 제거
  closesocket(cs);
  // 대기소켓제거
  closesocket(s);
  WSACleanup();
  return false;
 }

 printf("수신 데이터 = %s (%d bytes)\n",buf,ret);


 // send

 ret = recv(cs,buf,len,0);
 if(ret == SOCKET_ERROR){
  printf("데이터 송신 실패, 에러코드 = %u\n",WSAGetLastError());
  // 클라이언트 접속 소켓 제거
  closesocket(cs);
  // 대기소켓제거
  closesocket(s);
  WSACleanup();
  return false;
 }


 // shutdown

 if(shutdown(cs, SD_BOTH) != 0){
  printf("안전 종료 실패, 에러코드 = %u\n",WSAGetLastError());
  // 클라이언트 접속 소켓 제거
  closesocket(cs);
  // 대기소켓제거
  closesocket(s);
  WSACleanup();
  return false;
 }else{
  printf("안전 종료 성공\n");
 }
 

 // closesocket

 if(closesocket(cs) != 0){
  printf("소켓 제거 실패, 에러코드 = %u\n",WSAGetLastError());
  // 대기소켓제거
  closesocket(s);
  WSACleanup();
  return false;
 }else{
  printf("소켓 제거 성공\n");
 }

 if(closesocket(s) != 0){
  printf("소켓 제거 실패, 에러코드 = %u\n",WSAGetLastError());
  WSACleanup();
  return false;
 }else{
  printf("소켓 제거 성공\n");
 }


 // WSACleanup
 if(WSACleanup() != 0){
  printf("WSACleanup 실패, 에러코드 = %u\n",WSAGetLastError());
  return false;
 }else{
  printf("WSACleanup 성공\n");
 }


 return true;
}

댓글 없음:

댓글 쓰기