TCP와 UDP에 대한 이해 --------------------------------------------------------------------------------------------


설명전에 일단 전에 보았던 OSI 7계층을 다시 봅니다.


 레벨

 계층

 기능

 7계층

 Application

응용 계층

프로토콜 : DHCP, DNS, FTP, HTTP

서비스 제공

사용자가 네트워크에 접근할 수 있도록 해주는 계층이다.

사용자 인터페이스, 전자우편, 데이터베이스 관리 등 서비스를 제공한다.

예로, 텔넷이나 HTTP, SSH, SMTP, FTP 등을 들 수 있다.

 6계층

 Presentation 

표현 계층

프로토콜 : JPEG, MPEG, SMB, AFP

이해할 수 있는 포멧변환

운영체계의 한 부분으로 입력 또는 출력되는 데이터를 하나의 표현 형태로 변환한다.

필요한 번역을 수행하여 두 장치가 일관되게 전송 데이터를 서로 이해할 수 있도록 한다.

제어코드나 문자 및 그래픽등의 확장자(jpg, gif, mpg)를 생각하면 쉽다.

 5계층

 Session

세션 계층

프로토콜 : SSH, TLS

응용간의 질서 제어

통신 세션을 구성하는 계층으로, 포트(Port)연결이라고도 할 수 있다.

통신장치 간의 상호작용을 설정하고 유지하며 동기화 한다.

사용자간의 포트연결(세션)이 유효한지 확인하고 설정한다.

 4계층

 Transport

전송 계층

프로토콜 : TCP, UDP, ARP

장비 : 게이트웨이

전체 메시지를 발신지 대 목적지(종단 대 종단)간 제어와 에러를 관리한다.

패킷들의 전송이 유효한지 확인하고 실패한 패킷은 다시보내는 등 신뢰성 있는 통신을 보장하며, 머리말에는 세그먼트(Segment)가 포함된다. 대표적인 프로토콜은 TCP이다.

 3계층

 Network

네트워크 계층

프로토콜 : IP, ICMP, IGMP

장비 : 라우터

다중 네트워크 링크에서 패킷(Packet)을 발신지로부터 목적지로 전달할 책임을 갖는다.

2계층은 노드대노드 전달을 감독하는 것이고 3계층은 각 패킷이 시작 시점에서 최종 목적지까지 성공적이고 효과적으로 전달되도록하며, 대표적 프로토콜은 IP이다.

 2계층

 Data link

데이터링크 계층

프로토콜 : MAC, PPP

장비 : 브리지, 스위치

오류없이 한 장치에서 다른 장치로 프레임(Frame, 비트의 모음)을 전달하는 역할

스위치같은 장비의 경우 MAC주소를 이용하여 정확한 장치로 정보 전달

3계층에서 정보를 받아 주소와 제어정보를 시작(헤더)와 끝(테일)에 추가

 1계층

 Physical

물리계층

프로토콜 : Ethernet.RS-232C

장비 : 허브, 리피터

물리적 매체를 통해 비트(Bit)흐름을 전송하기 위해 요구되는 기능들을 조정

케이블, 연결 장치 등과 같은 기본적인 물리적 연결기의 전기적 명세를 정하고 네트워크의 두 노드를 물리적으로 연결시켜 주는 신호방식을 다름 


각 계층별 대표적 프로토콜


 7 Application (응용 계층)

HTTP, SMTP, SNMP, FTP, Telnet, SSH & Scp, NFS, RTSP 

 6 Presentation (표현 계층)

JPEG, MPEG, XDR, ASN.1, SMB, AFP 

 5 Session (세션 계층)

TLS, SSH, ISO 8327 / CCITT X.225, RPC, NetBIOS, AppleTalk 

 4 Transport (전송 계층)

TCP, UDP, RTP, SCTP, SPX, AppleTalk 

 3 Network (네트워크 계층)

IP, ICMP, IGMP, X.25, CLNP, ARP, RARP, BGP, OSPF, RIP, IPX, DDP 

 2 Data link (데이터 링크 계층)

Ethernet, Token Ring, PPP, HDLC, Frame relay, ISDN, ATM, 무선랜, FDDI 

 1 Physical (물리 계층)

전선, 전파, 광섬유, 동축케이블, 도파관, PSTN, Repeater,DSU, CSU, Modem




