본문 바로가기
TCP/IP

소켓 함수 및 헤더들

by 상레알 2011. 2. 7.



--------------------------------------------------------------------

* connect : 함수는 생성한 소켓을 통해 서버로 접속을 요청합니다.

원형 :  int connect (int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen);

int sockfd   : 소켓 디스크립터
struct sockaddr * serv_addr : 서버 주소 정보에 대한 포인터
socklen_t addrlen   : struct sockaddr * serv_addr 포인터가 가르키는 구조체의 크기

성공 시  0  return 실패시 -1 리턴


--------------------------------------------------------------------

* recvfrom : UDP 환경에서 데이터를 수신하는 함수

 

데이터를 전송하는 sendto 함수와 마찬가지로 수신할때에도 특정 클라이언트와 연결된 상태로 수신하는 것이 아니기 때문에 어디에서 데이터가 전송되었는지 알 수 없다. 따라서 함수 자체적으로 데이터가 전송된 위치 정보를 얻을 수 있는 기능을 제공한다.

 

엄밀히 따지면 수신된 UDP 패킷이 자체적으로 주소 정보를 지니고 있고, 데이터 수신함수는 이 주소 정보를 반환하는 것 뿐이다.

__________________________________________________________________________________

#include <sys/type.h>

#include <sys/socket.h>

 

int recvfrom(int sock, void *buf, int len, unsigned flags, struct sockaddr *addr, int *addrlen)


성공시 수신한 바이트 수 , 실패시 -1 리턴

 - sock : 데이터를 수신할 때 사용할 소켓의 파일 디스크립터를 인자로 전달한다.

- buf : 수신할 데이터를 저장할 버퍼를 가리키는 포인터이다.

- len : 수신할 수 있는 최대 바이트 수이다. 일반적으로 buf 가 가리키는 저장소의 크기를 넘지 않는다.

- flags : 옵션 정보를 설정하는데 필요한 인자.

- addr : 주소 정보 구조체 변수의 포인터를 인자로 넘긴다. 함수 호출이 끝나면, 데이터를 전송한 호스트의 주소 정보로 채워진다.

- addrlen : addr 포인터가 가리키는 주소 정보 구조체 변수의 크기를 인자로 전달한다.

 

--------------------------------------------------------------------

* getpid() 현 프로세스의 프로세스 ID 반환

 

#include <unistd.h>

pid_t getpid(void);

 
ex)  

#include <unistd.h>
#include <stdio.h> 

int main()
{
printf("my pid is %d\n", getpid());
exit(0);
}

--------------------------------------------------------------------

* isdigit() 문자가 숫자 문자인지 판별
 

인수로 받은 문자가 숫자 문자인 (‘0’~‘9’)지를 판별랍니다. 

#include <ctype.h> 

int isdigit(int c)
 

c : 판별할 문자.
반환값 : 0 이 아닌숫자 c가 숫자 문자 ,(‘0’~‘9’) / 0 일 경우 c는 숫자 문자 아님

--------------------------------------------------------------------

inet_addr() : Dotted - Decimal notation 을 Big-Endian 32비트 값으로 변환

//인텔계열은 Little-Endian 방식을 쓴다....

// 네트워크바이트 순서는 항상 Big-Endian 방식으로 한다

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> 

unsigned long inet_addr(const char *string); 

인자 값으로 Dooted-Decimal Notation 문자열의 포인터를 넘겨주게 되면, 해당하는 unsigned long 타입의 데이터 값을 리턴한다. 

반환값 : 성공시 bing_Endian 32비트 값, 오류 발생 시 INADDR_NONE 리턴 

--------------------------------------------------------------------

* strstr

substring 즉 찾기 원하는 문자열이 존재하는지 검사한다.

 

#include <string.h>
 

char *strstr(const char *haystack, const char *needle);

strstr 함수는 문자열 haystack 에서 needle 이 처음 발견되는 곳을 찾는다.  

반환값 : 만약 haystack 에서 needle 를 찾는다면 처음 발견된 위치의 포인터를 반환 한다. 만약 needle 가 발견되지 않는다면 null 을 반환한다.  

