(회전) Windows sockets 프로 그래 밍 안내

17095 단어 lwip 학습
다음은 Windows Sockets 프로 그래 밍 의 입문 안내 입 니 다. 가장 기본 적 인 Winsock 함수 와 데이터 구 조 를 이해 하 는 데 도움 을 주 고 어떻게 함께 작 동 하 는 지 알려 드 립 니 다.
0. 서버 와 클 라 이언 트
서버 (Servers) 와 클 라 이언 트 (Client) 가 전혀 다른 두 가지 네트워크 프로그램 이 있 습 니 다.서버 와 클 라 이언 트 는 서로 다른 행동 을 하기 때문에 이들 을 만 드 는 과정 도 다 릅 니 다. 다음은 TCP / IP 서버 와 클 라 이언 트 의 일반 모델 을 만 드 는 것 입 니 다.서버 1. Winsock 초기 화 2. 소켓 (Socket) 만 들 기 3. 소켓 바 인 딩 4. 소켓 에서 클 라 이언 트 감청 5. 수락 (Accept)클 라 이언 트 로부터 의 연결 6. 데 이 터 를 수신 하고 보 냅 니 다. 연결 클 라 이언 트 를 끊 습 니 다. 1. Winsock 을 초기 화 합 니 다. 2. Socket 을 만 듭 니 다. 서버 에 연결 합 니 다. 4. 데 이 터 를 보 내 고 받 습 니 다. 5. 연결 을 끊 습 니 다. 주의: 두 사람 에 게 몇 단 계 는 같 습 니 다. 이 몇 단 계 는 거의 똑 같 습 니 다.지침 에서 이 몇 단 계 는 세 워 진 프로그램의 유형 에 따라 구체 적 으로 설명 할 것 이다.
1. 기본 적 인 Winsock 프로그램 만 들 기
기본 Winsock 프로그램 만 들 기 1. 빈 프로젝트 만 들 기 2. 빈 C + + 원본 파일 추가 3. 마이크로소프트 SDK 의 Lib, Include, Src 폴 더 에 대한 환경 설정 확인 4. 환경 을 구축 하 는 커 넥 터 의존 항목 에 WS2 가 포함 되 어 있 는 지 확인 합 니 다.32. lib, Winsock 을 사용 하 는 프로그램 은 이 파일 에 연결 해 야 합 니 다. 5. Winsock 프로 그래 밍 을 시작 하고 Winsock 2. h 를 포함 하여 Winsock 의 API 를 사용 합 니 다.(Winsock 2. h 헤더 파일 은 대부분의 Winsock 함수, 데이터 구조 와 정 의 를 포함 하고 있 으 며, Ws2tcpip. h 헤더 파일 은 Winsock 2 프로 토 콜 호 환 문서 에서 TCP / IP 로 IP 주 소 를 검색 하 는 새로운 함수 와 데이터 구 조 를 포함 하고 있 습 니 다.
#include 
#include 
#include 
int main() {
    return 0;
}

메모: IP Helper API 를 사용 하려 면 Ipholpapi. h 헤더 파일 을 참조 해 야 합 니 다. Ipholpapi. h 가 인 용 될 때 Winsock 2. h 를 참조 하 는 \ # include 참조 줄 은 Ipholpapi. h 줄 위 에 있어 야 합 니 다. Winsock 2. h 헤더 파일 은 Windows. h 의 핵심 요 소 를 내 적 으로 인 용 했 습 니 다. 일반적으로 Winsock 프로그램 에는 Windows. h 파일 이 포함 되 어 있 지 않 습 니 다. Windows. h 헤더 파일 이 필요 하 다 면, 정의 해 야 합 니 다 \ # define WIN32 LEAN AND MEAN 매크로. 몇몇 역사적 인 이유 로 윈도 우즈. h 패키지 에는 1.1 버 전의 Winsock. h 헤더 파일 이 포함 되 어 있 기 때문에 Winsock. h 와 Winsock 2. h 는 정의 로 인해 충돌 합 니 다. WIN32 LEAN AND MEAN 매크로 는 Winsock. h 가 윈도 우즈. h 에 포함 되 는 것 을 막 았 습 니 다. 다음은 예 입 니 다.
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
 #endif
 #include 
 #include 
 #include 
 #include 
 #include 
int main() {
    return 0;
}

2. Winsock 초기 화
모든 프로 세 스 (프로그램 과 DLLs) 는 Winsock 함 수 를 사용 하기 전에 일부 함수 로 Windows Sockets DLL 을 사용 해 야 합 니 다. 이것 도 Winsock 이 시스템 에서 지원 되 는 지 확인 해 야 합 니 다. (CB 버 전: 모든 Winsock 프로그램 은 Windows socket 이 시스템 에 지 원 될 수 있 도록 초기 화 되 어야 합 니 다.)Winsock 초기 화 1. wsaData WSADATA wsaData 라 는 WSADATA 대상 을 만 듭 니 다.
int iResult;
//   Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
    printf(“WSAStartup   :%d
”, iResult); return 1; }