아래 이미지는 TCP/IP를 좀더 쉽게 설명하기 위해서 7계층의 몇가지 단계를 압축시켜 표현했다고 보시면 됩니다.

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


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

어플리케이션은 게임이라고 생각해 봅시다.

그 아래로 3개의 계층을 통해서 인터넷과 연결된다고 보면 됩니다. 

그리고 이 계층은 다른 호스트에도 존재하는 계층이 됩니다. 즉 컴퓨터 A와 컴퓨터B는 같은 계층을 통해서 서로 데이터를 주고 받고 있는 겁니다.

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



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

소켓의 종류에는 TCP/UDP두가지 종류가 존재합니다.

위의 이미지는 TCP방식의 소켓을 할당했을때 계층의 모델이다. 

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


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

소켓의 종류에는 TCP/UDP두가지 종류가 존재합니다.

위의 이미지는 TCP방식의 소켓을 할당했을때 계층의 모델이다. 

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


각 계층의 역할 --------------------------------------------------------------------------------------------

LINK 계층-------------------------------------------------------------------------------------------------------------------------

LINK 계층은 물리적인 영역을 생각하는게 좋다. 각 컴퓨터와 전산망을 생각하면 된다. 랜선이나 무선회선에 의해서 각 컴퓨터는 연결되고 송수신 되는 데이터는 라우터를 통해서 다른 호스트나 서버에게 전송되게 됩니다.

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

IP계층----------------------------------------------------------------------------------------------------------------------------

IP계층은 LINK계층의 어떤 경로를 이용할 것인가를 표시해준다고 생각하면 된다.

LINK계층이 지도라면 IP계층은 지도라고 보면 된다.

하지만 한가지 알아둬야 할건 지도가 있다고 해서 배달부가 목적지에 잘 도착했는지까지 보장하지는 않는다는 것이다.

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

      TCP가 IP계층에 신뢰성을 부여하는 이유. 간단히 말해서 상대가 패킷을 받았다는 신호를 보내지 않으면 다시 패킷을 보낸다.

TCP UDP계층------------------------------------------------------------------------------------------------------------------------


정리해보기


- TCP 통신 
TCP(Transmission Control Protocol)는 인터넷에서 가장 흔하게 그리고 많이 쓰이는 프로토콜 방식이다. 그 이유는 TCP통신은 error correction이라는게 존재하는데 말 그대로 에러를 다시 잡아주는 것이다. 서버에서 클라이언트에게 어떤 정보를 보냈다고 하자! 그러면 클라이언트는 서버가 보낸 정보를 제대로 받았는지, 확인해주는 메세지를 다시 서버에게 돌려주고, 클라이언트가 제대로 받지 못했을 경우엔 resend를 서버에 요청 할 수 있다. 그러면 loss된 데이터를 다시 클라이언트에게 보낼 수 있는 것이다. 이런 방법들을 flow control이라고 하며, 오리지널 데이터를 로스 하지 않고 받을 수 있게 한다. 즉, guaranteed delivery!

* IP계층은 데이터의 송수신결과를 보장하지 않는다. 하지만 TCP통신이란 서로간의 확인을 통해서 IP계층의 데이터입출력에 신뢰성을 부여한 프로토콜 모델이라고 생각하면 된다.

- UDP 통신
UDP(User Datagram Protocol) 은 인터넷에서 또 많이 쓰이는 프로토콜인데 그 사용처는 tcp 통신과는 다르다. tcp통신과의 가장 큰 차이는 단방향 통신이라는것! 서버가 클라이언트에게 혹은 클라이언트가 서버에게! error correction이 없고, 무조건 보내는 쪽에선 던지기만 하고 받는 쪽에선 받기만 한다. 그러다가 데이터 로스가 중간에서 발생하면 어쩌냐? 무시한다. 그냥 던지고 받는거다 ! 이렇게 되면 장점은 TCP통신 보다는 훨씬 빠른 전송을 보여주게 된다. 

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


Posted by JJOREG

// 윈도우 기반이고 함수가 리눅스와 거의 동일함으로 예체를 치고 주석을 첨부하는 식으로 구성한다.


인터넷 주소 할당 ------------


#include <stdio.h>

#include <string.h>

#include <winsock2.h>

void ErrorHandling(char* message);


