[Full-Stack Network] 4. Socket

Cherish·2023년 10월 13일
0
post-thumbnail
  • TCP or UDP의 Portnum + IP의 주소를 합쳐서 소켓 주소로 활용하기도 한다.
  • Socket : Transport layer의 상위계층과 L4 간의 정보를 주고받기 위한 구멍이다.

🍏 Socket Programming

  • Socket : 멀리 떨어진 컴퓨터, program들이 정보를 주고받을 수 있도록 한다. application이 데이터를 보내고 받을 때 bidirectional하게 할 수 있는 일종의 endpoint가 되는 것.
  • application이 socket을 열고 정보를 주면 그 정보가 상대방의 app까지 줌.
  • TCP / UDP도 bidirecitonal -> socket을 사용하는 프로그램들도 보내고 받고 동시에 가능
  • 하나의 컴퓨터 안의 program들 끼리의 통신에도 socket을 사용할 수 있다 = process간 커뮤니 케이션

✅ Client & Server Architecture

  • Server : request를 받는다 / listen
  • Client : server에게 정보를 요청

✅ Berkeley Socket API

이제부터 실용적으로 코드와 실행할 수 있는 프로그램에 대한 이야기를 할 것임

  • API : socket을 통해 정보를 주고받을 수 있음
  • 1983에 출시된 Unix OS 에서 정의한 Socket program API = POISX라는 이름의 표준을 통해 리눅스나 유닉스 계열 대부분에게 동일

🍏 Berkeley Socket API - Functions

socket( )

= 지금부터 통신 시작!
기본적으로 app 본인이 통신을 하려고 했을 때 OS로부터 포트번호와 같은 숫자들을 가져와야 한다. 함수 호출을 통해 OS가 메모리나 기타 등등 준비하도록 한다.

bind( )

상위계층에서 만들어진 socket과 OS를 연결해서 통신을 개시. 통신하고자 하는 컴퓨터의 IP add , port num을 OS에게 TCP UDP를 써서 설정

listen( )

상대방의 connection request를 listen하는 것

  • UDP : 주는대로 받기 -> listen 필요 X
  • TCP : conenction oriented기 때문에 연결필요

connect( )

client가 listen하고 있는 server에게 연결 요청을 보내는 것. TCP socket을 통해서 상대방 TCP socket과 connect 하는 것.

accept( )

server가 client의 request를 수락하는 과정. 본인이 임시로 만들었던 socket을 상대방의 정보와 합치는 것. remote client가 전달한 정보와 내 정보를 pair로 조합. 상대방과 내가 연결된 socket을 새롭게 가지게 된다
-> 이것 모두 API 밑에서 벌어지는 일이기 때문에 우리가 직접 관여하지는 않아영

send( ), recv( ), sendto( ), recvfrom( ) 등등
bidirectional하게 정보를 주고받는다.
write( ), read( )
socket을 file로 규정해서 write read하는 것도 가능

close( )
연결 해지하는 부분

유용한 옵션들

setsockopt( ) : 젤 많이 쓰일 것

개발자가 모든 설정을 하기에는 너무 복잡하기 때문에 대부분의 기능을 Socket 밑에서 자동으로 해준다. 개발자가 특정 소켓의 옵션을 건드릴 때 사용. 옵션을 가져오고 싶을 때는 getsocketopt( )

gethostbyname( ) , gethostbyaddr( )

도메인 이름을 숫자로 바꾸거나 IP add를 다시 도메인이름으로 바꾸는 것

select( ), poll( )
C나 C++ 때 쓰일 수도 있지만 설명은 안할 것.



🍏 TCP Echo Server in Python

  • 3 - 서버 프로그램이 사용할 IP Add
  • 4 - Port num
  • 7 - Socket_STREAM : TCP를 쓰겠다
    with = as 앞의 내용을 수행하고 serverSocket에 의미있는 정보가 들어가면 아래를 수행
  • 8 - 본인의 정보로 socket 열고 준비됨!
  • 9 - 기다리기
  • 10 - 연결요청
  • 11 - with로 client가 유효한지 확인
  • 13 - 정보 주고받기 / 받은거 다시 CLIENT에게 보냄 (Echo)
  • 18 - client가 quit보내면 중단

