티스토리 뷰


소켓(Socket)
  버클리 유닉스 에서 사용한 네트워크 프로그래밍 인터페이스, 이것을 윈도우에서 사용할 수 있도록 한 것을 윈도우 소켓(줄여서 윈속)이라 부름.
  윈도우 95버전부터 API에 정식으로 포함하여 제공되었고, 현재는 WinSock2 버전까지 나옴.

 

윈속(Windows Socket, Winsock)
  DLL를 통해 기능이 제공됨(WS2_32.DLL)
  윈도우의 메세지 구동방식으로 동작하므로, 이를 위한 확장 함수 존재
  유닉스 소켓과 소스 코드 수준에서 호환성이 높으므로 기존 프로그램을 포팅하기 쉽다.


  OS별 윈속 버전은 다음과 같다.
  윈도우 95 - 1.1
  윈도우 98/Me, 윈도우 NT/2000/XP/2003 - 2.2
  윈도우 CE - 1.1

 

#include "stdafx.h"
#include <winsock2.h> // w2_32.lib 링크 단계 추가 필수
#include <stdio.h>
#include <stdlib.h>

 

#define BUFFER_SIZE 512 // 클라이언트에서 받을 데이터 버퍼 사이즈

 

// 네트워크 관련 함수 오류 후 종료

void err_quit(char* msg)
{
   LPVOID lpMsgBuf;
   FormatMessage(
         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
         NULL, WSAGetLastError(),
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
         (LPTSTR)&lpMsgBuf, 0, NULL);
   MessageBox(NULL, (LPCTSTR)lpMsgBuf, msg, MB_ICONERROR);
   LocalFree(lpMsgBuf);
   exit(-1);
}

 

// 네트워크 관련 함수 오류 출력

void err_display(char* msg)
{
   LPVOID lpMsgBuf;
   FormatMessage(
         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
         NULL, WSAGetLastError(),
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
         (LPTSTR)&lpMsgBuf, 0, NULL);
   printf("[%s] %s", msg, (LPCTSTR)lpMsgBuf);
   LocalFree(lpMsgBuf);
}

 

int _tmain(int argc, _TCHAR* argv[])
{
   int retValue;

 

   // 윈속 초기화

   WSADATA wsa;
   if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
        return -1;

 

   // 소켓 생성

   SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, 0);
   if(listenSocket == INVALID_SOCKET)
       err_quit("socket()");

 

   // 위에서 생성한 소켓을 서버로서 만들기 위한 준비 단계 및 설정

   SOCKADDR_IN serverAddr;
   memset(&serverAddr, 0, sizeof(serverAddr));
   serverAddr.sin_family = AF_INET;
   serverAddr.sin_port = htons(5001);
   serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
   retValue = bind(listenSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
   if(retValue == SOCKET_ERROR)
       err_quit("bind()");

 

   // 접속하기 위한 소켓 대기자수 설정  

   retValue = listen(listenSocket, SOMAXCONN);
   if(retValue == SOCKET_ERROR)
       err_quit("listen()");

 

   SOCKET clientSocket;
   SOCKADDR_IN clientAddr;
   int nAddrLength;
   char recvBuffer[BUFFER_SIZE + 1];
// 기존 버퍼 사이즈에 +1 중요함. 문자열에 있어서 널문자 한 칸은 필수임

 

   while(1)
   {

       // 클라이언트 접속을 대기한다.
       nAddrLength = sizeof(clientAddr);
       clientSocket = accept(listenSocket, (SOCKADDR*)&clientAddr, &nAddrLength);
       if(clientSocket == INVALID_SOCKET)
       {
           err_display("accept()");
           continue;
       }


       printf("\n[TCP 서버] 클라이언트 접속 : IP 주소 = %s, 포트 번호 = %d\n",
          inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));

       // 클라이언트와 데이터 통신 루프
       while(1)
       {

          // 클라이언트에서 데이터를 읽는다.
          retValue = recv(clientSocket, recvBuffer, BUFFER_SIZE, 0);
          if(retValue == SOCKET_ERROR)
          {
               err_display("recv()");
               break;
          }
          else if(retValue == 0)
          {

               // 접속 종료
               break;
          }
          else
          {

               // 받은 데이터를 출력한다.
               recvBuffer[retValue] = '\0';
               printf("%s", recvBuffer);
          }
       }

 

       // 클라이언트 접속 종료 후 생성된 소켓을 반환한다.

       closesocket(clientSocket);


       printf("\n[TCP 서버] 클라이언트 접속 종료 : IP 주소 = %s, 포트 번호 = %d\n",
          inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));

   }

 

  // 생성한 서버 소켓을 반환한다.

   closesocket(listenSocket);

 

   // 윈속을 종료한다.

   WSACleanup();


   return 0;
}

'Programming > Network' 카테고리의 다른 글

소켓의 입출력 모델 준비  (0) 2011.03.08
Socket Option (소켓 옵션 세팅)  (0) 2011.03.08
Thread 란?  (0) 2011.03.08
네트워크 란?  (0) 2011.03.08
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
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
글 보관함