int main(int argc, char *argv[])

{

WSADATA wsaData;

if( WSAStartup( MAKEWORK(2, 2), &wsaData ) != 0 ) -> 소켓의 버전 생성 및 wsaData 초기화

ErrorHandling( "WSAStartup() error!" );


char *addr = "127.212.124.78";

unsigned long conv_addr = inet_addr(addr); -> 문자열 주소를 빅에디안으로 변환된 32비트형 정수형 주소로 변환한다.

if(conv_addr == INADDR_NONE) 

printf( "Error occured! \n" );

else

printf( "Network orddered integer addr : %#1x \n", conv_addr );

}


// 주소 구조체를 현재 PC에 맞춰서 주소를 넣는다.

{

struct sockaddr_in addr; -> 귀찮은 주소변환을 위해서 할당하는 구조체

char *strPtr;

char strArr[20];


addr.sin_addr.s_addr = htonl( 0x1020304 ); 

strPtr = inet_ntoa(addr.sin_addr);

strcpy(strArr, strPtr);

printf( "Dotted-Decimal notation3 %s \n", strArr );

}


WSACleanup();


return 0;

}


void ErrorHandling( char* message )

{

fputs(message, stderr);

fputc('\n', stderr);

exit(1);

}


소켓에 주소 할당하기 ------------


SOCKET servSock;

struct sockaddr_in servAddr;

char *servPort = "9190";


// 소켓 생성

servSock = socket( PF_INET, SOCK_STREAM, 0 );


// 주소 정보 초기화

memset( &servAddr, 0, sizeof(servAddr) );

servAddr.sin_family = AF_INET;

servAddr.sin_addr.s_addr = htonl( INADDR_ANY );

servAddr.sin_port = htons( atoi(servPort) );


// 주소 할당

bind(servSock, (struct sockaddr*)&servAddr, sizeof(servAddr)  );


윈도우 운영체제용 주소 변환함수(윈도우에서만 사용가능 편하지만 범용성이 없다고 생각하자.) ------------


// 이 함수는 주소정보를 나타내는 문자열을 가지고 주소정보 구조체 변수를 적절히 채워 넣을 때 호출하는 함수이다.

INT WSAAPI WSAStringToAddress( _In_      LPTSTR AddressString, -> IP와 PORT번호를 담고 있는 문자열의 주소값 _In_      INT AddressFamily, -> 첫 번째 인자로 전달된 주소정보가 속하는 주소체계 정보전달. _In_opt_  LPWSAPROTOCOL_INFO lpProtocolInfo, -> 프로토콜 프로바이더(Provider) 설정, 일반적으로 NULL전달 _Out_     LPSOCKADDR lpAddress, -> 주소 정보를 담을 구조체 변수의 주소 값 전달 _Inout_   LPINT lpAddressLength -> 네 번째 인자로 전달된 주소 값의 변수 크기를 담고 있는 변수의 주소 값 );


// 구조체 변수에 저장된 데이터를 참조하여 주소정보를 담고 있는 문자열을 만들어서 반환한다.

INT WSAAPI WSAAddressToString( _In_      LPSOCKADDR lpsaAddress, -> 문자열로 변환할 주소정보를 지니는 구조체 변수의 주소 값 전달 _In_      DWORD dwAddressLength, -> 첫번째 인자로 전달된 구조체 변수의 크기 전달 _In_opt_  LPWSAPROTOCOL_INFO lpProtocolInfo, -> 프로토콜 프로바이더(Provider) 설정, 일반적으로 NULL전달 _Inout_   LPTSTR lpszAddressString, -> 문자열로 변환된 결과를 저장할 배열의 주소 값 전달 _Inout_   LPDWORD lpdwAddressStringLength -> 네 번째 인자로 전달된 주소 값의 배열 크기를 담고 있는 변수의 주소 값 전달 );



Posted by JJOREG

// 대부분의 설명은 리눅스를 기초로 해서 쓰여지나 windows와도 거의 차이가 없다.


일단 소켓 함수를 확실히 확인해보자.

SOCKET socket(

  _In_  int af, -> 소켓이 사용할 프로토콜 체계 

  _In_  int type, -> 소켓의 타입

  _In_  int protocol -> 프로토콜 체계중 실제적으로 상요할 프로토콜

);