WSASTartup 함 수 는 WS2 32. lib 를 사용 하기 위해 호출 되 었 습 니 다. WSADATA 구조 체 는 Winsock 의 실현 정 보 를 포함 하고 있 습 니 다. 매개 변수 MAKEWORD (2, 2) 는 2.2 버 전의 Winsock 을 사용 하여 높 은 버 전의 Winsock 을 사용 할 수 있 도록 시스템 에 설명 합 니 다.
3. Socket 을 만 듭 니 다.
MSDN 과 C + + Builder 의 문 서 는 여기에서 갈 라 진다. 내용 은 기본적으로 같 지만 구조 가 다르다. 다음은 MSDN 을 위주 로 한다.
(1) 클 라 이언 트 버 전
초기 화 후 SOCKET 대상 은 클 라 이언 트 에 의 해 예화 되 어야 합 니 다. Socket 1 을 만 듭 니 다. addrinfo 대상 을 설명 합 니 다. sockaddr 구 조 를 포함 하고 이 값 을 초기 화 해 야 합 니 다. 이 프로그램 에서 인터넷 주소 족 (Internet address family) 은 IPv 6 로 돌아 갈 지 IPv 4 로 돌아 갈 지 명확 하 게 밝 히 지 않 았 습 니 다. 프로그램 이 Socket 에 요청 하 는 형식 은 TCP 프로 토 콜 스 트림 소켓 입 니 다.(stream socket)。
#define DEFAULT_PORT "27015"
struct addrinfo *result = NULL,
                 *ptr = NULL,
                 hints;
ZeroMemory( &hints, sizeof(hints) );hints.ai_family = AF_UNSPEC;//       
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

2. getaddrinfo 함 수 를 호출 하여 명령 행 에서 전 송 된 서버 이름 의 IP 주 소 를 가 져 옵 니 다. getaddrinfo 함 수 는 서버 주소 와 포트 를 잘못 찾 거나 분석 하기 위해 정 수 를 되 돌려 줍 니 다.
iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
     printf("getaddrinfo   : %d
"
, iResult); WSACleanup(); return 1; }

3. ConnectSocket 이라는 SOCKET 대상 만 들 기
SOCKET ConnectSocket = INVALID_SOCKET;

4. socket 함 수 를 호출 하여 connectSocket 에 반환 값 을 부여 합 니 다. 이 프로그램 에 서 는 getaddrinfo 를 호출 하여 얻 은 hints 인자 의 첫 번 째 IP 주 소 를 사용 합 니 다. hints 에는 주소 족, 소켓 유형, 지정 한 프로 토 콜 형식 이 포함 되 어 있 습 니 다. 이 예 에서 TCP 스 트림 소켓 은 SOCK STREAM 으로 지정 되 어 있 으 며, 프로 토 콜 형식 은 IPPROMO TCP 로 지정 되 지 않 았 습 니 다. 주소 족 은 지정 되 지 않 았 습 니 다.(AF UNSPEC) 서버 의 반환 값 은 IPv 4 또는 IPv 6 일 수 있 습 니 다. 클 라 이언 트 가 IPv 6 또는 IPv 4 만 사용 하려 면 hints 매개 변수 에 있 는 주소 족 을 AF INET 6 또는 AF INET 로 설정 해 야 합 니 다.
//     getaddrinfo          
ptr = result;
//    SOCKET      
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);