--------------------------------------------------------------------

#include <unistd.h>

 

int gethostname(char *name, size_t len);

int sethostname(const char *name, size_t len);

 

이 함수는 현재 프로세스의 호스트 이름을 가져오거나 변경하기 위해서 사용한다. gethostname()함수는 호스트 이름을 가져온다. len은 가져올 name의 최대 길이를 지정하기 위해서 사용한다.

 

반환값 : 성공하면 0 을 실패하면 -1을 리턴하고, 적당한 errno를 설정한다.

 

에러

EINVAL : sethostname을 적용하는데 있어서 len이 음의 정수이거나, len이 허용된 크기를 넘었을 경우.

EPERM : sethostname은 루트권한을 가지고 있어야 한다.

EFAULT : name이 잘못된 주소영역을 가리키고 있다.

--------------------------------------------------------------------

* getpwuid()

패스워드 파일 엔트리를 UID 를 이용해서 가져온다.

 

#include <sys/types.h>

#include <pwd.h>

 

struct passwd *getpwuid(uid_t uid);

 

사용자 UID 와 일치하는 엔트리를 /etc/passwd 에서 가져오고 각 필드의 내용을 분리해서 passwd 구조체에 대한 포인터를 통해서 반환한다.

 

passwd 구조체는 <pwd.h> 에 정의되어 있다. struct passwd {

char *pw_name; /* 유저 이름 */

char *pw_passwd; /* 유저 패스워드 */

uid_t pw_uid; /* 유저 id */

gid_t pw_gid; /* 그룹 id */

char *pw_gecos; /* 실제 이름 */

char *pw_dir; /* 홈 디렉토리 */

char *pw_shell; /* shell 프로그램 */

};

 

반환값 : passwd 구조체에 대한 포인터를 반환하거나 일치하는 엔트리가 발견되지 않을경우 혹은 에러가 발생했을경우 NULL 을 반환한다.

에러 - ENOMEM : 패스워드 구조체를 할당할 메모리가 충분하지 않다.

 

--------------------------------------------------------------------

#include <netdb.h> 

struct hostent* gethostbyaddr(const char *addr, int len, int type); 

성공 시 hostent 구조체의 포인터 / 실패 시 NULL 포인터 리턴 

- addr : 이번에도 선언은 char*로 되어 있지만 실제로 요구하는 것은 변경할 IP 주소 정보를 지니고 있는 in_addr 구조체 변수 포인터이다. 물론 IPv4와 IPv6 두 주소 체계를 모두 수용하기 위해서 선택한 일반화에 해당된다.

- len : 입력되는 주소의 길이를 전달한다. IPv4 인 경우 4 IPv6인 경우 16을 전달한다.

- type : 입력되는 주소의 주소체계(타입)를 전달한다. AF_INET 혹은 AF_INET6가 될것이다.

결과는 hostent 구조체 변수를 통해서 얻게 된다

--------------------------------------------------------------------

socket( ) 

#include<sys/types.h>
#include<sys/socket.h> 

int socket(int domain, int type, protocol); 

domain : 생성할 소켓이 통신을 하기 위해 사용할 프로토콜를 설정
type: 소켓이 데이터를 전송하는데 있어서 , 사용하게 되는 전송 타입을 설정
protocol : 두 호스트 간에 통신을 하는데 있어서 특정 프로토콜을 지정 하기위해 사용된다 

socket 함수 호출 시 요구되는 세 개의 인자들이 각각 무엇을 의미하는지 상당히 애매하게 느껴질 것이다. 그렇게 느껴지는 것도 어떻게 보면 당연한 것이다. 그러나 소켓을 생성하기 위해서 이 세가지 인자에 대한 이해는 필수이다.  

socket 함수의 첫 번째 인자로 프로토콜 체계를 지정해야 한다. 그렇다면 프로토콜 체계란 무엇은가. 또 어떠한 값을 지정해 주어야 하는지.... 아래 표는 인자로 전달할 수 잇는 프트토콜 체계를 정리 한 것이다.