프로토콜? ---------------------------------------------------------------------------------------------------------

프로토콜이란 컴퓨터 상호간에 필요한 통식규약이다. 신호를 보내는 방법부터 이런런 식으로 신호를 보낸다고 미리 약속해 놓은 규약이다.


// 프로토콜의 체계

■ 소켓 생성 시 사용되는 인자 도메인은 PF_INET과 AF_INET이 있다.
- PF_INET는 프로토콜 체계(프로토콜 패밀리)중 하나이고, AF_INET는 주소 체계(주소 패밀리)중 하나이다.

(1) PF_INET 프로토콜 체계

 프로토콜 체계(Protocol Family)  정의
 PF_INET IPv4인터넷 프로토콜
 PF_INET6 IPv6인터넷 프로토콜
 PF_LOCAL LOCAL 통신을 위한 UNIX 프로토콜
 PF_PACKET Low level socket을 위한 인터페이스
 PF_IPX IPX 노벨 프로토콜

소켓을 만들 때는 소켓이 사용될 환경을 고려해 프로토콜을 설정해 줘야 한다.
다시 말해 프로토콜 패밀리는 소켓을 생성할 때 이 소켓이 어떤 프로토콜을 사용해 통신을 할지 정한다.
참고로 소켓은 네트워크 통신을 할때만 사용되는 것이 아니다.
유닉스 계열의 시스템에서 시스템 내부의 프로세스들끼리 통신을 하기 위해서도 사용된다. 
자주 사용되는 PF_INET는 프로토콜 패밀리중 하나이다. 

(2) AF_INET 주소 체계

 주소체계(Address Family) 정의
 AF_INET  IPv4인터넷 프로토콜
 AF_INET6  IPv6인터넷 프로토콜
 AF_LOCAL  LOCAL 통신을 위한 UNIX 프로토콜

이 들은 주소 구조체 안에 주소 패밀리를 정의할 때 사용한다.
프로토콜 체계를 나타내는 PF_INET와 주소체계를 나타내는 AF_INET 는 같은 상수 값을 가지고 있다.
그렇다고 해서 주소정보를 설정하는 부분에 PF_INET를 사용하고 프로토콜 패밀리 정보를 설정하는 부분에 AF_INET를 넣는 것은 좋지 않다.

결과적으로, 프로토콜 체계를 설정하는 부분은 PF로 시작하는 상수를 사용하고, 주소 체계를 설정하는 부분은 AF로 시작하는 상수를  사용하는 것이 좋다.

실제 코딩 부분에서 socket()함수에 프로토콜 패밀리에 AF_INET를 넣어도 되지만 PF_INET를 넣는게 바람직하고,
struct sockaddr_in 구조체에 주소 체계를 넣을 때에도 PF_INET 를 넣어도 되지만 AF_INET를 넣는게 바람직하다.

소켓의 타입 ------------------------------------------------------------------------------------------------------

소켓의 타입에는 2가지가 존재한다.


1. 연결 지향형 소켓 

SOCK_STREAM(TCP 소켓을 할당할때 상요되는 인자값.)

* 소켓과 소켓이 계속 연결되어있는 상태를 유지한다.

* 연결지향형 소켓의 특징은 소켓과 소켓의 연결은 1 vs 1이다.

* 신뢰성 있는 순차적인 바이트 기반의 연결지향 데이터 전송 방식의 소켓

// 추가적으로 이해해야할 부분


2. 비 연결 지향형 소켓 

SOCK_DGRAM (UDP 소켓을 할당할때 사용되는 인자값.)

* 소켓이 특정 주소로 메세지를 보내고 다른 한 소켓은 연셜상태 관련없이 메세지가 오면 받기만 하면 된다.

* 즉 주소로 보내기만 할 뿐이지 데이터의 파손이나 분실에 대해서는 체크할 수 없다.

* 전송되는 데이터의 경계가 존재한다.

* 한번에 전송 할 수 있는 데이터의 크기가 제한 된다.

// 추가적으로 이해해야할 부분


프로토콜 최종결정 --------------------------------------------------------------------------------------------------

어떤 체계를 사용할지도 결정했고 어떤 연결 방식을 사용할지도 결정했다. 그렇다면 다음으로 진짜 사용할 프로토콜의 종류를 결정해야할 때다. 간단한 몇가지 인자값을 보도록하자.


