[TCP] TCP 데이터 경계 문제에 대해서

2021. 4. 1. 01:11Web, Network

 

네트워크 통신에 쓰이는 소켓에는

UDP(User Datagram Protocol)와 TCP(Transmission Control Protocol)가 있고

 

UDP의 경우 데이터 경계가 명확해 3번 send 호출해서 보냈으면

3번 recv 호출해서 받아야되죠

 

그러나 TCP의 경우에는 데이터 경계가 없어 3번 send로 보냈어도

recv를 몇 번 호출해야될지 알 수가 없습니다.

 

그냥 이 문제를 어떻게 처리하는게 효율적일지 생각해보고 스크립트 짜보며 끄적여본거 올리는겁니다ㅋㅋ

 

 

 

 

TCP 데이터 경계 문제 해결방법

  • 끝을 나타내는 문자열을 추가한다.
  • 미리 데이터의 길이를 고정시킨다.

이 문제에 대해 제가 파이썬으로 작성한 코드입니다.

 


이 부분은 개인적으로 테스트 해본 내용입니다.

 

위의 sock.py와 아래의 코드로 파일 전송 테스트를 해봤습니다.

크기가 작은 파일 위주로 해본 결과 잘 되는 것 같습니다.

'''
sock.py example
'''
import sock
BASE_DIR = ''
END_DELIMITER = '[EOF]'
SERVER = 'ip'
PORT = port_num
def recv_file():
'''
Receive file
'''
pkt = s.recv_with_delimiter(END_DELIMITER, byte=True)
idx = pkt.find(b'\n\n')
rel_path = pkt[:idx].decode()
con = pkt[idx+2:-len(END_DELIMITER)]
with open(BASE_DIR + rel_path, 'wb') as f:
f.write(con)
s = sock.sock('tcp', log=True)
s.connect(SERVER, PORT)
recv_file()
s.close()
view raw client.py hosted with ❤ by GitHub
'''
sock.py example
'''
import sock
BASE_DIR = ''
END_DELIMITER = '[EOF]'
FILE = 'filename'
SERVER_NAME = ''
PORT = port_num
def send_file(rel_path):
'''
Send file
rel_path: file relative path
'''
con = None
with open(BASE_DIR + rel_path, 'rb') as f:
con = f.read()
s.send(rel_path + '\n\n')
s.send(con + END_DELIMITER.encode())
servSock = sock.sock('tcp', log=True)
servSock.bind(SERVER_NAME, PORT)
servSock.listen()
s, addr = servSock.accept()
send_file(FILE)
s.close()
servSock.close()
view raw server.py hosted with ❤ by GitHub

 

기타

  • 자바 소켓 프로그래밍 시 입출력 스트림의 버퍼링에 주의해야된다(로우레벨 넘나 불편한것...).
  • 파이썬에서 socket.bind 함수에 전달하는 ip는 '이 주소로부터 오는 패킷은 나한테 묶어줘라'는 의미인 것 같다. 127.0.0.1로 바인딩 했더니 외부 요청을 못받는다(파이썬만 테스트 해봤다).