프트토콜 체계(Protocol Family)

정의

PF_INET

IPv4 인터넷 프로토콜

PF_INET6

IPv6 인터넷 프로토콜

PF_LOCAL

Local 통신을 위한 UNIX 프로토콜

PF_PACKET

Low level socket 을 위한 인터페이스

PF_IPX

IPX 노벨 프로토콜

 

 

주소체계(Address Family)

정의

AF_INET

IPv4 인터넷 프로토콜

AF_INET6

IP_6 인터넷 프로토콜

AF_LOCAL

Local 통신을 위한 UNIX 프로토콜

PF_INET 을 소켓의 첫 번째 인자로 전달하는 경우에 생성되는 소켓은 주소 체계를 IPv4기반으로 하는 인터넷 프로토콜에 적합한 소켓이 생성될 것이다. 다시 말하면 IPv4기반의 인터넷 프로토콜을 기본으로 하는 소켓을 생성하는 것이다.

 

데이터를 주고 받는 환경이 달라지면 그에 맞는 프로토콜이 존재하기 마련이다. 이러한 모든 경우에 소켓은 좋은 통신 기구가 될 수 있다. 왜냐하면 소켓은 여러 환경에서 사용될 수 있도록 설계되어 있기 때문이다. 따라서 소켓을 생성할 때 환경을 고려하여 프로토콜 체계를 지정해주면 그 환경에서 사용가능한 소켓이 생성된다. 즉 소켓은 모든 프로토콜을 수용할 수 있다는 뜻이라는데 이를 두고, 소켓은 “소켓은 프로토콜에 독립적이다.라고 표현한다.

--------------------------------------------------------------------

* select 함수

select 함수 호출전에 진행되어야 하는 세가지 설정은 디스크립터 설정, 검사 범위 설정,타임아웃 설정 과정 /

첫 번째로 디스크립터 설정 이다. select 함수를 사용하게 되면, 여러 개의 파일 디스크립터를 동시에 관찰할 수 있다고 하였다. 파일 디스크립터를 관찰할 수 있다는 말은 결국 소켓을 관찰할 수 있다는 말과 같다. 그렇다면 일단 관찰하고자 하는 파일의 디스크립터들을 모아야 한다. 모을 때도 관찰되는 항목에 따라서 따로 모아야 한다. 그렇다면 관찰할 수 있는 항목에는 어떠한 것들이 있는가?

■ 수신할 데이터를 지니고 있는 소켓이 존재하는가?

■ 데이터를 전송할 경우 블로킹되지 않는 소켓은 무엇인가?

■ 예외 상황이 발생한 소켓이 있는가?

이렇게 관찰 항목이 셋이기 때문에 세 묶음으로 파일 디스크립터를 준비해 둬야 한다.

파일 디스크립터를 세 묶음으로 모아 놓기 위해서 사용되는 것이 fd_set 데이터 타입의 자료형이다. fd_set은 0과1을 나타내는 비트들의 배열이라고 생각하면 된다.

 

그림에서 보듯이 0과 1을 표현할 수 있는 비트 단위 데이터 배열이다. 가장 왼쪽 비트는 파일 디스크립터 0을 나타낸다. 1로 설정된 비트가 관찰 대상이 되는 파일 디스크립터를 의미한다. 그렇다면 지금 그림에서는 어떤 파일 디스크립터를 관찰하겠다고 되어 있는가? 파일 디스크립터 1과 3을 관찰 대상으로 하고 있다.

두 번째로 검사 범위 설정 이다. select 함수는 여러 파일 디스크립터를 관찰하고, 그 결과를 전달해 준다. 그렇다면 여러 개의 디스크립터를 확인해야 하는데 이왕이면 확인해야하는 범위를 설정해 주면, 보다 효율적으로 수행할 수 있을 것이다.

세 번째로 타임아웃 설정이다. 타임아웃을 설정한다는 것은 블록킹 상태를 빠져 나가기 위한 시간 설정을 의미한다.

