본문 바로가기

카테고리 없음

소켓 관련 함수



리눅스,윈도우에 따라 함수의 모습이 조금씩 다른것이 있고 이름이 다른것이 있다. 
물론 모습에 한정에 역할은 같고 사용하는데 지장은 없다
예를 들어 inet_addr() 함수인데 
MSDN에 따른 정의이다

1
2
3
4
unsigned long inet_addr(
  _In_ const char *cp
);
 
cs
_In_ 은 SAL이라고 일종의 코드상에 보여주는 주석이다 자세한 내용은 링크: MSDN


Linux manual 에 따른 정의이다
1
in_addr_t inet_addr(const char *cp);
cs
참고) typedef __uint32_t in_addr_t;
  typedef unsigned int       uint32_t;
unsigned long 하고 unsigned int 하고 다른게 아닌가 하는 의문이 들지도 모르지만 
크기가 동일하게 4바이트이다 이 또한 복잡한데 자세한 내용은 링크: MSDN 




#01 socket
1
2
3
4
5
6
7
8
#ifndef __linux__ 
#include <WinSock2.h> //윈도우 환경일시
#else
#include<sys/types.h> //리눅스 환경일시
#include<sys/socket.h> //리눅스 환경일시
#endif
 
int socket(int domain, int type, int protocol);
cs


domain - 네트워크에 따라 달라진다 TCP/IP 시 AF_INET

type - 소켓의 형태 SOCKET_STREAM , SOCK_DGRAM ,프로토콜 헤더를 직접 만들 경우 SOCK_RAW

RAW 소켓은 패킷은 만드는 것은 물론 송수신하는 네트워크 패킷의 데이터를 확인 할 수 있는데 리눅스에서는 root권한으로만 실행 가능하고 윈도우에서는 지원하지 않는다

prorocol - 소켓의 프로토콜 타입 지정 보통 0으로 지정하거나 맞는 프로토콜 값으로 지정


소켓 디스크립터 socket descriptor 란? socket이 성공적으로 생성되었으면 리턴되는 값으로 이로 각각의 소켓을 구분한다 


#02 connect

1
2
3
4
5
6
7
8
#ifndef __linux__
#include <WinSock2.h> //윈도우 환경일시
#else
#include<sys/types.h> //리눅스 환경일시
#include<sys/socket.h> //리눅스 환경일시
#endif
 
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
cs

연결 대기 중인 서버로 실제 연결을 맺는 함수

sockfd - socket 함수가 리턴하는 소켓 디스크립터

addr - 접속하고자 하는 아이피 및 서버 포트 정보가 있는 sockaddr 구조체의 주소값

addrlen - 전달하고자 하는 구조체의 길이



1
2
3
4
struct sockaddr {  
    unsigned short sa_family;  
    char sa_data[14];  
}; 
cs

소켓 통신을 하는 컴퓨터에 대한 IP 주소를 저장하는 데 사용된다

sa_family - 어떤 주소 체계를 가지고 있는지를 나타낸다 예를 들어 IP주소 체계인지 유닉스 주소 체계인지

sa_data - 14바이트의 주소 정보가 기록 된다


소켓이란 IP/TCP 통신만을 위해 존재하는 게 아닌 모든 네트워크 통신을 지원하기 위해 만들어 졌기 때문에 sockaddr 구조체는 다른 구조체로 캐스팅 되어서 사용된다. 주로 사용하는 TCP/IP의 주소정보를 저장하기 위해서는 sockaddr_in의 구조체가 캐스팅 되어 사용된다

1
2
3
4
5
6
struct sockaddr_in {
    short   sin_family; //주소 체계
    USHORT sin_port; // 포트 번호
    IN_ADDR sin_addr; //ip 주소 
    CHAR sin_zero[8]; // 패딩
}
cs

sockaddr(2바이트+14바이트) sockaddr_in(2+2+4+8) 사이즈가 같아서 캐스팅이 가능하다 char sin_zero[8]은 sockaddr 구조체와 크기를 맞추기 위한 것이다 

in_addr 구조체는 다음과 같이 union으로 선언되어 있다

