바이트 순서


CPU 종류 마다 데이터를 저장하는 방법이 다르다.

CPU는 데이터를 메모리에 저장을 한다. 

CPU 마다 데이터 순서를 순방향, 역방향 두 가지 방식으로 저장한다.

순방향 => 빅 엔디안   ( Big Endian )

역방향 => 리틀 엔디안( Little Endian )

사실 순방향, 역방향 이라는 말은 없다. 

설명하기 쉽게 하려고 필자가 만든말이니

이글을 읽는 분은 (빅,리틀) 엔디안만 기억해주기 바란다.


2진수 표현식으로 알아보는 바이트 순서


바이트 순서를 말하기 앞서 바이트가 뭔지 알아야 한다.

1byte = 8bit 이다.  1bit는 0과 1로 구성 되어 있다.

1byte는 00000000 이렇게 표현 가능하다.

정수는 4byte이다. 정수를 bit로 표현하면 다음과 같다.

00000000 00000000 00000000 00000000

정수1은 다음과 같이 표현이 가능하다.

00000000 00000000 00000000 00000001

이우리는 정수1이 CPU마다 어떻게 저장 되는지 알아보겠다.


 Big Endian

 Little Endian 

 00000000 00000000 00000000 00000001

 00000001 00000000 00000000 00000000

 순방향, 읽기 좋은 방향

 역방향, 읽는 순서가 바뀐 방향



메모리 저장 방식으로 알아보는 바이트 순서


CPU 가 메모리에 저장하는 순서를 알아보겠다.

'abcd' 를 저장하는 예를 들어보겠다.

영문은 1byte의 공간을 차지 한다. 메모리 한 블록당 1byte씩 저장한다고 가정 한다.



[BIG Endian]


 a

 b

 c

 d




[Little Endian]


 d

 c

 b

 a




메모리 주소와 바이트 순서

한가지 예를 더 들도록 하겠다. 이번 예는 좀 더 어렵다.

메모리 0x01번지를 시작하는 4바이트 int 정수 0x12345678을 넣도록 하겠다.


4바이트이기 때문에 메모리는 다음과 같은 번지수를 사용한다.


 0x01

 0x02

 0x03

 0x04

작은 번지 수에서 큰 번지수 값을 가진다.


그럼 정수 0x12345678의 최상위 바이트는 0x12이며 최하위 바이트는 0x78이다.


 빅 엔디안   ( Big Endian )

  상위 바이트 값을 작은 번지수에 저장

 리틀 엔디안( Little Endian )

  상위 바이트 값을 큰 번지수에 저장   



[BIG Endian]


  0x01

 0x02

  0x03

  0x04

  0x12

 0x34

  0x56

  0x78



[Little Endian]


  0x01

  0x02

  0x03

  0x04

  0x78

  0x56  0x34  0x12



메모리 저장 순서로 인한 송수신 문제와 해결방법


A,B라고 불리는 두 개의 시스템이 있다. 

서로 데이터를 송수신을 하는 프로그램을 구축했다.

하지만 각각 시스템은 서로 다른 CPU를 사용하여 바이트 저장 순서가 다르다.

그래서 데이터를 송신하면 받는 쪽에서 처리가 불가능 하다.


A시스템에서 0x12, 0x34라고 보냈다. 

B시스템은 0x34, 0x12라고 해석하여 개발자가 의도한데로 동작을 하지 않는다.


[해결방법]

네트워크를 통해 전송할 때는 빅 엔디안 방식으로 통일해서 보낸다.

내 CPU와 상관없이 무조건 송신하기 전에는 빅엔디안으로 보내고 받는쪽에서는 빅엔디안에서 받는쪽 CPU에 맞는 바이트 순서로 바꾼다.



마무리

위에 내용을 자세히 몰라도 프로그램 개발 하는데 지장은 없다.

네트워크를 통해 전송 할 때는 빅 엔디안으로 통일한다는 것만 기억한다.

많은 언어가 비슷한 함수명을 사용하는데 바로 ntoh, hton... 와 같은 이름을 갖은 함수들이다.

송신 전 빅엔디안으로 변환, 수신 후 빅엔디안을 수신쪽 CPU에 맞는 바이트 순서로 바꾸는 함수라 생각하면 된다.





반응형