select 함수는 호출했을 때 관찰 대상들에게서 변화 (관찰 항목에 부합되는 소켓의 변화를 의미한다) 가 발생해야 리턴하며, 그렇지 않으면 변화가 발생될 때까지 무한정 블로킹 상태에 있게 된다. 그러나 타임아웃을 설정해 놓으면 관찰 대상들에게서 변화가 없더라도 설정 시간이 지나면 무조건 리턴한다. 따라서 무한 대기 상태에 바지는 것을 피할수 있다.

 

#include <sys/time.h>

#include <sys/types.h>

#include <unistd.h>

 

int select (

int n, fd_set *readfds,

fd_set *writefds,

fd_set *exceptfds,

struct timeval *timeout

);

- n : 검사 대상이 되는 파일 디스크립터의 수

- readfds : “입력 스트림에 변화가 발생했는지” 확인하고자 하는 소켓들의 정보를 전달한다.여기서 입력 스트림에 변화가 발생했다는 것은 수신할 데이터가 있다는 뜻이다.

- writefds : "데이터 전송 시, 블로킹되지 않고 바로 전송이 가능한지“ 확인하고자 하는 소켓들의 정보를 전달 한다.

- exceptfds : "예외가 발생했는지“ 확인하고자 하는 소켓들의 정보를 전달한다.

- timeout : 함수 호출 후 , 무한 대기 상태에 빠지지 않도록 타임-아웃(time-out)을 설정하기 위한 인자를 전달한다.

리턴 값 : -1이 리턴되는 경우 오류 발생을 의미한다. 또한 0이 리턴되는 경우에는 타임아웃에 의해 리턴 되었음을 의미한다. 마지막으로 리턴된 값이 0보다 큰 경우는 변경된 파일 디스크립터의 수를 의미한다.

=> select 함수 호출시 전달되는 파일 디스크립터의 정보는 소켓뿐 아니라 파일을 나타내는 경우에도 전달이 가능한다.

- 더 자세한 내용은 TCP/IP 소켓 프로그밍 책 287 을 참고 하기 바란다.

 

 

* struct timeval

 

struct timeval {

longtv_sec;//seconds

long tv_usec; //and microseconds

};

--------------------------------------------------------------------

* struct sockaddr_in IPv4의 주소 체계를 나타내는 구조체

 

struct                   sockaddr_in {

sa_family_t          sin_family; //주소 체계(address family)

uint16_t               sin_port; // 16비트 TCP/UDP Port

struct                 in_addrsin_addr; // 32비트 IPv4주소

char                   sin_zero[8]; // 사용되지 않음

};

 

ex) struct in_addr{

uint32_t                 s_addr;//32비트 IPv4 인터넷 주소

};

 

생소한 데이터 타입들이 나오고 있다. 이러한 데이터 타입들은 POSIX에서 그 근거를 찾을 수 있다. POSIX(Portable Operating System Interface)란 유닉스 계열의 운영 체제를 위해 표준화 해 놓은 인터페이스(API)다.

 

Data type

Description

Header

int8_t

uint8_t

int16_t

uint16_t

int32_t

uint32_t

signed 8-bit int

unsigned 8-bit in (unsigned char)

signed 16-bit int (unsigned short)

signed 32-bit int

unsigned 32-bit int(unsigned long)

<sys/types.h>

sa_family_t

socklen_t

address family

length of struct

<sys/socket.h>

 

이런 식으로 데이터 타입을 따로 선언해 놓은 이유는 확장성을 고려한 결과이다. 즉 int32_t라는 데이터 타입을 사용한다면, 어떠한 경우에도 4바이트 데이터 타입이라는 것을 보장 받을 수 있다.

--------------------------------------------------------------------

* struct passwd

 

사용 예)

if((p_pwd = getpwnam(uname)) == NULL) {

return -1;

}

 

/etc/passwd 에서 해당 uname의 정보를 passwd에 저장

 

passwd 구조체는 다음처럼 <pwd.h>에 정의.

 

