동기 서버 작성 시 tcp 의 경계 특성 때문에 생기는 질문입니다.

balgarac1의 이미지

#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 호출 했을 때 버퍼 크기를 지정해줘야 하는데 어떻게 설정하든 데이터 읽어오는 것이

보낸 만큼 읽어들이지 못합니다.

생각한 방법이 구조체에 더미를 집어넣어서 모든 구조체가 같은 크기를 갖게 하는 방법을 생각했는데

올바른 방법일 수 있을까요??

jick의 이미지

TCP는 스트림 방식이기 때문에 보내는 사람이 100바이트를 한번에 보냈다고 읽을 때 100바이트를 한번에 읽는다는 보장이 없습니다. 어떤 방식을 택하든 "원하는 바이트 수만큼 읽지 못하는 상황"은 반드시 생기니까 그 상황을 해결하는 코드가 어차피 들어가야 합니다.

익명 사용자의 이미지

jick 님이 스트림의 속성에 대해 간결하면서 정확한 표현을 해주셨네요. TCP를 하신다면, 반드시 해야하는 것이지요.
---------
고정사이즈 프로토콜을 정의하는 방법으로 구현하는 것은 대역폭(bandwidth)를 다소 낭비하겠지만, 다른 사유로 필요하다면, 상황에 맞추어 사용해도 되겠지요.
운영조건이 망여건이 우수한 한국이라면, 게다가 로컬망에서만 사용하는 것 이라면, 예상되는 데이터의 유통량에서 대략 낭비되는 대역폭을 살펴 보시고, 견딜 만하다고 판단되시면 하면... 되지요.

* 그러나, 시간 여유가 있는 일이라면, 가변 길이 프로토콜을 만들어서 사용하시는 것이 좋겠습니다.

balgarac1의 이미지

네 답변 감사드립니다.

twinwings의 이미지

윈도가 아니라 리눅스 기준으로 설명하면..

file descriptor로 소켓을 읽을 때

read/write로 할 때가 있고

recv/send로 할때가 있습니다.

read/write는 좀 더 추상적인 연산이고(연결지향의 일반적인 입출력. 파일입출력까지 포함)
recv/send는 네트워크에 한정된 연산입니다.
(from man, "The recv() call is normally used only on a connected socket")

그래서 좀더 구체적인 옵션을 줄 수 있는데요.

       MSG_WAITALL (since Linux 2.2)
              This  flag  requests  that  the  operation block until the full request is satisfied.
              However, the call may still return less data than requested if a signal is caught, an
              error  or  disconnect  occurs, or the next data to be received is of a different type
              than that returned.

리눅스의 경우 recv에 해당 플래그를 걸면 연결이 끊기지 않는 이상

무조건 해당 길이만큼 기다립니다.(block)

윈도에서는 어떨지 잘 모르겠네요. 옵션 줄 수 있는지 한번 찾아보세요.

Necromancer의 이미지

각 패킷 보니까 길이를 지정하는 란이 있네요.

1. 패킷 타입과 길이까지만을 읽어서 얼마나 많은 데이터가 오는지 알아낸다.
2. 길이에서 추가 수신할 데이터의 양을 확인 후 읽는다.

이 순서대로 진행합니다.

각 단계마다 제한시간을 두어서 이 시간 초과하면(TIMEOUT) 송수신에 이상 생긴것으로 간주하고 이 송수신을 요청한 쪽에 에러 리포트를 하도록 코드를 짜야죠. 다 읽지 못했다면 원하는 양만큼 읽도록 계속 반복해야 합니다.

Written By the Black Knight of Destruction

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.