* 윈도우 환경에서 C언어의 ENUM 값으로 지정된 인자값이라는 것을 유념하고 본다.

    IPPROTO_HOPOPTS       = 0,  // IPv6 Hop-by-Hop options 자동으로 앞의 인자값을 기준으로 결정해주는것 같다..

    IPPROTO_ICMP          = 1,

    IPPROTO_IGMP          = 2,

    IPPROTO_GGP           = 3,

    IPPROTO_IPV4          = 4,

    IPPROTO_ST            = 5,

    IPPROTO_TCP           = 6, -> TCP가 보인다.

    IPPROTO_CBT           = 7,

    IPPROTO_EGP           = 8,

    IPPROTO_IGP           = 9,

    IPPROTO_PUP           = 12,

    IPPROTO_UDP           = 17, -> UDP 요있네.

    IPPROTO_IDP           = 22,

    IPPROTO_RDP           = 27,

    IPPROTO_IPV6          = 41, // IPv6 header

    IPPROTO_ROUTING       = 43, // IPv6 Routing header

    IPPROTO_FRAGMENT      = 44, // IPv6 fragmentation header

    IPPROTO_ESP           = 50, // encapsulating security payload

    IPPROTO_AH            = 51, // authentication header

    IPPROTO_ICMPV6        = 58, // ICMPv6

    IPPROTO_NONE          = 59, // IPv6 no next header

    IPPROTO_DSTOPTS       = 60, // IPv6 Destination options

    IPPROTO_ND            = 77,

    IPPROTO_ICLFXBM       = 78,

    IPPROTO_PIM           = 103,

    IPPROTO_PGM           = 113,

    IPPROTO_L2TP          = 115,

    IPPROTO_SCTP          = 132,

    IPPROTO_RAW           = 255,

    IPPROTO_MAX           = 256,

    IPPROTO_RESERVED_RAW  = 257,

    IPPROTO_RESERVED_IPSEC  = 258,

    IPPROTO_RESERVED_IPSECOFFLOAD  = 259,

    IPPROTO_RESERVED_MAX  = 260


함수를 채워보자 --------------------------------------------------------------------------------------------------


SOCKET socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

IPv4 인터넷 프로토콜 체계에서 동작하는 연결지향형 TCP 소켓을 생성하여 반환하라.


SOCKET socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);

IPv4 인터넷 프로토콜 체계에서 동작하는 비 연결지향형 UDP 소켓을 생성하여 반환하라.




소켓에 할당되는 IP주소 ---------------------------------------------------------------------------------------------


1. IP주소 : 라우터(정확히 말하면 물리적인 회선이라고 이해하는 편이 빠를듯 하다. 컴퓨터에 꼽는 랜, 혹은 허브 등에)에 부여되는 주소.

2. 프로토콜 주소 : 프로그램상에서 생성되는 소켓을 구분하기 위해 소켓에 부여되는 번호.


IP주소의 체계

* IPV4( Internet Protocol version 4 ) 4바이트 주소 체계 (우리가 일반적으로 알고 있는 255.162.42.182 같은 형식)

* IPV4( Internet Protocol version 6 ) 16바이트 주소 체계


라우터와 스위치 --------------------------------------------------------------------------------------------------

네트워크를 구성하려면 물리적인 장치가 필요하다. 여기서 물리적인 장치란 LEN카드 같은 것을 생각해 보면 편하다. 선이 연결되어 있거나 무선으로 전파를 송수신 할 수 있는 물리적인 무언가가 있어야만 우리는 네트워크를 이용할 수가 있다.

IP주소란 그런 라우터나 혹은 스위치에 할당되는 주소라고 이해한다면 편 할 것이다.


PORT번호 ------------------------------------------------------------------------------------------------------


IP주소로 내 컴퓨터의 주소는 부여됐다 PORT번호는 이렇게 생각해보자.

RPG게임 하나와 FPS게임 하나를 동시에 켰다. 둘은 모두 네트워크 게임이기 때문에 양쪽을 하나의 컴퓨터에게 동시에 켜고 동시에 접속했다.

이 녀석들은 하나의 소켓으로 한번에 데이터를 다 받을까? 아니다.

