socket programming #1

2020. 12. 9. 00:32CS/네트워크

1. Network programming Interfave(API)

 1 ) API : Application Programming Interface

   - service를 부를 수 있는 application

   - application 을 위해 system에 의해 제공되는 interfaces and abstractions

 2) Network Programming at different levels

   - send Ethernet, ATM, ... packets -> layer2 (L2) 쪽을 access해서 사용 (복잡, 잘 안씀)

   - exchange UDP/TCP packets -> layer4 (L4)

   - RPC, Xlib, Corba..

 

 

  

2. API for TCP/IP

  - TCP/IP 는 정해진 API definition이 없다 -> 다양한 형태의 API가 존재

  - Sockets / TLI, XTI / Winsock / MacTCP

 

 

 

3.  socket API

  - 1981년 BSD 4.1(Unix)에서 소개

  - muliple protocol 지원

  - 처음엔 only UNIX -> winsock 확대

  - BSD에선 system call형태로, SVR4에서 library 로 구현

  - TCP/IP dml 3가지 socket types : streamed-oriented(TCP), datagram(UDP), raw IP(IP, ICMP)

 

 

 

4. socket

  1) socket interface: application과 TCP/UDP and other protocol stacks 사이에 위치 (common interface)

 

  2) socket and TCP/UDP relationship

    - socket 함수를 부르면 socket descriptor 가 return 된다 (=file descriptor)

    - port num 과 sd가 연결되어 데이터가 왔다 갔다

 

  3) 각 socket은 5가지 components와 관련

    - protocol family and protocol : socket()

    - source address, source port (자기 자신) : bind()

    - destination address, destination port (상대방) : connect() -> tcp

                                                                                  sendto() -> udp 에선 전송할때마다 주소를 넣어 보냄

 

 

 

5. creating a socket

  1) 개요

  #include <sys/types.h>

  #include <sys/socket.h> //헤더

  int socket(int family, int type, int protocol)

  - socket descriptor (small integer)를 return 하고 오류시 -1 을 return 한다.

  - socket 들이 정보를 주고 받기 위한 resources들이 (구조체 형태로?) 있다.

 

  2) family

    - PF_INET(protocol family internet): Internet Protocol(TCP/IP) ->IPv4를 사용할 때 //인터넷에서는 주로 이 두가지

    - PF_INET6: IPv6 //이것도! 하지만 지금은 IPv4를 쓰므로 위에꺼 사용

    - PF_LOCAL: for local communication //내부에서 사용

    - PF_UNIX:  UNIX system internal protocol //내부에서 사용

등등

 

  3) type of service

    - SOCK_STREAM: TCP

    - SOCK_DGRAM: UDP

    - SOCK_RAW: raw IP

 

  4) example

 #include<stdio.h>
 #include<sys/types.h>
 #include<sys/socket.h>
 
 int sockfd; //socket file descriptor
 
 if((sockfd=socket(PF_INET, SOCK_STREAM,0))<0){ //socket 생성 함수 호출 //protocol family
     perror("socket error"); //에러 발생 메세지 출력   
     exit(1) //비정상적 종료}
 }

 

 

6. bind the local address

  1) 개요

#include<sys/types.h>

#include<sys/socket.h>

int bind(int sockfd, struct sockaddr *addr, int addr_len)

             -> socket file descriptor, (일반적으로 server의) ip address/ portnum 구조체, 구조체 길이

  - 현재 socket의 ip 주소와 port num을 묶어주는데 쓰인다.

  - return 0 -> successful -1 -> error

 

  2) address structures

    - defined in <netinet/in.h>

struct sockaddr{

  u_char sa_len; //length: used in kernel (sa-> socket addr)

  u_char sa_family; //address family

  u_char sa_data[14];  //address (14 bytes)

}

struct sockaddr_in{  //internet에서 사용

  u_char sin_len;  //length

  u_short sin_family; //AF_INET

  u_short sin_port;  //portnum (2 bytes)

  struct in_addr sin_addr;  //IPaddress (4 bytes)

  char sin_zero[8];  //사용x (8 bytes)

}

