소켓 통신을 프로그래밍 하는 중에 버퍼사이즈를 정할수있어서 버퍼 사이즈만 늘린다면 무제한으로 보낼수 있지 않을까 하는 생각이 들었다.
백문이불여일견이라 하였던가...
한번 테스트해보자
무엇이든 해보는게 제일 좋다
############################### 클라이언트 코드
# 메시지를 전송합니다.
msg = '\
일단 튼튼함에 있어서는 석탑보다는 못하지만 전탑이나 목탑보다는 강한 편이다. 일단 과거에는 벽돌을 튼튼하게 굽기가 어려운데다가, 벽돌로 쓰이는 재료도 저질인지라 현대의 벽돌처럼 튼튼하지 않으므로 수시로 보수해야 한다.\
이런 면에서 원래 돌이었던 것을 벽돌같이 깎아서 만든 모전석탑이 강하다. 단, 벽돌쌓기의 특성상 균형이 한번 무너지기 시작하면 폭삭 주저앉는 경향이 있으므로 석탑보다는 약할 수 밖에 없다. \
목탑은 잘 만들면 석탑에 준하게 튼튼하지만, 화재가 나면 그냥 잿더미가 되므로 종합적으로는 강도가 떨어진다. 하지만 모전석탑이 그렇게 많지 않은 이유는 손이 많이 가기 때문이다. \
당장 건설시에도 석재를 다듬는 것도 만만치 않은데, 가공하기 쉬운 석재를 쓴다지만 벽돌 모양으로 잘게 나누어 다듬으려면 얼마나 품이 많이 들어갈까? \
그리고 모전석탑이 완성된 다음에 수리나 보수를 위해 다시 돌벽돌이 필요하면 또다시 돌을 캐다가 벽돌모양으로 잘게 나누어서... \
따라서 굳이 전탑처럼 보여야 할 필요가 없다면 차라리 석재를 큼직하게 써서 석탑을 쌓는 것이 훨씬 튼튼하고 보수하기 쉬우므로 모전석탑을 많이 건축할 필요가 없었고, 일단 파손된 모전석탑을 보수하기도 힘들기 때문에 방치돼서 파괴될 확률도 높다.\
그래서 모전석탑이 많지 않은 것이다. 한편 어디선가 벽돌을 조달할 길이 열리면 전탑을 흉내낸 모전석탑이 아니라 그냥 전탑을 쌓을 확률이 높아진다. 예를 들어 낙동강을 낀 안동시 지역에서는 양질의 점토를 구하기 쉬워 전탑을 많이 쌓았다. \
# 물론 벽돌을 가공하는데는 알맞은 흙과 더불어 벽돌을 만드는데는 진흙을 햇볕에 말리는 원시적인 방법이 아닌 이상 연료가 필요하기 때문에 주변환경에 따라서는 노동력을 좀 더 들이는 편이라 전탑보다 비용은 더 적게 들어간다.\
|우리나라에 유독 이런 양식이 발달한 이유?'
client_socket.sendall(msg.encode())
############################### 서버 코드
while True:
# 클라이언트가 보낸 메시지를 수신하기 위해 대기합니다.
data = client_socket.recv(16184) # buffer size 4096 8192 16184...2의 거듭제곱
# 빈 문자열을 수신하면 루프를 중지합니다.
if not data:
break
# 수신받은 문자열을 출력합니다.
print('Received from', addr, data.decode())
# 받은 문자열을 다시 클라이언트로 전송해줍니다.(에코)
client_socket.sendall('success')
서버의 버퍼 사이즈를 16184로 수정한뒤 실행을 해보았다...
근데 이게 뭐지?
python socket UnicodeDecodeError: 'utf-8' codec can't decode byte 0xeb in position 1459: unexpected end of data
소켓 통신에 유니코드 에러라니....
에러 내용은 1459 위치에서 디코딩 되지 않는 문자가 있다는것이다...
흠..... 왜일까?
클라이언트측에서 msg를 바이트로 인코딩한뒤 길이를 보니
그런데 서버측에서 받은 바이트수는?
잉.....
아무래도 1460 이후로 끊기면서 바이트가 짤려 스트링으로 디코딩하지 못하는것같다.
그렇다면 버퍼 사이즈를 늘려줬음에도 왜 짤리는걸까???
그래서 msg 문자열의 숫자를 줄여가며 테스트해본 결과 최대 1973까지 전달되는것을 확인하였다.
1973을 초과하게되면 1460까지만 전달이 되는것 같다. 그런데 이게 문제는 문자열 형식에 따라서 또 변경되는것 같아서 스트레스....
소켓 통신의 버퍼 사이즈에 대한 이슈는 아직 찾지 못하였다.... 내가 못찾는거겠지...ㅠ
할수없이 버퍼의 사이즈를 줄이고 보내야겠다...ㅠ 버퍼 사이즈에 대한 확신이 없다보니.. 일단 최소한 1024이상 전달 가능한것으로 보고 버퍼사이즈는 1024로 확정한뒤
한글이 1자에 3바이트, 그래서 1024로 볼때 340자 내외로 전송된다 치고 끊어서 보내는 방식을 취해야겠다...
코드를 수정하자면..
############################### 클라이언트 코드
MSG_SIZE=340 # 메세지 길이
# 메시지를 전송합니다.
msg = '\
일단 튼튼함에 있어서는 석탑보다는 못하지만 전탑이나 목탑보다는 강한 편이다. 일단 과거에는 벽돌을 튼튼하게 굽기가 어려운데다가, 벽돌로 쓰이는 재료도 저질인지라 현대의 벽돌처럼 튼튼하지 않으므로 수시로 보수해야 한다.\
이런 면에서 원래 돌이었던 것을 벽돌같이 깎아서 만든 모전석탑이 강하다. 단, 벽돌쌓기의 특성상 균형이 한번 무너지기 시작하면 폭삭 주저앉는 경향이 있으므로 석탑보다는 약할 수 밖에 없다. \
목탑은 잘 만들면 석탑에 준하게 튼튼하지만, 화재가 나면 그냥 잿더미가 되므로 종합적으로는 강도가 떨어진다. 하지만 모전석탑이 그렇게 많지 않은 이유는 손이 많이 가기 때문이다. \
당장 건설시에도 석재를 다듬는 것도 만만치 않은데, 가공하기 쉬운 석재를 쓴다지만 벽돌 모양으로 잘게 나누어 다듬으려면 얼마나 품이 많이 들어갈까? \
그리고 모전석탑이 완성된 다음에 수리나 보수를 위해 다시 돌벽돌이 필요하면 또다시 돌을 캐다가 벽돌모양으로 잘게 나누어서... \
따라서 굳이 전탑처럼 보여야 할 필요가 없다면 차라리 석재를 큼직하게 써서 석탑을 쌓는 것이 훨씬 튼튼하고 보수하기 쉬우므로 모전석탑을 많이 건축할 필요가 없었고, 일단 파손된 모전석탑을 보수하기도 힘들기 때문에 방치돼서 파괴될 확률도 높다.\
그래서 모전석탑이 많지 않은 것이다. 한편 어디선가 벽돌을 조달할 길이 열리면 전탑을 흉내낸 모전석탑이 아니라 그냥 전탑을 쌓을 확률이 높아진다. 예를 들어 낙동강을 낀 안동시 지역에서는 양질의 점토를 구하기 쉬워 전탑을 많이 쌓았다. \
# 물론 벽돌을 가공하는데는 알맞은 흙과 더불어 벽돌을 만드는데는 진흙을 햇볕에 말리는 원시적인 방법이 아닌 이상 연료가 필요하기 때문에 주변환경에 따라서는 노동력을 좀 더 들이는 편이라 전탑보다 비용은 더 적게 들어간다.\
|우리나라에 유독 이런 양식이 발달한 이유?'
print(len(msg))
if len(msg) > MSG_SIZE: # 제한된 길이보다 길다면
cnt=0
while (cnt+1)*MSG_SIZE < len(msg) : # 전체 텍스트보다 짧다면 반복
msg_tmp = '|||'+msg[cnt*MSG_SIZE:(cnt+1)*MSG_SIZE] # 분할 전송이라는 의미 |||
client_socket.sendall(msg_tmp.encode(encoding='utf-8'))
cnt=cnt+1
msg_tmp = '|||' + msg[cnt * MSG_SIZE:len(msg)] +'|/|' # 분할 전송중 마지막 이라는 의미로 |||, |/| 추가
client_socket.sendall(msg_tmp.encode(encoding='utf-8'))
else:
client_socket.sendall(msg.encode(encoding='utf-8'))
############################### 서버 코드
data_tmp='' # 데이터를 담기위한 것
# 무한루프를 돌면서
try:
while True:
# 클라이언트가 보낸 메시지를 수신하기 위해 대기합니다.
data = client_socket.recv(2048) # buffer size 4096 8192 16184...2의 거듭제곱
# 빈 문자열을 수신하면 루프를 중지합니다.
if not data:
break
rec_data = str(data.decode(encoding='utf-8'))
if rec_data.__contains__('|||') :
if not rec_data.__contains__('|/|'): # ||| 파싱
rec_data= rec_data.replace('|||','')
data_tmp = data_tmp + rec_data
continue
else: # |/| 파싱
rec_data = rec_data.replace('|||', '')
rec_data = rec_data.replace('|/|', '')
data_tmp = data_tmp + rec_data
rec_data = data_tmp
# 수신받은 문자열을 출력합니다.
print('Received from', addr, rec_data.decode())
# 받은 문자열을 다시 클라이언트로 전송해줍니다.
client_socket.sendall('success')
이렇게 하면 전송 완료됨.
도대체 왜 이런겨..........ㅠ
2020/06/10 수정
https://minwan1.github.io/2018/10/28/2018-10-28-TCP-IP-DATA-PROCESSING/
tcp 소켓통신할 때 패킷 사이즈에 대한 내용!
이걸 이해해야했음.
ㅠㅠㅠ
2021/03/03 수정
클라이언트에서 서버로 보낼때 length:data 와 같은 형식으로 보냄
서버에서는 버퍼를 줄여 한문자씩 읽고 ':' 가 나온다면 버퍼의 크기를 length만큼 정의해서 데이터를 받기
이렇게 하면 끊기지도 않고 훨씬 보기좋은 코드가 된다!!
이에 대한 정리는 따로 하기
'Python' 카테고리의 다른 글
jupyter notebook 실행시 conda env가 보이지 않을때 (0) | 2021.06.16 |
---|---|
판다스 사용법 정리(url) (0) | 2020.12.30 |
jupyter notebook에 LaTex 표기법으로 수학식 만들기(url) (0) | 2020.12.08 |
파이썬으로 pdf 워터마크 제거하기(url) (0) | 2020.12.01 |
파이썬 정렬, 다중 조건 정렬, 정렬 키 여러개(url) (0) | 2020.10.21 |
댓글