5. 오 류 를 검사 하여 이 socket 이 유효 하 다 는 것 을 확인 합 니 다.
if (ConnectSocket == INVALID_SOCKET) {
    printf(“  socket%d
”, WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; }

socket 함수 의 인 자 는 필요 에 따라 변 경 될 수 있 습 니 다. 오 류 를 검사 하 는 것 은 성공 적 인 네트워크 프로그램의 관건 입 니 다. socket 함수 호출 에 실패 하면 INVALID SOCKET 으로 돌아 갑 니 다. 따라서 위의 if 문 구 는 소켓 을 만 들 때 발생 할 수 있 는 오 류 를 잡 는 데 사 용 됩 니 다. WSAGetLastError 는 마지막 에 발생 한 오 류 를 되 돌려 줍 니 다. 많은 오 류 를 주의 하 는 것 은 당신 에 게 달 려 있 습 니 다.의 프로그램, WSACleanup 은 WS2 32. DLL 의 사용 을 중지 하 는 데 사 용 됩 니 다.
(2) 서버 버 전
초기 화 후 소켓 은 서버 에 의 해 예화 되 어 socket 1 을 만들어 야 합 니 다. getaddrinfo 함 수 는 sockaddr 구조의 값 을 확인 합 니 다. AF INET 는 IPv 4 주소 족 SOCK STREAM 이 스 트림 소켓 (stream socket) 을 표시 합 니 다.IPPROTO TCP 는 TCP 프로 토 콜 AI PASSIVE 플래그 를 사용 하여 호출 자가 bind 함수 에서 되 돌아 오 는 소켓 주소 구조 체 를 사용 할 것 임 을 알려 줍 니 다. AI PASSIVE 플래그 가 설정 되 어 있 고 getaddrinfo 함수 의 인자 nodename 이 NULL 포인터 일 때 IPv 4 주소 일 경우 소켓 의 IP 주소 부분 은 INADDR ANY 로 설정 되 며 IPv 6 는 IN6ADR ANY INIT 가 됩 니 다. 27015 는서버 가 클 라 이언 트 와 연결 할 포트
#define DEFAULT_PORT "27015"
struct addrinfo *result = NULL,
    *ptr = NULL,
    Hints;
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
//                 
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
    printf(“getaddrinfo    :%d
”, iResult); WSAClearnup(); return 1; }

2. 서버 쪽 에 Listen Socket 이라는 SOCKET 대상 을 만들어 클 라 이언 트 의 연결 을 감청 합 니 다.
SOCKET ListenSocket = INVALID_SOCKET;

3. socket 함 수 를 호출 하여 ListenSocket 에 반환 값 을 부여 합 니 다. 이 서버 프로그램 에 대해 서 는 getaddrinfo 에서 IP 주 소 를 되 돌려 줍 니 다. 매개 변수 hints 는 주소 족, 연결 유형, 프로 토 콜 형식 을 포함 합 니 다. 이 예 에서 IPv 4 의 TCP 스 트림 소켓 이 만 들 어 졌 습 니 다. 형식 은 SOCK STREAM 이 고 프로 토 콜 은 IPPROMO TCP 입 니 다. 따라서 ListenSocket 은 IPv 4 주 소 를 되 돌려 줍 니 다. 서버 가 있 으 면프로그램 이 IPv 6 감청 을 사용 하려 면 인자 hints 에 있 는 주소 족 을 AF INET 6 로 설정 해 야 합 니 다. 서버 가 IPv 4 와 IPv 6 를 동시에 감청 하려 면 두 개의 socket, 한 개의 감청 IPv 4, 한 개의 감청 IPv 6 를 만들어 야 합 니 다. 두 개의 소켓 은 프로그램 에 의 해 독립 적 으로 분리 되 어야 합 니 다. Windows Vista 와 그 후 버 전 은 하나의 IPv 6 소켓 을 만들어 서 동시에 감청 I 를 만들어 야 합 니 다.pv4 와 IPv 6. 이 특성 에 대한 더 많은 정 보 는 MSDN 의 "Dual - Stack Sockets" 를 참조 하 십시오.
//        socket         
LisitenSocket = socket( result->ai_family, result->ai_socktype, result->ai_protocol);