프로토콜 체계와 소켓 타입(TCP/UDP)


네트워크 프로그램을 할 때 가장 핵심이 되는 것이 소켓이다.

수년 전에도 지금도 socket을 이용하여 컴퓨터, 각종 디바이스( 핸드폰, 테블릿 등)와 데이터를 송수신을 한다.

이런 socket을 생성할 때 2가지 중요한 정보를 입력 하는데 그것이 바로 프로토콜 체계와 소켓을 타입이다.

오늘은 두 가지 중요한 정보에 대해 설명 하도록 하겠다. 


프로토콜 체계


포로토콜(protocol)이란 컴퓨터 간에 데이터를 주고 받는 방식이다.

즉 각 컴퓨터 간 서로 데이터를 주고 받기 위해서 정의해 놓는 약속을 뜻한다.

이러한 규약을 정해 놓지 않으면 내가 의도한 것과 다르게 상대 컴퓨터에서 이해를 다르게 할 수 있다.


소켓 통신을 할 때 사용하는 프로토콜 부류가 몇가지 있다. 

이러한 부류를 프로토콜 체계라고 하며 c에서 소켓을 생성 할 때 다음과 같이 함수를 호출 할 때 첫 번째 인자에 프로토콜 부류를 넣는다.


#include <sys/socket.h>

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


프로토콜 부류 종류는 아래와 같다.

 이름

프로토콜 체계(Protocol Family) 

 PF_INET     IPv4 인터넷 프로토콜 체계

 PF_INET6

 IPv6 인터넷 프로토콜 체계 

 PF_LOCAL

 로컬 통신을 위한 UNIX 프로토콜 체계 

 PF_PACKET

 Low Level 소켓을 위한 프로토콜 체계 

 PF_IPX

 IPX 노벨 프로토콜 체계 



주소 체계


C에서는 소켓을 생성 후 bind나 connect 할 때 주소 구조체에 주소 체계를 넣어 준다.

Python에서는 프로토콜 체계를 넣지 않고 아래 처럼 주소 체계만 넣어 준다.


serverSocket = socket(AF_INET, SOCK_STREAM)


주소 체계의 종류는 다음과 같다.



 이름

주소 체계(Address Family) 

 AF_INET     IPv4 인터넷 프로토콜 체계

 AF_INET6

 IPv6 인터넷 프로토콜 체계 

 AF_LOCAL

 로컬 통신을 위한 UNIX 프로토콜 체계 



소켓 타입(TCP/UDP)


소켓 타입은 데이터 전송 방식을 의미 하며 socket 함수 호출 시 2번 째 인자에 값을 넣는다.


[C 예제]

#include <sys/socket.h>

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


[Python 예제]

serverSocket = socket(AF_INET, SOCK_STREAM)


대표적인 소켓의 타입은 아래와 같다.


 TCP

 UDP

 연결 지향형 소켓

 비 연결 지향형 소켓 

 SOCK_STREM

 SOCK_DGRAM 

 데이터 손실 없이 목적지로 전송

 데이터 손실 우려가 있다. 

 전송 순서대로 데이터가 수신 된다.

 전송된 순서에 상관없이 가장 빠른 전송 지향 

 데이터 경계 없음

 데이터 경계 존재 




반응형

파이썬을 이용한 네트워크 프로그래밍



 파이썬을 이용한 서버 개발                                                                              


파이썬을 이용해서 네트워크 프로그래밍을 예제를 설명 하도록 하겠다.

네트워크 개념이 없으신 분은 여기를 클릭하여 먼저 이해를 하는것이 좋습니다.

파이썬 서버 개발 예제부터 살펴 보겠다.


#! /usr/bin/python

# -*- coding: utf-8 -*-


from socket import *

from select import *

import sys

from time import ctime


HOST = ''

PORT = 10000

BUFSIZE = 1024

ADDR = (HOST,PORT)


serverSocket = socket(AF_INET, SOCK_STREAM)#1.소켓을 생성한다.


serverSocket.bind(ADDR) #2.소켓 주소 정보 할당

print('bind')

serverSocket.listen(100) #3.연결 수신 대기 상태

print('listen')

clientSocket, addr_info = serverSocket.accept() #4.연결 수락

print('accept')

clientSocket.close() #소켓 종료