struct passwd {

char *pw_name; /* 유저 이름 */

char *pw_passwd; /* 유저 패스워드 */

uid_t pw_uid; /* 유저 id */

gid_t pw_gid; /* 그룹 id */

char *pw_gecos; /* 실제 이름 */

char *pw_dir; /* 홈 디렉토리 */

char *pw_shell; /* shell 프로그램 */

};

--------------------------------------------------------------------

struct hostent

#include <netdb.h> 에 정의

 

struct hostent {

char *h_name;// official name

char **h_aliases;//alias list

int h_addrtype;//host address type

int h_length;//length of address

char **h_addr_list//list of addresses

}

 

hostent 구조체를 보면 IP 정보만 얻게 되는 것이 아니라, 여러 가지 다른 정보들도 덤으로 얻을 수 있다는 것을 알 수 있을 것이다. 복잡하게 생각하지 않아도 된다. 도메인 이름을 IP로 변경하는 경우에는 h_addr_list 멤버가 이중에서 가장 중요한 의미를 지닌다.

 

- h_name : 아마 들어 본 적 있을 것이다. 인기 그룹 누구의 공식 홈페이지, 어느 잘 나가는 회사의 공식 홈페이지, 이 공식 홈페이지에 접속할 수 있는 도메인 이름인 공식 도메인 이름(official domain name) 이다. h_name 멤버에는 공식 도메인 이름이 저장된다.

- h_aliases : 같은 홈페이지인데도 다른 도메인 이름으로 접속할 수 있는 경우를 본 적이 있는가? http://microsoft.net으로 한 번 접속해 보고 http://www.domestic.microsoft.com 으로 다시 한번 접속해 보라. 같은 홈페이지로 접속되는 것을 알 수 있을 것이다. 이처럼 해당 호스트에 접속할 수 이쓴 공식 도메인 이름 이외의 다른 이름들을 alias name 이라고 하는데 h_aliases 에는 이러한 정보들이 들어가게 된다.

 

- h_addrtype : gethostbyname 함수는 IPv4뿐 아니라 IPv6까지 지원을 한다. 그렇기 때문에 h_addr_list로 전달된 IP 주소의 주소 체계가 무엇인지를 가르쳐 준다.

 

- h_length : 결과로 전달되는 IP주소의 길이를 가르쳐 준다. IPv4인 경우는 주소의 길이가 4바이트이므로 4가 전달될 것이고, IPv6인 경우는 16바이트가 되므로 16이 저장될 것이다.

 

- h_addr_list : 이제 마지막 구조체 멤버에 대한 설명을 할 차례이다. 사실 가장 주요한 멤버가 된다. gethostbyname 함수로 전될된 도메인 이름에 해당하는 IP주소를 전달해 준다. 그런데 큰 회사 같은 경우는 여러 대의 서버를 운영하기 EOans에 하나의 도메인 이름에 대응하는 IP주소가 여러 개가 될 수 있다.

 

 

--------------------------------------------------------------------

------------------------------------------------

*struct servent

 

#include <netdb.h>

 

struct hostent {

char*s_name;//서비스의 공식 이름

char**s_aliases;//별명이름

ints_port;//포트번호

char*s_proto;//사용하는 프로토콜

}

--------------------------------------------------------------------

typedef struct _eth_header{

 

UCHAR dest_addr[6]; // 목적지 주소

 

UCHAR src_addr[6]; // 출발지 주소

 

USHORT d_type; // 이더넷 유형 또는 ieee 길이

 

} ETH_HEADER, *PETH_HEADER;

 

typedef struct _ip_header{

 

//little endian begin

USHORT len : 4; //버전

USHORT version : 4; //헤더 길이

// little endian end

USHORT tos : 8; // 서비스 유형

USHORT length; // 전체 길이

USHORT id; // 16 비트 아이디

//little endian begin

USHORT fragment_offset1 : 5; // 단편화 옵셋

USHORT flags : 3; // flag

USHORT fragment_offset2 : 8; // 단편화 옵셋

//little endian end

USHORT ttl : 8; // ttl

USHORT protocol : 8; // protocol tcp==06

USHORT checksum; // 헤더 첵섬

ULONG src_ip; // 출발지 IP

ULONG dest_ip; // 목적지 IP

} IP_HEADER,*PIP_HEADER;

 