4. 오 류 를 검사 하여 이 소켓 이 유효 하 다 는 것 을 확인 합 니 다.
if (ListenSocket == INVLID_SOCKET) {
    printf(“Error at socket(): %ld
”, WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; }

4. 데이터 교환 전의 행위
(1) 클 라 이언 트 버 전: Socket 연결
클 라 이언 트 가 네트워크 를 통 해 교 류 를 할 수 있 도록 서버 에 연결 해 야 합 니 다. Socket 에 연결 하여 connect 함 수 를 호출 하고 이미 만들어 진 socket 과 sockaddr 구조 체 를 매개 변수 로 한 다음 오 류 를 검사 합 니 다.
//      
iResult = connect( ConnectSocket, ptr->ai_addr, (int)pter->ai_addrlen); if (iResult == SOCKET_ERROR) { closesocket(ConnectSocket); ConnectSocket = INVALID_SOCKET; } // , getaddrinfo // , getaddrinfo freeaddrinfo(result); if (ConnectSocket == INVALID_SOCKET) { printf(“ !\n”);WSACleanup(); return 1; }

함수 getaddrinfo 는 socketadr 구조의 값 을 확인 하 는 데 사 용 됩 니 다. 이 예 에서 getaddrinfo 에서 돌아 온 첫 번 째 IP 주 소 는 connect 함수 에 전 달 된 sockaddr 구조 체 를 표현 하 는 데 사 용 됩 니 다. connect 에서 첫 번 째 IP 주 소 를 호출 하 는 데 실패 하면 getaddrinfo 에서 돌아 온 링크 의 다음 addrinfo 구조 체 를 시도 합 니 다. sockaddr 구조 체 에서 설명 한 정 보 는 다음 클 라 이언 트 맛 보기 입 니 다.연결 을 시도 하 는 서버 의 IP 주소 2 클 라 이언 트 가 연결 할 서버 포트 입 니 다. 위의 27015 는 클 라 이언 트 가 getaddrinfo 함 수 를 호출 할 때의 포트 입 니 다.
(2) 서버 엔 드 버 전: 소켓 연결, 감청 포트 연결, 연결 수락
서버 가 클 라 이언 트 로부터 연결 을 받 아들 이기 위해 서 는 반드시 네트워크 주소 가 있어 야 합 니 다. 아래 코드 는 IP 주소 와 포트 로 만 든 소켓 을 연결 하 는 방법 을 보 여 줍 니 다. 클 라 이언 트 는 IP 주소 와 포트 를 통 해 호스트 네트워크 에 연결 합 니 다. Socket 을 연결 하고 bid 함 수 를 호출 하여 이미 만 든 socket 과 getaddrinfo 함수 에서 돌아 온 sockaddr 를 호스트 네트워크 로 연결 합 니 다.인자 가 들 어 온 후에 오 류 를 검사 합 니 다.
//  TCP     
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
    printf(“    :%d
”, WSAGetLastError()); freeaddrinfo(result); closesocket(ListenSocket); WSACleanup(); return 1; }

