본문 바로가기
코스웨어/14년 스마트컨트롤러

2014.06.13 업무보고 출석번호 6번 김용우입니다.

by 알 수 없는 사용자 2014. 6. 16.
728x90
반응형

※네트워크 프로그래밍

▶소켓통신 연결에 대해서 기본적으로 배워보도록 하자.


먼저 기본적으로 소켓에 대해서 알아보자.

애플리케이션이 데이터를 주고 받을 수 있는 하나의 추상적인 통로이다.


애플리케이션이 자유롭게 하나의 파일로부터 데이터를 읽고 쓸 수 있는데, 소켓도 이와 비슷한 개념이다.

소켓을 사용하여 네트워크에 접속하고, 같은 네트워크에 접속중인 다른 애플리케이션과 통신할 수가 있다.


한 기기의 애플리케이션에서 소켓으로 데이터를 전송하면 다른 기기의 애플리케이션에서는 이 데이터를 받아서 읽을 수 있다.


간단히 말해서 컴퓨터를 연결해주는 소프트웨어 프로그램이라고 보면 간단하다. 

아래에서 간단히 알아볼 UDP와 IPX가 이와같은 소켓 통신이다.



먼저 네트워크의 기본적인 용어만 짚고 넘어가도록하자.

 


 domain

  - 소켓이 사용되는 네트워크의 영역을 정의 

IPC 

  - 창안에서 이동되는 통신을 의미 

 Network

  - 2개 이상의 다른 공간의 컴퓨터가 서로 연결하는 것을 의미



AF_UNIX 프로세스간 통신 IPC용

AF_INET 일반 TCP/IP 인터넷 통신

AF_IPX 노벨의 IPX

AF_X25 X.25 프로토콜



 Type

Protocol 

  •  통신에 사용할 패팅의 타입을 지정한다.
  •  Type에 따라서 Protocol이 정해진다.
  • 통신에 사용할 프로토콜 지정한다. 




SOCK_STREAM : 연결 지향형, 여러 번 write를 호출했더라도 수신 버퍼가 충분하면 한 번의 read로 수신 가능(no boundary).

SOCK_DGRAM : 비연결 지향형, write를 여러 번 호출했으면 수신 측에서도 반드시 여러 번의 read를 통해서 모든 데이터를 수신할 수 있다(boundary).

 

[출처] SOCK_STREAM, SOCK_DGRAM|작성자 jingene

SOCK_STREAM : IPPROTO_TCP

SOCK_DGRAM : IPPROTO_UDP

SOCK_RAW : 소켓을 생성하는데 안에 채워넣지 않음을 의미하는 것이다.



SOCK_STREAM & IPPROTO_TCP : TCP 기반의 통신에 사용

우리는 TCP방식에 집중한다.

SOCK_DGRAM&IPPROTO_UDP:UDP 기반의 통신에 사용

SOCK_RAW&(원하는 프로토콜): RAW Socket으로 저수준에서 프로토콜을 직접 다룰 때 사용



TCP소켓



소켓생성


socket 함수 반환값.

- 성공적으로 소켓을 만들면 0보다 큰 int 값을 반환

if(-1=iSock) = socket

(★소켓의 정확한 생성을 확인하기위해서 작성되는 소스코드는 -1로 표시하지만 실제로는 0보다 작다로도 많이 사용한다.)

- 소켓지정번호, socket descriptor(소켓의 서술자 즉 소켓에 대한 정보를 가지고있는 메모리 공간을 의미한다.)라고 부른다.

말그대로 소켓기술자, 서술자 등으로 불리며 소켓에 대한 정보를 가지고 있기 때문에 해당 내용을 지시, 제어 한다.

- 소켓을 지시하며, 이를 이용해서 소켓을 제어한다.



grep sockaddr_in /usr/include -r


grep : 어떤 글자를 잡아내라라는 의미이다

sockaddr_in : 찾아내고자하는 문자열이다.

/usr/include : 해당 위치 디렉토리에가서 찾는 것을 의미한다.

-r : 모든 것을 찾아라는 의미이다.



connect 함수의 사용 예.

struct sockaddr_in serveraddr;

server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

serveraddr.sin_family = AF_INET;

serveraddr.sin_addr.s_ADDR = INET_ADDR("218.234.19.87");

serveraddr.sin_port = htons(8080);


client_len = sizeof(serveraddr);

connect(server_sockfd,(struct sockaddr * ) & serveraddr, client_len);


- Intetnet TCP/IP 통신

- 218.234.19.87 주소로 연결요청

- 8080 포트에 연결된 프로그램을 요청


IP주소 -> 보관용 메모리라고 하면 이해할수 있다.

이러한 보관용 메모리를 구조체로 만들었으며

sockaddr_in 이라고 말그대로 소켓의 주소라고 하는 것이다.

ip Address와 Port번호를 저장하는 주소이다.


편지를 보내려면 받는 사람의 주소를 적어야한다. 위의 sockaddr_in구조체는  편지의 받는사람주소를 기입하는 공간과 같은 역할을 한다가 볼 수 있다.