typedef struct _tcp_header{

 

USHORT src_port; // 출발지 port

USHORT dest_port; // 목적지 port

ULONG sqc_number; // 시컨스 넘버

ULONG ack_number; // ack 넘버

//little endian begin

USHORT reserved1 : 4; // reserved

USHORT length : 4; // 헤더 길이

USHORT fin : 1; // FIN

USHORT syn : 1; // SYN

USHORT rst : 1; // RST

USHORT psh : 1; // PSH

 

USHORT ack : 1; // ACK

USHORT urg : 1; // URG

USHORT reserved2 : 2; // reserved

//little endian end

USHORT window_size; // 윈도우 크기

USHORT tcp_checksum; // TCP checksum

USHORT urg_point; //긴급 포인터

} TCP_HEADER,*PTCP_HEADER;

--------------------------------------------------------------------

* struct ifreq

다음은 ifr구조체의 멤버들이다. 이름에서 알수 있듯이 이더넷 장치에 대한 여러가지 중요 정보를 얻어 올수 있다.

 

struct ifreq

{

# define IFHWADDRLEN 6

# define IFNAMSIZ IF_NAMESIZE

union

{

char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */

} ifr_ifrn;

union

{

struct sockaddr ifru_addr;

struct sockaddr ifru_dstaddr;

struct sockaddr ifru_broadaddr;

struct sockaddr ifru_netmask;

struct sockaddr ifru_hwaddr;

short int ifru_flags;

int ifru_ivalue;

int ifru_mtu;

struct ifmap ifru_map;

char ifru_slave[IFNAMSIZ]; /* Just fits the size */

char ifru_newname[IFNAMSIZ];

__caddr_t ifru_data;

} ifr_ifru;

};

멤버들은 이름만 봐도알수 있을 것이다. ifru_addr, ifru_boradaddr,ifru_netmask등은 인터페이스 주소, 브로드케시팅 주소, 네트마스크 주소를 나타낸다. ifru_mut는 MTU(Maximum Transmission Unit)값을 가져오기 위해서 사용된다. MTU는 TCP/IP 네트워크 상에서 한번에 전송할 수 있는 패킷의 최대크기를 나타낸다. 이보다 큰 데이터를 보내고자 할때는 MTU사이즈에 맞도록 여러개로 나뉘어서 보내게 된다. 하나의 큰데이터를 보내는 것보다는 적당한 크기로 나누어서 보내는게 네트워크 환경의 효율을 높일 수 있기 때문이다. MTU사이즈는 네트워크 환경에 따라 달라 질수 있다. 일반적으로 ethernet은 1500의 크기를 가진다.

 

--------------------------------------------------------------------

* vfprintf

포맷된 출력을 스트림에 기록한다.

 

#include <stdio.h>

