티스토리 뷰
소켓(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 |