RPG는 RPG의 소켓을 가지고 FPS는 FPS의 소켓을 가진다.

물론 IP주소로는 모든 데이터가 하나가 되어 컴퓨터에 전송된다. 하지만 전송된 데이터는 RPG와 FPS의 데이터 정보를 모두 가지고 있으므로 적절한 분배가 필요하다.

****(여기까지는 하드웨어적인 신호라고 생각하자.)


컴퓨터에는 NIC(네트워크 인터페이스 카드)라고 불리는 데이터 송수신 장치가 하나씩 달려있는데.

이 녀석의 역할은 물리적인 장치로 송신된 데이터를 컴퓨터의 내부의 데이터로 직접 전송시켜 주게 된다. 

****(여기까지는 운영체제에 데이터를 넘긴다고 생각하자.)


이때 이 데이터안에는 PORT번호가 새겨져 있고, 데이터를 전송받은 컴퓨터의 내부의 운영체제에서 PORT번호를 이용하여 데이터를 분배하여 RPG와 FPS의 네트워크 데이터를 전달해 주게 된다.

****(운영체제가 각각 RPG와 FPS에 데이터를 분배한다.)


주소정보의 표현 ---------------------------------------------------------------------------------------------------

종합적으로보면 하나의 소켓통신을 하기위한 주소는 다음의 정보를 가져야 한다.

1. 주소체계

2. IP주소

3. PORT주소


소켓통시네서 각기 따로 입력되는 것이 아니라. 다음의 구조체를 통해서 하나의 정보로서 묶여있다.


struct sockaddr_in

{

sa_family_t           sin_family;     //주소체계

uint16_t                sin_port;       //16비트 PORT주소

struct in_addr       sin_addr       //32비트 IP주소

char                    sin_szro[8]  //사용되지 않는 여분의 공간

}

// ip주소는 구조체로 전체 주소를 위한 구조체 안에 포함되어있다.

struct in_addr

{

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

}


하지만 이 주소정보 구조체는 본래 이런 모양이 아니라 다음과 같은 구조체로 정의되어 있었다.

struct sockaddr

{

sa_family_t           sin_family;     // 주소체계

char                    sa_data[14]; // 주소 정보

}


2가지 구조체가 있는 이유는 의외로 단순하다. 주소는 모든 정보를 요구하고 마지막에는 8바이트의 0으로 채워진 공간을 요구하는데.

sockaddr구조체에 그런 정보를 넣기가 매우 불편하기 때문에 sockaddr_in 구조체로 좀더 손쉽게 주소를 넣게 해준 것이다.


리틀에디안 빅 에디안 -----------------------------------------------------------------------------------------------

네트워크주소는 CPU에 바이트 순서로 저장되는데 CPU마다 바이트순서를 저장하는 방식이 달라. 애써 입력한 주소가 제대로 기능하지 못하는 경우가 있다. 설명하자면 아래 그림과 같다.





그래서 통신규약으로는 보내지는 정보는 모두 빅에디안으로 보내도록 되어있다.

하지만 리틀에디안으로 정보를 처리하는 CPU에는 빅에디안 정보는 제대로 전송되지 않기 때문에 다음과 같은 함수를 통해서 변환 작업을 거친다.


htons(short s) -> short데이터를 호스트의 바이트 순서에서 네트워크 바이트 순서로 변환해라.

ntohs(short s) -> short데이터를 네트워크 바이트 순서에서 호스트 바이트 순서로 변환해라.


htonl(long s) -> long데이터를 호스트의 바이트 순서에서 네트워크 바이트 순서로 변환해라.

ntohl(long s) -> long데이터를 네트워크 바이트 순서에서 호스트 바이트 순서로 변환해라.


자신의 CPU가 리틀에디안이건 빅에디안이건 어느 컴퓨터에서나 돌아갈 수 있도록 이변환을 이용해 주는 것이 좋다.


인터넷 주소의 초기화와 할당 -----------------------------------------------------------------------------------------

네트워크 바이트 순서의 정수로 변환하는 역할.
sockaddr_in안에서 주소정보를 저장하기 위한 멤버는 32비트 정수형으로 정의되어 있다. 하지만 실제 구조체를 받아들일때는 
주소 정보 같은 문자열 주소를 사용하며 당연히 이를 변환해주기 위한 변수도 존재한다.