🍏 TCP Echo Client in Python

3,4 - Server의 주소
11 - 타이핑 요청
12 - 서버에게 보내기
13 - 다시 Client에게 보내면 recv로 받아서 화면에 출력


✅ Socket API Functions

Socket( )

  • create endpoint
  • socket을 만들고 전달받을 때 원래 C에서는 file처럼 사용되었다.
  • 실패 = -1 return / 다른 숫자면 = socket 식별
  • AF_INET : IPv4
  • type
    -SOCK_STREAM = TCP
    -SOCK_DGRAM = UDP
    -SOCK_SEQPACKET (잘 안쓰임)
    -SOCK_RAW

TCP는 stream base로 byte단위로 전송 / UDP : user datagram방식

SOCK_RAW : network layer위에서 쓰는 것 / 원래 소켓은 4계층위에서 짜는데. 극단적으로 TCP UDP를 쓰지 않고 알아서 하겠다~ 할 때 쓰는 것.

  • protocol : TCP/UDP/... 등등 뭐 쓸지 정하는 것. 주로 C 언어에서 쓰였음. 원래는 추가 옵션으로 더 많이 줄 수 있었다.
    우리 코드에서는 파이썬이라 두개만 받음. 아주 잘되어있어용

bind( )

  • 실패 = -1 return
  • 3 arguments (C 기준)
    - sockfd
    C는 객체 지향이 아니었기 때문에 socket에 대한 정보 -> 이제 객체지향이라 필요 X
    - my_addr : 주소 -> 위에 파이썬에서는 이것만 줌
    - addrlen

listen( )

  • for TCP
  • 2 arguments (C 기준)
    - socktf : 역시 필요없어짐
    - backlog : server입장에서 얼마나 많은 TCP연결을 지원할 수 있는지. 내가 받아들이 ㄹTCP connection = client의 request를 몇개까지 받아들일 수 있을 지 정할 수 있음. 현재 python은 default로 되어있음.

0이오면 request 받아 연결이 만들어진 것
-1 는 실패

accept( )

  • stream oriented
  • 상대방이 요청을 해서 내 정보와 상대 정보를 pair로 관리
  • 실패 : -1 return / 성공 : socket desciptor(=숫자 / 모든 연결에는 독립적인 숫자가 부여됨)
  • 2 arguments (C 기준)
    - sockfd
    - cliaddr : 상대방에 대한 정보들
    - addrlen

이제 client쪽

connect( )

  • TCP의 bidirectioanl 통신 가능.
    만약 UDP를 사용한다면 필요 XX
    UDP는 대기하고 있다가 그냥 정보를 받기만 하면됨.
  • 성공하면 0 / 실패 : -1
  • 잘못된 주소 or server가 나 더이상 못받아.. 하면 해지 요청할 수도. -> 반드시 성공한다는것 X
    실패하면 socket()부터 다시 시작해야함

🍏 TCP Echo Server in Python (Enhance)

돌아가는 내용은 동일
아까와 달리 에러처리도 넣어줌
통신에서 아주 중요


🍏 TCP Echo Client in Python (Enhance)


🍏 Socket Programming (1:N)

우리가 할 것 (1:N)
1. Socket API 사용 X / Python이 제공하는 socket server 사용
2. Multi-thread
-> Multi threading을 이용해서 여러개의 client 요청을 동시에 받으며 각각이 독립적으로 동작하도록 할것이다.

[접근1]

  • Socket API로도 가능하긴 하지만 많이 불편함

[접근2] -> 우리가 이걸 사용

  • 최근에 나온 SW는 더 편한 기능이 추가되었기 때문에 Good

