동기 서버 작성 시 tcp 의 경계 특성 때문에 생기는 질문입니다.
글쓴이: balgarac1 / 작성시간: 목, 2015/11/12 - 8:09오후
#ifndef MSGTYPE_H_ #define MSGTYPE_H_ #define UB2 unsigned short #define UB4 unsigned int #define SCHAR signed char #define auth_req_msg 1 #define auth_res_msg 2 #define sql_req_msg 3 #define sql_res_msg 4 #define close_req_msg 5 #define close_res_msg 6 #define SELECT 1 #define UPDATE 2 #define DELETE 3 typedef struct _dgt_auth_req_msg { UB2 msg_type; SCHAR db_user[33]; SCHAR password[33]; SCHAR program_name[33]; SCHAR db_name[33]; }dgt_auth_req_msg; // msg type 1 typedef struct _dgt_auth_res_msg { UB2 msg_type; UB2 rtn_len; SCHAR rtn_msg[257]; }dgt_auth_res_msg; // msg type 2 typedef struct _dgt_sql_req_msg { UB2 msg_type; UB4 sql_len; SCHAR sql_text[1025]; UB2 sql_type; }dgt_sql_req_msg; // msg type 3 typedef struct _dgt_sql_res_msg { UB2 msg_type; UB4 rtn_len; SCHAR rtn_data[1025]; UB2 sql_type; }dgt_sql_res_msg; // msg type 4 typedef struct _dgt_close_req_msg { UB2 msg_type; }dgt_close_req_msg; typedef struct _dgt_close_res_msg { UB2 msg_type; UB2 rtn_len; SCHAR rtn_msg[257]; }dgt_close_res_msg; // msg type 5
멀티 플렉싱 서버(select)를 사용하고 있고
위와 같은 프로토콜 형식으로 주고 받아야 합니다. 구조체 크기는 다 다릅니다.
서버에서 recv 호출 했을 때 버퍼 크기를 지정해줘야 하는데 어떻게 설정하든 데이터 읽어오는 것이
보낸 만큼 읽어들이지 못합니다.
생각한 방법이 구조체에 더미를 집어넣어서 모든 구조체가 같은 크기를 갖게 하는 방법을 생각했는데
올바른 방법일 수 있을까요??
Forums:
...
TCP는 스트림 방식이기 때문에 보내는 사람이 100바이트를 한번에 보냈다고 읽을 때 100바이트를 한번에 읽는다는 보장이 없습니다. 어떤 방식을 택하든 "원하는 바이트 수만큼 읽지 못하는 상황"은 반드시 생기니까 그 상황을 해결하는 코드가 어차피 들어가야 합니다.
jick 님이 스트림의 속성에 대해 간결하면서 정확한
jick 님이 스트림의 속성에 대해 간결하면서 정확한 표현을 해주셨네요. TCP를 하신다면, 반드시 해야하는 것이지요.
---------
고정사이즈 프로토콜을 정의하는 방법으로 구현하는 것은 대역폭(bandwidth)를 다소 낭비하겠지만, 다른 사유로 필요하다면, 상황에 맞추어 사용해도 되겠지요.
운영조건이 망여건이 우수한 한국이라면, 게다가 로컬망에서만 사용하는 것 이라면, 예상되는 데이터의 유통량에서 대략 낭비되는 대역폭을 살펴 보시고, 견딜 만하다고 판단되시면 하면... 되지요.
* 그러나, 시간 여유가 있는 일이라면, 가변 길이 프로토콜을 만들어서 사용하시는 것이 좋겠습니다.
네 감사합니다.
네 답변 감사드립니다.
윈도가 아니라 리눅스 기준으로 설명하면..
윈도가 아니라 리눅스 기준으로 설명하면..
file descriptor로 소켓을 읽을 때
read/write로 할 때가 있고
recv/send로 할때가 있습니다.
read/write는 좀 더 추상적인 연산이고(연결지향의 일반적인 입출력. 파일입출력까지 포함)
recv/send는 네트워크에 한정된 연산입니다.
(from man, "The recv() call is normally used only on a connected socket")
그래서 좀더 구체적인 옵션을 줄 수 있는데요.
리눅스의 경우 recv에 해당 플래그를 걸면 연결이 끊기지 않는 이상
무조건 해당 길이만큼 기다립니다.(block)
윈도에서는 어떨지 잘 모르겠네요. 옵션 줄 수 있는지 한번 찾아보세요.
각 패킷 보니까 길이를 지정하는 란이 있네요.1.
각 패킷 보니까 길이를 지정하는 란이 있네요.
1. 패킷 타입과 길이까지만을 읽어서 얼마나 많은 데이터가 오는지 알아낸다.
2. 길이에서 추가 수신할 데이터의 양을 확인 후 읽는다.
이 순서대로 진행합니다.
각 단계마다 제한시간을 두어서 이 시간 초과하면(TIMEOUT) 송수신에 이상 생긴것으로 간주하고 이 송수신을 요청한 쪽에 에러 리포트를 하도록 코드를 짜야죠. 다 읽지 못했다면 원하는 양만큼 읽도록 계속 반복해야 합니다.
Written By the Black Knight of Destruction
댓글 달기