int vfprintf(FILE "stream, const char *format, va_list arglist);

 

UNIX System V에서 사용 가능하다.

v...printf 함수는 ...printf 함수를 위한 대치 입력접으로 알려져 있다. 이 함수는 그것의 ...printf 상대역과 똑같은 행동을 하지만 인수 목록 대신 인수의 목록 포인터를 받아들인다.

vfprintf는 일련의 인수 포인터를 받아들이고 각 인수에 format이 가리키고 있는 포맷 문자열에 들어 있는 포맷 명시자를 공급한 뒤 포맷된 데이터를 스트림에 출력한다.이때 인수와 같은 수의 포맷 명시자가 있어야한다(포맷 명시자에 대한 자세한 설명은 printf를 참조하라).

반환값 : vfprintf는 출력된 바이트 수를 반환하며 에러가 발생하면 EOF를 반환한다.

--------------------------------------------------------------------

* va_arg , va_end , va_start

변수 인수 목록을 구현한다.

 

#include <stdarg.h>

void va_start(va_list ap, lastfix);

type va_arg(va_list ap,type);

void va_end(valist ap);

 

vfprintf 및 vprintf 같은 일부 C 함수는 고정된(알려진) 수의 파라미터와 아울러 변수 인수 목록을 취하는데, va_arg,va_end,va_start 매크로는 이들 인수 목록을 액세스하는 편리한 방법을 제공한다.

이들 함수는 호출된 함수가 전달 중인 인수의 목록을 일일이 추적하기 위해 사용된다.

해더 파일 stdarg.h는 하나의 형(va_list)과 세 개의 매크로(va_start,va_arg,va_end)를 선언한다.

va_list : 이 배열은 va_arg와 va_end에 의해 요구되는 정보를 유지하며 호출된 함수가 변수 인수 목록을 취할 때는 형 va_list의 변수 ap를 선언한다.

va_start : 이 루틴(매크로로 구현됨)은 ap를 함수에 전달 중인 첫 번째 변수 인수를 가리키도록 설정하는데, 반드시 첫 번째 va_arg 또는 va_end 호출 이전에 사용되어야 한다.

va_start는 ap와 lastfix등 두 파라미터를 취하는데, 전자는 va_list에서 설명한 것과 같고 lastfix는 호출된 함수에 전달중인 고정된 최종 파라미터명이다.

va_arg : 이 루틴(역시 매크로로 구현됨)은 전달중인 다음 인수(변수 인수 가운데 하나)와 같은 값과 인수를 가진 식으로 확장되며 va_arg에 대한 변수 ap는 반드시 va_start가 초기화된 ap 와 같아야 한다.

디폴트 규정 때문에 va_arg에서는 형 char, unsigned char,float를 사용할 수 없다.

첫 번째로 사용될 때 va_arg는 목록 내의 첫 번째 인수를 반환하며 다음부터는 매번 목록내의 다음 인수를 반환한다. 이것은 ap를 참조 취소한 뒤ap를 증가시켜 다음 항목을 가리키게 함으로써 수행된다. va_arg는 type을 사용하여 참조 취소를 수행하고 다음 항목을 위치시킨다. 다음부터 기동될 때마다 va_arg는 ap를 목록 내의 다음 인수를 가리키도록 수정한다.

a_end : 이 매크로는 호출된 함수가 정상적인 반환을 수행하도록 돕는다. va_end는 va_start가 재호출되지 않으면 사용될 수 없도록 ap를 수정할 수도 있다. va_end는 va_arg가 모든 인수를 판독한 뒤에 호출되어야 하는데 실패하면 프로그램 내에 정의되어 있지 않은 이상한 일이 벌어질 수도 있다. 

반환값 : va_start와 va_end는 값을 반환하지 않으며 va_arg는 목록 내의 현 인수(ap가 가리키고 있는 것)를 반환한다.

--------------------------------------------------------------------
* recv()

소켓으로 부터 데이터 수신....

 

#include <sys/types.h>
#include <sys/socket.h> 

int recv(int s, void *buf, size_t len,int flags)

 

int s : 소켓 디스크립터
void *buf : 수신할 버퍼 포인터 데이터
size_t len : 버퍼의 바이트 단위 크기
int flags : 아래와 같은 옵션을 사용할 수 있습니다.

flags

옵션 설명

MSG_DONTWAIT

수신을 위해 대기가 필요하다면 기다리지 않고 -1을 반환하면서 바로 복귀

MSG_NOSIGNAK

상대방과 연결이 끊겼을때, SIGPIPE 시그널을 받지 않도록 합니다.

 

반환 : -1 이외 : 실제 수신한 바이트 수 실패 -> -1

--------------------------------------------------------------------

* recv & send 입.출력 함수

 

#include <sys/types.h>
#include <sys/socket.h>

int recv(int sock, void * buf, int len, unsigned int flags);

int send(int sock, const void *buf, int len, unsigned int flags);

 

-성공 시 송 수신한 바이트 수, 실패시 -1 리턴

 

sock : 입.출력의 대상이 되는 소켓의 파일 디스크립터.

buf : 입력 및 출력을 위한 버퍼의 포인터

len : 전송할 데이터의 바이트 수, 혹은 수신할 수 있는 최대 바이트 수.

flags : 데이터 입.출력 시 그 방법에 있어서 옵션을 설정하는 용도로 사용된다. 옵션을 설정할 필요가 없어서 0을 인자로 넘길 경우 read , write와 완전 동일한 기능의 함수가 된다. 옵션은 Bitwise-OR('|')로 묶어서 두 개 이상이 함께 전달될 수 있다.

 

flags

Description

recv

send

MSG_DONTROUTE

데이터 전송 시 라우팅 테리블을 참조하지 않는다는 뜻으로 로컬 네트워크상에서 목적지를 찾겟다는 의미

 

MSG_DONTWAIT

데이터 입.출력 함수 호출 시 블로킹 되지 않고 바로 리턴할 것을 요구하는 경우에 사용. 이를 두고 넌 블로킹(non-blocking)I/O라 한다.

MSG_OOB

데이터 전송 시, 긴급 데이터(out-of-band data)전송을 위한 옵션

MSG_PEEK

버퍼에 수신된 데이터가 있는지 확인하기 위한 용도로 사용되는 옵션

 

--------------------------------------------------------------------
shutdown - shut down socket send and receive operations
 

#include <sys/socket.h> 

int shutdown(int s, int how); 

s: 종료하고자 하는 소켓의 파일 디스크립터

how : 종료 모드

-> SHOUT_RD(입력), SHOUT_WR(출력) , SHUT_RDWR(입.출력)

 반환값 : 성공시 0, 실패시 -1

 파일 전송 ....

1. 클라이언트가 서버에 연결
2. 서버는 클라이언트에게 파일을 전송한다.
3. 클라이언트는 서버로부터 파일을 수신한 후 Thank you 메시지를 전송
4. 클라이언트는 EOF를 수신해야 Thank you 메시지를 전송
5. close, shutdown 함수 모두 EOF를 전송하지만 서버는 shutdown함수를 호출해야 클라 이언트로부터 Thank you 메시지를 받을수 있다.

--------------------------------------------------------------------

* close()

#include <unistd.h>

int close( int fildes ); 

- fildes : 닫아줄 파일의 파일 디스크립터

 

close 함수를 호출하면서 닫고자 하는 파일의 디스크립터를 인자로 전달한다.

중요한 사실은 리눅스에서는 소켓도 파일로 취급하기 때문에 생성된 소켓을 닫아 줄 때에도 close 함수를 사용한다는 것이다.

 

 

==================================Header ==================================

stdio.h : 표준 입출력 라이브러리 (Standard input/output)
stdlib.h : 표준 라이브러리 (Standard library)
string.h : 문자열 처리 함수
unistd.h : 유닉스 시스템 표준 라이브러리 (UNIX Standard library)
sys/socket.h : 소켓 시스템 함수
sys/types.h : 소켓 시스템에 필요한 상수 선언
arpa/inet.h : 인터넷 주소 조작 함수
netinet/in.h : 인터넷 주소 조작 함수 

주소체계(Address Family)

정의

AF_INET

IPv4 인터넷 프로토콜

AF_INET6

IP_6 인터넷 프로토콜

AF_LOCAL

Local 통신을 위한 UNIX 프로토콜


'TCP/IP' 카테고리의 다른 글

Nagle 알고리즘  (0) 2011.05.02
getsockopt() , setopt () 함수  (0) 2011.05.02
ioctl : 장치 제어 함수  (0) 2011.04.29
sendto()  (0) 2010.03.28
SOCKADDR_IN 구조체  (0) 2010.03.28
SOCKET() 함수  (0) 2010.03.25
Linux: SOCK_PARCKET  (0) 2009.12.03
ICMP 프로토콜  (0) 2009.11.16
인터넷 소켓 활용  (0) 2009.08.31
TCP/IP 열혈 강의  (0) 2009.08.12