struct in_addr{

  u_long s_addr; //32 bit IP address

}

 

   3) example

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

#define MYPORT 50000

int sockfd; 
struct sockaddr_in my_addr; //구조체 선언 후 bind 해야함

//create socket(위 참고)

memset(&my_addr, 0, sizeof(my_addr)); //memory set->구조체 내용 clear
//bzero((char*)&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET; //address family
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY); //host to net

if(bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr))<0){
  //error 메세지 출력
  exit(1);
}

 

 

(여기부터)

* byte order conversion

  1) byte ordering (여러 byte로 되어 있는 data를 메모리에 어떻게 표현할 것인가)

    - little endian: least significant byte first(Intel) 

    - big endian: most significant byte first(Motorola, Sun)

 

  2) network byte order => big endian (통일해서 사용해야 함)

 

  3) 개요

#include <sys/types.h>

#include <netinet/in.h>

 

//host byte order <-> network byte swaping

u_long htonl(u_long hostlong);  //host to network long integer

u_long ntohl(u_long netlong);  //network to host long integer

u_short htons(u_short hostshort);  //host to network short integer

u_short ntohs(u_short netshort);  //network to host short integer

 

* Name-to-Address Conversion (ip 주소가 아닌 다른 정보, 이름을 알고 있을 때 사용)

  1) 개요

#include <sys/socket.h>

#include <netdb.h>

 

//host 이름을 주고 return => host information

struct hostent *gethostbyname(const char *name);

//network byte order address를 주고 return => host information

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

 

* Looking up A Domain Name

  - defined in <netdb.h>

#define h_addr haddr_list[0]

struct hostent{

  char *h_name; //host name

  char **h_alias; //별명

  int h_addrtype;  //addr type = 2 (=AF_INEF)

  int h_length; //addr length = 4 for IPv4

  char **h_addr_list; //addr list

} //등등 여러가지 정보

 

* Gethostbyname()

  - example

struct hostent *phost;
struct in_addr**addr_list;

if((phost = gethostbyname("주소 입력"))==NULL){
  herror("gethostname");
  return 1;
}
//host에 대한 information을 print 해준다
printf("Official name is: %s\n", phost->h_name);
printf("   ip addresses:");
addr_list = (struct in_addr**)phost->h_addr_list);
for(i=0; addr_list[i] != NULL, i++){
  printf("%s", inte_ntoa(*addr_list[i]);  //internet network to addr (203.212.106 같은 형태로 바꿔준다)
}
printf("\n");

*Gethostbyaddr() -> 그냥 알아만 두기

- example

struct hostent *phost;
struct in_addr addr;

inet_aton("203.141.97.12", &addr); //a->아스키
phost = gethostbyaddr(&addr, sizeof(addr), AF_INET);
printf("Host name: %s\n", phost->h_name);

*Looking up A Well-known Port by Name

*New Function(IPv 4 뿐만 아니라 IPv6에서도 사용 가능) : name-to-addr conversion

*Getnameinfo

(-> 수업에 내용은 있으나 필요할때만 참고하면 될듯)

 

 

 

7. IP Address Manupulation

  -

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet.h/in.h>

 

//ip addr (203.252.106.2 이런 형태)를 dotted decimal(32 bits 형태로 바꿔줌!)

char *inet_ntoa(struct in_addr address); //network to aski

 

//dotted decimal to IP address

u_long inet_addr(char *dottedAddress);  //error-> return -1

int inet_aton(const char *cp, struct in_addr *inp);  //error-> return 0 (-1 이 return 되면 문제가 발생해서 생긴 함수)

//*inp->dotted deciaml 로 바뀐 값이 들어감

 

 -

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet.h/in.h>

#include <arpa.h>

bind() 구현 -> 위 참고

inet_aton("10.12.110.57",&(my_addr.sin_addr)); //my_addr.sin_addr.s_addr = inet_addr("10.12.110.57");

printf("%s", inet_ntoa(my_addr.sin_addr);

 

- summary

 - IPv6 확장 (pdf 파일 참고해서 시간 남으면 보기!)