[완료]구조체안에 배열+포인터가 있는데 이를 소켓프로그래밍을 통해 전송 가능할까요??

jinprho의 이미지

안녕하세요, 소켓 프로그래밍을 구현하다가 막막하게 막히는 부분이 있어서 문의 드립니다.

typedef struct packet
{
char *ip[256];
int port[256];
} packet;

이고 각각의 ip 및 포트는 클라이언트에서 얻어온 클라이언트의 주소와 포트번호를 저장하게 해놨습니다.
(ip는 inet_ntoa함수를 이용해서 얻어왔어요)

이렇게 얻어온 것을 다시 클라이언트에 보내려고 하거든요
(즉, 클라이언트가 현재 서버에 접속되어 있는 여러 클라이언트 정보를 얻을 수 있게 하는게 프로그램 목적이죠)

write함수와 read함수를 어떻게 조작을 해야 보내지는지 막막하네요
구조체 안에 포인터도 있고 배열도 선언되어 있으니, 더욱 막막하고요

이럴 경우 어떤 식으로 보낼 수 있는 테크닉이 있을까요??
ip는 더구나 포인터로 선언되어 있어서 보내는 방법이 있을지도 잘 모르겠네요
ip[0] = inet_ntoa(cli_addr)
로 얻어오는 바람에 부득이하게 포인터를 썼는데, 그냥 포트처럼 포인터 안쓰면 보내기 쉬울 꺼 같기도 한데..
변환을 하면 될지...

질문하다보니 질문이 2가지가 되어버렸네요..

아시는 분 가르침 부탁드립니다.

체스맨의 이미지

포인터는 로컬 머쉰에서만 유효합니다. ( 발달된 운영체제에서는 로컬 머쉰의 한 프로세스 내에서만 유효합니다. )

네트워크에 데이터를 보내고 받는 것은, 파일에 데이터를 저장하고 읽을 때와 동일하게 생각하시면 됩니다. 그래서 포인터가 가리키는 곳에 있는 정보가 클라이언트 서버간에 모두 필요한 정보라면 모두 보내고 받아야 합니다.

용어적으로 보면 직렬화(serialization) 과정을 거치는 것입니다.

이런 문제때문에, 통신 프로토콜을 정하는 과정이 중요하고, 그 작업 중 일부가 패킷 형식을 결정하는 것입니다.

Orion Project : http://orionids.org

jinprho의 이미지

포인터에 문제가 있는것을 지적해주셔서
주소는 unsigned long형으로 받고 나중에 클라이언트 측에서 그냥 inet_nota로 변환하는 방법이 나은 거 같아서
수정했습니다.

그러면 포인터 문제는 사라져서 다행인데,
아직 구조체+배열을 어떻게 클라이언트에 보내는지가 미지수네요..

이것에 대한 해결책은 없나요?

어디 글을 보니 memcpy를 이용하는 방법을 이용하시는 듯 하던데..

익명 사용자의 이미지

포인터가 포함되어 있지 않은 구조체는
그냥 문자열 주고받듯이 통째로 char형 배열로 취급해서 보내고 받으면 됩니다.
구조체 안의 고정크기의 배열은 구조체 크기 안에 포함이 됩니다.

하지만 서로 다른 컴퓨터 간에
1. 빅/리틀 엔디안
2. 각 기본 데이터형의 크기 - sizeof(int), sizeof(long)
3. 각 데이터형의 정렬제한
4. 구조체 내부 변수 사이의 빈공간의 크기
등이 서로 일치하지 않을 수 있고
그런 경우에는 구조체를 통째로 주고받을 경우 문제가 생기므로
되도록이면 위에 분께서 말씀하신 직렬화 과정을 거치시길 권합니다.

익명 사용자의 이미지

readv(),writev()를 사용하면 댈거 같은데요..

tinywolf의 이미지

struct client_ipport
{
    unsigned char ip[4];
    unsigned short port;
};
 
struct client_list
{
    unsigned char size;
    struct client_ipport[256];
};

전송할 때는 (sizeof(unsigned char) + sizeof(client_ipport) * size)크기만큼만 전송하고
받을 때는 sizeof(unsigned char)만큼의 size를 먼저 읽어서 (sizeof(client_ipport) * size)만큼 나머지를 읽어서 채운다면 되지않을까요?

ㅡ_ㅡ;

tinywolf의 이미지

이렇게 하면 unsigned short인 port만 엔디안을 관리해주면 되잖아요.

ㅡ_ㅡ;

체스맨의 이미지

구조체를 네트워크로 보내거나, 파일에 저장할 때 항상 직렬화가 필요한 이유는 다음 두 문제가 존재하기 때문입니다.

바이트 순서
정렬

말씀하신 것처럼 sizeof(구조체) 로 보내는 것은, 구조체 사이마다 있을 수 있는 pad 영역까지 보내는 것을 의미하는데, 이 pad 가 모든 시스템마다 동일하다고 가정할 수는 없습니다.

이를 위해 특별히 구조체 pack 옵션을 줄 수 있으나,
모든 컴파일러가 지원한다고 가정할 수 없고
이 구조체를 그대로 사용하는 경우 성능을 저하시킬 수 있습니다. (물론 직렬화 목적으로만 사용하는 구조체라면 얘기가 다르죠 )

구조체 각 멤버를 쭉 훑어서 바이트 순서 정렬하고 프로토콜대로 패킷을 직렬화하는 것이 정석입니다.

Orion Project : http://orionids.org

jinprho의 이미지

참 다양한 방법들이 있는데, 전 아무것도 몰랐네요~

답변 달아주셔서 감사드려요~

이것을 바탕으로 열심히 한번 구현해보겠습니다^^

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.