inet_addr ------------------------
inet_addr(const char* string );
성공시 빅에디안으로 변환된 32비트 정수 값, 실패시 INADDR_NONE 반환.

이 함수를 제외하고 다음과 같은 함수도 존재하지만 인자 값으로 in_addr을 하나 더 받는다.
inet_aton ------------------------
inet_aton(const char* string in_addr);
성공시 (true) 실패시 (false 반환)

반대로 구조체 안에 있는 정보를 다시 문자열 형으로 변환해주는 기능을 하는 함수도 존재한다.
inet_ntoa ------------------------
inet_ntoa(struct in_addr adr
성공시 변환된 문자열의 주소값 실패시 -1 반환

인터넷 주소의 초기화의 실제 코드 ------------------------------------------------------------------------------------
그럼 함수들을 이용하여 주소값을 초기화하는 코드를 작성해본다.

struct socketaddr_in addr;
char *serv_ip="211.217.168.13";
char *serv_port="9190";
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(serv_ip);
addr.sin_port = htons(atoi(serv_port));

소켓에 인터넷 주고 할당하기 ------------------------------------------------------------------------------------
소켓에 인터넷 주소를 할당하기 위해서는 다음과 같은 함수가 필요하다.
int bind(int sockfd, struct sockaddr *myaddr, socklen_t addrlen);
int sockfd -> 주소 정보를 (IP와 PORT를) 할당할 소켓의 파일 디스크럽터.
struct sockaddr *myaddr 할당하고자 하는 주소정보를 지니는 구조체 변수의 주소값.
socklen_t addrlen 두번째 인자로 전달된 구조체 변수의 길이정보


Posted by JJOREG

소켓이란 무엇인가? -------------------------------------------------------------------------------------------

소켓이란 멀리있는 대상과 나를 연결해주는 통로 같은 존재. 전화기 같은 존재이다.

전화기로 통화를 하려면 상대의 전화번호를 알아야 하는 것처럼 소켓으로 컴퓨터간 네트워크 교류를 하려면 서로간의 IP주소를 알아야 한다.

위의 명령어는 연결을 요청하는 함수와 그 헤더파일이다.

위의 명령어는 연결요청을 수락한다는 함수이다.

  이와 같이 소켓 프로그래밍도 어려울것이 없다.

  전화기를 한대 구입하고, 전화번호를 할당한다음, 전화를 케이블에 연결하고, 전화를 기다리다가, 전화가 오면 전화기를 받고 대화를 하는 것이라고 보면 된다.


클라이언트? 서버? -------------------------------------------------------------------------------------------

일단 클라이언트와 서버의 기본적인 개념부터 이해해본다.

클라이언트란 여러분이 직접 플레이를 하고 있는 컴퓨터라고 보면 된다.

반대로 서버란? 여러분이 접속을 요청하는 게임회사에 존재하는 커다란 컴퓨터라고 보면된다.

일반적으로 클라이언트 쪽에서 대부분의 연락을 취한다.

게임 접속하겠습니다. 공격하겠습니다. 아이템 구매하겠습니다. 이동하겠습니다. 대부분의 요청을 클라이언트에서 요청하고 서버에서는 그것을 받아서 현재 클라이언트에 존재하는 객체의 값을 기록하거나 데이터를 변경하는 역할을 한다.


파일 입출력 -------------------------------------------------------------------------------------------

서버에서는 요청에 대한 대상을 파일로 간주하는 경우가 많다. 리눅스 기반이건 윈도우즈 기반이건 이는 다르지 않으며 시스템 수준에서 이러한 파일 입출력 조작함수를 지원한다.

리눅스에서는 이것을 파일디스립터라고 부르며 윈도우에서는 핸들이라고 부른다. 핸들은 윈도우즈 시스템 프로그래밍을 읽어본 나로서는 이해가 가는 부분이며 리눅스에서는 그것을 파일디스크립터라고 부른다고 이해하기로 했다. 즉 클라이언트에서는 항상 서버에게 이런 요청을 한다고 보면 된다.

내 파일(혹은 소켓)의 XX줄의 XX번부터 XX번까지를 참조해줘. 복사해줘....

당연히 이런 파일을 조작하기 위해서는 파일에 접근할수 있어야 하고 접근한다는 것은 그 파일을 열어서 조작한다는 것을 의미한다.

이런 명령어를사용해서 파일을 열어서 조작하여 클라이언트에 변화를 주는 것이다.

path 는 당연히 파일의 경로를 의미한다. 파일의 경로를 모르면 어떤 파일에 접근할지 알수가 없기 때문이다.

두번째로 flag는 파일의 모드를 의미한다.

방금 말했던대로 윈도우에서는 핸들이라고 하고 리눅스에서는 소켓 혹은 파일이라고 지칭했다. 윈도우에서 커널오브젝트나 핸들은 사용후엔느 닫아줘야 했다. 어느 시스템이건 이는 공통적으로 적용된다.

열고 닫는 함수가 있다면 당연히 쓰기 위한 함수도 있을 것이다.

fildes 데이터의 전송 영역을 나타내는 파일스크립터

buf 전송할 데이터를 가지고 있는 버퍼의 포인터

nbytes 전송할 바이트 수를 의미한다.

쓰는 함수가 있다면? 당연히 읽는 함수도 존재한다.

fildes 데이터의 전송해 주는 대상을 가리키는 파일스크립터

buf 수신 한 데이터를 저장할 버퍼를 가리키는 포인터

nbytes 수신할할 바이트 수를 의미한다.

여기까지는 리눅스 기반 일반적인 소켓과 파일 함수였다면 이번에는 윈도우즈의 소켓에 대해서 알아보자.


윈도우즈 소켓 기본 함수 및 프로그래밍 --------------------------------------------------------------------------

일단 알아두어야 할것이. 윈도우즈 소켓은 상당부분 BSD 계열 유닉스 소켓을 참고로 설계되어 있다는 것이다. 따라서 대다수의 부분이 리눅스 기반 소켓과 유사하다.

관련 함수
-------------------------------------------------------
1. 소켓을 생성하는 함수

SOCKET socket(int af, int type, int protocol);

성공시 소켓 핸들을 반환한다. 실패시 INVALID_SOCKET를 반환한다.

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

2. IP주소와 PORT번호의 할당을 목적으로 호출하는 함수  

int bind(SOCKET s, cosnt struct sockaddr* name, int namelen);

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

3. 소켓이 클라이언트의 프로그램의 연요청을 받아들일 수 있는 상태가 되게 하는 것을 목적으로 호출되는 함수.

int listen(SOCKET s, int backlog);

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

4. 클라이언트 프로그램에서 연결요청을 수락할때 호출하는 함수.

SOCKET accept(SOCKET s, cosnt struct sockaddr* addrint addrlen);

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

5. 클라이언트 프로그램에서 소켓을 기반으로 연결요청연결 요청을 할때 호출하는 함수

int connect(SOCKET s, cosnt struct sockaddr* name, int namelen);

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

6. 소켓을 닫을때 사용하는 함수

INT closesoket(SOKET s);


소켓 과 핸들 ------------------------------------------------------------------------------------------------

윈도우에서는 시스템 함수의 호출을 통해서 파일을 생성할때 핸들을 반환한다. 윈도우는 리눅스와는 달리 파일 핸들과 소켓 핸들을 구분하고 있으며 핸들이라는 관점에서 바라볼 때는 동일하다고 바라볼수 있지만. 완벽하게 동일하지 않다.


윈도우 기반 입출력 함수 --------------------------------------------------------------------------

-------------------------------------------------------
1. 데이터 전송 함수

int send(SOCKET s, cosnt char * buf, int len, int flags);

s : 데이터 전송 대상과의 연결을 의미하는 소켓의 핸들 값 전달.

buf : 전송할 데이터를 저장하고 있는 버퍼의 주소 값 전달.

len : 전송할 바이트 수 전달.

flags : 데이터 전송 시 적용할 다양한 옵션 정보 전달.

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

2. 데이터 수신 함수

int bind(SOCKET s, cosnt struct sockaddr* name, int namelen);

s : 데이터 수신 대상과의 연결을 의미하는 소켓의 핸들 값 전달.

buf : 수신된 데이터를 저장할 버퍼의 주소 값 전달.

len : 수신할 수 있는 최대 바이트 수 전달.

flags : 데이터 수신시 적용할 다양한 옵션 정보 전달.

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

Posted by JJOREG
이전버튼 1 2 이전버튼