일반적으로 port번호에서 80번은 웹에서 사용하는 번호이다.


8080은 포트번호이다. 이러한 포트번호의 중요성은 통신을 통해서 연결하여 접속하기 위한 PORT이다.

DOS창에서 기본적으로 telnet을 통해 구글에 접속하고자할때 telnet port인 21번 포트로는 접속하기 어렵다.

따라서 웹 port인 80 port를 타고 접속이 가능하다.


port는 기본적으로 2byte이다

따라서 구조체를 확인해보면


struct sockaddr_in{

{

sa_family_t               sin_family;    /* Address family

unsigned short int     sin_port;     /* Port Number

struct in_addr           sin_addr;          /* Internet address


/* Pad to size of 'struct sockaddr' . */

unsigned char __pad[__SOCK_SIZE__ - sizeof(short sizeof(unsigned short int) - sizeof(struct

구조체는 예전부터 설계를 해두었기 때문에 특정용량이 되어야한다. 따라서 마지막 Pad에 해당하는 부분은 채워넣기위한 부분이라서 더미 즉 그다지 쓸모없는 값을 의미한다. 따라서 사용하지 않는 부분이다.

};




※ IP의 문자열을 숫자로 바꾸어주는 함수가 따라 존재한다?

네트워크에서 사용하는 타입의 반대개념이

host타입의 숫자가 있고

네트워크타입을 사용하는 숫자가 있는데

이를 서로 바꾸어주는 함수가있는데


Host에서 Network로 바꾸어주는 함수가

H TO N이라고 해서 htons이 있다

반대로는

NTOH즉 ntohs가 존재한다.


우리가 아는 ip주소는 실제로 문자열이라고 볼 수 있다.

이러한 문자를 숫자로 바꾸어주는 함수가 있는데

이것이 바로 inet_addr();함수이다.






※inet_addr()함수는??

→우리가 아는 ip주소는 "192.135.123.21"과 같이 숫자로되어있다. 하지만 실제로는 문자열에라고 볼 수 있는데

inet_addr()함수는 이러한 ip주소의 문자열을 숫자로 바꾸어주는 역할을 하는 것이다. 우리가 생성한 구조체에 컴퓨터가 인식할 수 있게 바꾼뒤에 주소를 넣어주면된다.

(man 3 inet_addr 을 통해서 리눅스에서 알아볼 수 있다.)

→inet_addr함수는 아래와 같이 사용하였다.

 26     staddr.sin_addr.s_addr      =inet_addr("192.168.10.250");   // 문자열(IP)를 int로 바꾸어주는 함수이다.



※connect함수를 통해서 소켓을 연결해보자.

→connect함수는 말그대로 생성된 소켓을 통해서 소켓 연결을 시작하는 함수이다.

사용방법은 아래와 같다.

→connect함수를 사용한 예이다.

     28     connect(iSock,(struct sockaddr*)&staddr, sizeof(staddr));
     29     if(0 > iRet)    //connect() 실패하게되면 음수를 반환하게된다.
     30     {
     31         printf("\nConnect Fail!!\n\n");
     32         close(iSock);
     33         return 0;
     34     }


▶일반적으로 소켓연결에 성공하면 양수의 값 1이 반환된다. 하지만 실패시 음수의값 -1이 반환되기 때문에 실패할 것을 고려해서 위와같이 소스코드를 작성해두는 것이다.






※완성된 소스코드이다.

      1 #include <stdio.h>
      2 #include <sys/types.h>
      3 #include <sys/socket.h>
      4 #include <sys/stat.h>
      5 #include <arpa/inet.h>
      6
      7
      8 int main(void)
      9 {
     10     int iSock;
     11     struct sockaddr_in staddr;
     12     int iRet;
     13
     14     // IPv4를 사용하고 TCP방식 사용하는 소켓을 생성
     15     iSock = socket(AF_INET,SOCK_STREAM,0);
     16
     17     if(0 > iSock)   // or ((-1)==iSock); 에러발생시
     18     {
     19         printf("\n소켓을 생성할 수 없음\n\n");
     20         return 0;
     21     }
     22
     23
     24     staddr.sin_family       = AF_INET;
     25     staddr.sin_port         =htons(4006);   // '4006'번 port에 접속할 예정이다.
     26     staddr.sin_addr.s_addr      =inet_addr("192.168.10.250");   // 문자열(IP)를 int로 바꾸어주는 함수이다.
     27
     28     connect(iSock,(struct sockaddr*)&staddr, sizeof(staddr));
     29     if(0 > iRet)    //connect() 실패하게되면 음수를 반환하게된다.
     30     {
     31         printf("\nConnect Fail!!\n\n");
     32         close(iSock);
     33         return 0;
     34     }
     35
     36     printf("\n소켓번호 : %d \n\n", iSock);
     37     close(iSock);   //소켓을 닫을 때 close를 사용
     38     return 0;
     39 }




늦어서 죄송합니다 ㅠㅠㅠㅠㅠㅠㅠㅠ

728x90