1
2
3
4
5
6
typedef struct in_addr {
        union {
                struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b;
                struct { USHORT s_w1,s_w2; } S_un_w;
                ULONG S_addr;
        } S_un;
cs



#03 bind

1
2
3
4
5
6
7
8
#ifndef __linux__
#include <WinSock2.h> //윈도우 환경일시
#else
#include<sys/types.h> //리눅스 환경일시
#include<sys/socket.h> //리눅스 환경일시
#endif
 
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
cs

sockfd - socket 함수가 리턴하는 소켓 디스크립터

addr - 접속하고자 하는 아이피 및 서버 포트 정보가 있는 sockaddr 구조체의 주소값

addrlen - 전달하고자 하는 구조체의 길이


connect 함수와 동일하지만 하는 역할은 다르다 

클라이언트 측의 sockaddr_in 은 서버의 ip주소와 포트번호 지만 서버측의 즉 bind() 에서의 sockaddr_in 은 연결 받고자 하는 소켓번호와 소켓 주소이다


#04 listen

1
2
3
4
5
6
7
8
#ifndef __linux__
#include <WinSock2.h> //윈도우 환경일시
#else
#include<sys/types.h> //리눅스 환경일시
#include<sys/socket.h> //리눅스 환경일시
#endif
 
int listen(int sockfd, int backlog);
cs

연결을 기다리는 함수이다

sockfd - 소켓 디스크립터

backlog - 연결을 기다리는 대기열 큐의 사이즈


#05 accept

1
2
3
4
5
6
7
8
#ifndef __linux__
#include <WinSock2.h> //윈도우 환경일시
#else
#include<sys/types.h> //리눅스 환경일시
#include<sys/socket.h> //리눅스 환경일시
#endif
 
int accept(int sockfd, struct sockaddr * addr, socklen_t * addrlen);
cs

연결을 수락하는 함수

연결 성공 시 리턴 값은 연결을 받아들인 새로운 소켓 디스크립터이다 실패 시 -1 리턴

연결 요청이 없는 경우 요청이 있을 때까지 대기 상태를 유지한다

sockfd - 연결을 기다리는 소켓 디스크립터

addr - 받아들인 클라이언트 주소 및 포트 정보가 있는 sockaddr 구조체의 주소값

addrlen - sockaddr 구조체의 길이가 저장된 변수의 주소값


#05 send

1
2
3
4
5
6
7
8
#ifndef __linux__
#include <WinSock2.h> //윈도우 환경일시
#else
#include<sys/types.h> //리눅스 환경일시
#include<sys/socket.h> //리눅스 환경일시
#endif
 
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
cs

스트림 기반의 데이터 전송 함수 이다 데이타그램 기반의 데이터 전송 함수는 sendto()이다 
sockfd - 연결이 맺어진 소켓 디스크립터
buf - 보내고자 하는 데이터의 시작 주소
len - 보내고자 하는 데이터의 길이
flags - 옵션 플래그 보통 0 사용

#06 recv
1
2
3
4
5
6
7
8
#ifndef __linux__
#include <WinSock2.h> //윈도우 환경일시
#else
#include<sys/types.h> //리눅스 환경일시
#include<sys/socket.h> //리눅스 환경일시
#endif
 
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
cs
 
스트림 기반의 데이터 수신 함수 이다 데이타그램 기반의 데이터 수신 함수는 recvfrom()이다 
sockfd - 연결이 맺어진 소켓 디스크립터
buf - 수신받고자 하는 데이터가 저장될 주소
len - 수신받고자 하는 데이터의 길이
flags - 옵션 플래그 보통 0 사용


#07 sendto

1
2
3
4
5
6
7
8
9
#ifndef __linux__
#include <WinSock2.h> //윈도우 환경일시
#else
#include<sys/types.h> //리눅스 환경일시
#include<sys/socket.h> //리눅스 환경일시
#endif
 
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
    const struct sockaddr *dest_addr, socklen_t addrlen);
cs

데이터그램 기반 전송 함수

sockfd - 연결이 맺어진 소켓 디스크립터
buf - 보내고자 하는 데이터의 시작 주소
len - 보내고자 하는 데이터의 길이
flags - 옵션 플래그 보통 0 사용
dest_addr - 전송하려는 대상의 주소 정보가 저장된 sockaddr 구조체의 주소값
addrlen - sockaddr 구조체의 길이

#08 recvfrom

1
2
3
4
5
6
7
8
9
#ifndef __linux__
#include <WinSock2.h> //윈도우 환경일시
#else
#include<sys/types.h> //리눅스 환경일시
#include<sys/socket.h> //리눅스 환경일시
#endif
 
ssize_t recvfrom(int sockfd, const void *buf, size_t len, int flags,
    const struct sockaddr *src_addr, socklen_t addrlen);
cs
데이터그램 기반 수신 함수

sockfd - 연결이 맺어진 소켓 디스크립터

buf - 수신받고자 하는 데이터가 저장될 주소

len - 수신받고자 하는 데이터의 길이

flags - 옵션 플래그 보통 0 사용
src_addr - 수신지의 주소 정보가 저장된 구조체의 주소값
addrlen - sockaddr 구조체의 길이


sendto()와 recvfrom() 함수는 비연결 지향이기 때문에 함ㅅ를 사용 할 때는 대상 주소를 명시 해줘야 한다
send함수와 recv함수는 사전에 bind함수 또는 connect함수에서 대상의 주소값을 지정했기 때문에 대상 주소값을 지정할 필요가 없다



#09 close - 리눅스

1
2
#include <unistd.h>
int close(int fd);
cs


파일을 닫을 때 사용하는 close 함수가 소켓 디스크립터를 닫을 떄도 close 함수를 사용 할 수 있다


#10 closesocket - 윈도우

1
2
#include <WinSock2.h>
int closesocket(_In_ SOCKET s);
cs

윈도우 환경에서는 소켓 디스크립터를 닫을 때는 closesocket 함수를 이용해야 한다


#11 WSAStartup - 윈도우

1
2
#include <WinSock2.h>
int WSAStartup(WORD wVersionRequested, LPWSADATA IpWSAData);
cs

윈도우에서는 소켓 라이브러리를 사용하기 때문에 소켓 라이브러리 버전을 명시해줘야한다

wVersionRequested - 버전 정보

IpWSAData - 소켓의 세부 정보


#12 WSACleanup - 윈도우

1
2
#include <WinSock2.h>
int WSACleanup(void);
cs

소켓 라이브러리를 사용한 후 소켓 라이브러리를 해제 해줘야한다

WSAClenup 함수를 호출 시기는 프로그램이 종료하기 직전에 소켓 함수를 사용하지 않게 될 때 호출한다