Socket 이 Socket 에 연결 되 어 있 는 것 을 감청 한 후, 서버 는 반드시 와 야 하 는 클 라 이언 트 에 게 IP 주소 와 포트 를 감청 해 야 합 니 다. listen 함 수 를 호출 하면 만들어 진 ListenSocket 과 backlog 의 값 입 니 다. 받 아들 여야 할 연결 대기 열의 최대 수 를 매개 변수 로 입력 합 니 다. 이 경우, 매개 변수 backlog 는 SOMAXCONN 으로 설 정 됩 니 다. 이 특별한 상 수 는 Winsoc 에 게 알려 줍 니 다.k. 이 socket 에 허용 되 는 최대 연결 대기 열 수 를 제공 합 니 다. 그리고 오 류 를 검사 합 니 다.
if ( listen( ListenSocket, SOMAXCONN ) == SOCKET_ERROR ) {
    printf(“    :%d
”, WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; }

연결 을 수락 합 니 다. 소켓 이 연결 을 감청 하기 시작 하면 프로그램 은 소켓 의 연결 요청 을 처리 해 야 합 니 다. 소켓 의 연결 을 수락 합 니 다. 1. 클 라 이언 트 의 연결 을 받 아들 이기 위해 임시 SOCKET 대상 을 Client Socket SOCKET Client Socket 이 라 고 합 니 다. 2. 보통 서버 프로그램 은 listen 함 수 를 통 해 연결 요청 을 지속 적 으로 순환 합 니 다. 연결 이 발생 하면요청, accept 함 수 를 호출 하여 이 연결 을 처리 합 니 다. 이 기본 예 에서 코드 는 하나의 연결 만 받 아들 일 수 있 습 니 다.
ClientSocket = INVALID_SOCKET;
//          
ClientSocket = accept(ListenSocket, NULL, NULL);
if ( ClientSocket == INVALID_SOCKET) {
    printf(“      :%d
”, WSAGetLastError()); closesocket(ListenSocket); WSACleanup(); return 1; }

3. 클 라 이언 트 연결 이 받 아들 여지 면 서버 는 보통 받 아들 인 연결 을 다른 작업 의 스 레 드 나 I / O 작업 포트 로 옮 기 고 다른 연결 을 계속 받 습 니 다. 이 기본 예 에서 서버 는 다음 단 계 를 직접 진행 합 니 다.
5. 데이터 교환
(1) 클 라 이언 트 버 전: 데이터 전송 및 수신
다음 코드 는 연결 이 완료 되면 클 라 이언 트 가 send 와 recv 함 수 를 어떻게 사용 하 는 지 보 여 줍 니 다.
#define DEFAULT_BUFF 512
char *sendbuf = “this is a test”;
char recvbuf[DEFAULT_BUFF];
int recvbuflen = DEFAULT_BUFF;
int iResult;
//    
iResult = send ( ConnectSocket, sendbuff, (int)strlen(sendbuff) );
if ( iResult == SOCKET_ERROR ) {
    printf(“Send error: %d
”, WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } printf(“ :%ld
”, iResult); // , , ClientSocket iResult = shutdown(ConnectSocket, SD_SEND); if (iResult == SOCKET_ERROR) { printf(“ :%d
” WSAGetLastError()); closesocket(ConnectSocket); WSACleanup(); return 1; } // , do { iResult = recv(ConnectSocket, recvbuff, recvbuflen, 0); if ( iResult > 0 ) printf(“ :%d
”, iResult); else if ( iResult == 0 ) printf(“
”); else printf(“recv%d
”, WSAGetLastError()); } while ( iResult > 0 );

함수 send 와 recv 의 반환 값 이 전송 되 었 거나 받 아들 인 바이트 의 값 이나 다른 오류 가 있 습 니 다. 두 함수 모두 같은 인자 가 있 습 니 다. 활성 화 된 socket, 하나의 char 형식의 버퍼, 보 내 거나 받 아들 일 바이트 길이, 또는 사용 할 수 있 는 모든 플래그 가 있 습 니 다.

좋은 웹페이지 즐겨찾기