✅ Python - Socketserver

  • 서버 클래스가 해야할 일들을 알아서 처리해준다
  • request handerclass : client의 request를 전담해서 담당 / TCP서버는 연결 요청이 오면 handerclass한테 줌.
  • TCP Server
    - bind and active : bind랑 activate까지 할까요? 일일이 구분하지 않고 한방에할 수 있도롣.

TCP Server만들기

  • requesetHandler만들기
    base requesthandler를 제공하기 때문에 이중에서 일부를 수정해서 사용
    가장 많이 수정해야할 부분은 handle() method
  • TCP Server class를 객체로 만들기
    IP Add 주기 + 1.에서만든 핸들러 클리스 주기.
  • handle_request 나 serve_forever 실행해서 무한루프 돌리기

p.32
서버가 실행이 되어서 main에 들어가면 단계별로 진행
하는 일도 받는걸 해야하고, 받았으면 보내야하고.. 이런식으로 또깍또깍
프로그램이 시작해서 끝날때까지 정해진 행동함.


🍏 비동기식 TCP socketserver

  • 동기식
    - A와 B 사이에 선후관계가 명확하여 client1이 동작을 마쳐야 client2가 동작한다.
    - 단점 : blocking / 응답을 받기 전까지 처리못하고 기다린다

  • 비동기식
    여러 client의 요청이 동시에 와도 동시에 처리 가능 / non-blocking - 안기다려용


✅ Multi-Thread / Process

  • Multi-Process

    • 독립적인 프로그램 여러 개 실행
    • 주로 fork()로 실행
    • 각 프로그램 모두 메모리를 차지하면서 CPU위에서 실행되는 것
  • Multi-Thread

    • Process 안에서 data를 공유하는 일꾼(thread)을 늘림


✅ 비동기식 TCP socketserver 개발

[단계 1] - socketserver의 multi-thread 버전 생성

  • TCP서버와 ThreadingMixIn을 베이스로 생성

[단계 2] - Request Handler 수정

  • threading.current_thread( ) / cur_threaed.name 등 추가

[단계 3] - Main Thread 설정 및 실행

  • handler 뿐만 아니라 main도 thread화 된다. 각각 모두 독립적으로 작동.
  • quit할 때 두가지 방법
    • main부가 더이상 thread가 필요없다고 판단하면 main이 죽을 때 thread도 함께 죽인다.(daemon_thread = True)
    • main이 죽어도 thread는 살아있는 방법도 있음(daemon_thread = False)
  • 예쁜 코드~

    server_thread 만들기 -> 사실상 thread를 만든것
    daemon 설정
    start( ) -> thread 실행

if baseThreadNum == active_count()
-> 뒤에서 작없하는 handler thread가 다 죽었다는 뜻 = 종료

🍏 Socket Programming ( N:M )

✅ 비동기식 TCP Chatting 서비스 개발

  • client1 -> client n에게도 전달 가능.
    기존 코드에 {chat} 부분을 추가 -> N:M
  • Server 변경
    • 모든 client의 socket 연결 정보를 저장
    • Client와 연결 등록 & 해지
    • 특정 client가 메세지를 보내면 전체 client에게 복사해서 전달
    • TCP 서버는 connection oriented -> connection 정보 = client 정보
  • Client 변경
    • 전송은 Thread화 X / 수신은 Thread화
    • Client가 타이핑을 하면서 동시에 수신 가능하도록 (비동기식) = 서버가 echo를 하든말든 타이핑 가능
    • main은 키보드에서 입력받아서 server로 보내는 걸 계속하고 수신프로그램(multi thread)은 기다리고 있다가 server에서 뭐가 올때마다 화면에 뿌리기.

✅ socketserver 기반 UDP 채팅 서비스 개발

  • UDP : Connection-less
  • TCP는 connection oriented라서 server가 active socket connection만 봐도 몇개인지 알 수 있다.
  • UDP는 connection less기 때문에 client가 직접 본인이 연결했다는 것을 알려주는 것이 일반적이다.
  • Client > #REG : 등록~ / #DEREG : 해지~
    등록된 REG들은 server가 관리




0개의 댓글