Network Programming(Socket Programming)
소켓은 컴퓨터 네트워크에서 프로세스 간 통신을 가능하게하는 기술이며, 네트워크상에서 데이터 송수신을 담당한다.
소켓은 주로 클라이언트/서버 모델에서 사용되며, 클라이언트는 서버로 연결을 시도하고, 서버는 연결을 수락하고 데이터를 송수신한다.
소켓은 application 레이어와 transport레이어 사이의 인터페이스 역할을 한다.
서버측 주요코드
#include <sys/socket.h>
int socket(int domain,int type, int protocol); //성공시 파일 디스크립터를, 실패시 -1 반환
int bind(int sockfd, struct sockaddr *myaddr, socklen_t addrlen);//IP와 포트번호를 소켓에 할당
int listen(int sockfd, int backlog); //성공시 0, 실패시 -1 반환
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); //성공시 파일 디스크립터, 실패시-1 반환.
//socket함수의 리턴 파일 디스크립터는 접속요청용, accept의 리턴 파일 디스크립터는 데이터 송수신용
int socket(int domain, int type, int protocol)
domain: 소켓이 사용할 프로토콜 체계(protocol family)이다. (IPv4를 사용하는지, IPv6인지.. 등. IPv4는 PF_INET이다.)
type: 소켓의 데이터 전송방식이다. 연결지향형(connection oriented)인지, 비연결지향형(connectless)인지 적어주어야 한다. 연결지향형은 SOCK_STREAM을 넘기면 되고, 비연결지향형은 SOCK_DGRAM을 넘기면 된다.
protocol: 두 컴퓨터간 통신에 사용되는 프로토콜 정보이다. TCP인 경우 IPPROTO_TCP를, UDP인 경우 IPPROTO_UDP를 넘기면 된다. 그런데, 앞서 type에 적은 정보를 통해 소켓의 프로토콜이 정해지기 때문에 protocol에 0을 전달해도 된다.
성공시 파일디스크립터를, 실패시 -1을 반환한다
int bind(int sockfd, struct sockaddr *myaddr, socklen_t addrlen)
IP와 포트번호를 소켓에 할당하는 함수.
sockfd: 주소정보(IP와 PORT)를 할당한 소켓의 파일 디스크립터이다. socket()으로부터 반환받은 파일 디스크립터를 넣어주면 된다.
myaddr: 할당하고자 하는 주소정보를 지니는 구조체 변수의 주소 값
일반적으로 bind함수 사용시
bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr))==-1)
error_handling("bind() error");
위와 작성하게 되는데,
두번 째 인자가 *myaddr 이다.
그런데, sockaddr 포인터 타입을 바로 전달하는 것이 아니라, sockaddr_in 타입의 serv_addr를 작성한 뒤에, 형변환하여 전달하고 있다. 왜 이렇게 복잡하게 했을까?
우선 sockaddr의 구조를 보면
struct sockaddr
{
sa_family_t sin_family; //주소체계(address Family. IPv4인지..v6인지..)
char sa_data[14]; //주소정보
}
위와 같은데,
sa_data라는 14바이트의 배열안에 port번호, IP주소, 나머지 빈칸은 0으로 채워야 한다.
그런데, 개발자가 이 배열에 일일이 차곡차곡 작성하고 있기는 힘들기 때문에 sockaddr_in 구조체를 만들어 작성하고, sockaddr으로 변환하여 사용하는 것이다
sockaddr_in의 구조는 아래와 같다.
struct sockaddr_in
{
sa_family_t sin_family; //주소체계
uint16_t sin_port; //port번호
struct in_addr sin_addr; //32비트 IP주소
char sin_zero[8]; //사용되지 않음. 0으로 채움
}
struct in_addr
{
in_addr_t s_addr; //32비트 IPv4 인터넷주소
}
(참고: 위 sockaddr_in 구조체는 IPv4만을 위한 구조체이다)
sockaddr로 변환하여 사용하기 위해, IPv4를 위한 구조체임에도 sin_family 값을 또 저장하고 있어야 하고
sockaddr에 필요한 port번호, 32비트 IP주소, 0을 가지고 있다.
addrlen; 두 번째 인자로 전달된 구조체 변수의 길이정보
클라이언트 주요 코드
#include <sys/socket.h>
int socket(int domain, int type, int protocol); //성공시 파일 디스크립터를, 실패시 -1 반환
int connect(int sockfd, struct sockaddr *serv_addr, socklen_t addrlen); //성공시 0, 실패시 -1 반환
소켓 통신 과정
'2023-1 > 컴퓨터네트워크및실습' 카테고리의 다른 글
htons / inet_addr (0) | 2023.03.31 |
---|---|
DHCP (0) | 2023.03.23 |
IP Addressing: classful, CIDR /IP Fragmentation /NAT (0) | 2023.03.17 |
Network Layer Basic (0) | 2023.03.10 |
Network Layer (1) | 2023.03.09 |
댓글