serverSocket.close()

print('close')


1. 시작은 소켓을 생성하는 것으로 부터 시작 한다. serverSocket은 이제 socket 클래스의 인스턴스이다.

2. bind 함수를 호출 하여 주소 정보인 ADDR을 할당 한다.

3. listen 함수를 호출하여 연결 수신 대기 상태를 만든다.

4. 클라이언트가 연결을 하면 accept 함수를 이용하여 연결을 수락한다.

   이때 연결을 수락하면서 연결 클라이언트와 송수신을 하는 소켓(clientSocket)을 하나 리턴 받는다.

5. close함수를 호출하여 바로 종료 시킨다.




파이썬을 이용한 클라이언트 개발


파이썬 클라이언트 개발 예제부터 살펴 보겠다.

참고로 클라이언트 프로그램을 다 만들고 실행하기 전에는 서버 프로그램을 먼저 실행 시킵니다. 


#! /usr/bin/python

# -*- coding: utf-8 -*-


from socket import *

from select import *

import sys

from time import ctime


HOST = '127.0.0.1'

PORT = 10000

BUFSIZE = 1024

ADDR = (HOST,PORT)


clientSocket = socket(AF_INET, SOCK_STREAM)#1 서버에 접속하기 위한 소켓을 생성한다.


try:

        clientSocket.connect(ADDR)#2. 서버에 접속을 시도한다.

except  Exception as e:

        print('%s:%s'%ADDR)

        sys.exit()

print('connect is success')


1. 시작은 소켓을 생성하는 것으로 부터 시작 한다. clientSocket은 이제 socket 클래스의 인스턴스이다.

2. connect 함수를 호출하여 서버 접속을 시도한다.


파이썬으로 네트워크 프로그래밍을 할 때는 네트워크 프로그래밍 개념과 더불어 파이썬에서 제공하는 socket 클래스를 이해하면

어렵지 않게 프로그램을 만들수 있습니다.


반응형

네트워크 프로그래밍의 이해 2



소켓 연결 과정


두개의 컴퓨터가 어떻게 연결이 되는지 하나하나 설명 하도록 하겠다.

모든 네트워크 프로그램 개념은 동일 하다.

네트워크 프로그램을 만들 때 언제나 Server와 Client가 짝을 이루어 만들어야 한다.

일단 Server가 하는일 부터 설명 하겠다.


1. socket을 생성한다.

   모든 프로그램이 소켓을 생성하는 함수가 있다 보통 함수명은 socket 이며 언어 마다 이름은 다를 수 있지만 반드시 존재한다.

2. 소켓에 주소정보 할당

   우리가 누구에게 전화를 하려면 고유한 전화번호를 알고 있어야 한다.

   그와 마찬가지로 어떤 컴퓨터가 내 컴퓨터를 접속 하려고 하면 내 컴퓨터 주소를 알아야 하며 그 주소를 할당해 주는 작업이 필요하다.

   이런 함수를 bind라 하며 거의 모든 프로그램 언어가 비슷한 명을 사용한다. ( 컴퓨터의 주소 체계는 앞에서 설명 하였다. )

3. 연결 수신 대기 상태

   client가 연결을 시도하면 받을 수 있도록 해당 소켓을 listen 소켓으로 설정한다.

   이렇게 listen 상태로 바꾸는 함수는 대부분 listen이라는 이름을 갖고 있는 함수를 사용한다.


4. client의 연결 시도

   서버가 연결을 받을 준비가 되어 있으므로 클라이언트에서는 서버에 연결을 시도한다.

   이때 클라이언트는 connect 함수를 사용하며 위에서 서버 소켓을 설정할 때 입력 했던 IP, PORT를 입력 한다.

5. 연결 수락

    client가 연결을 요청하면 server에서는 수락을 하여야 한다.

    여기서 수락하는 함수 명은 accept이며 수락과 동시에 또하나의 소켓이 생성 된다.

    listen으로 설정된 소켓은 또 다른 client의 연결을 받기위해 계속 대기 해야 하기 때문이다.


이렇게 연결이 완료되면 데이터 송수신을 할 수 있다.

다음이 위의 그림까지 python을 이용하여 프로그래밍을 해보도록 하겠습니다.

   


   








반응형

+ Recent posts