[완료]구조체안에 배열+포인터가 있는데 이를 소켓프로그래밍을 통해 전송 가능할까요??
글쓴이: jinprho / 작성시간: 월, 2007/08/27 - 8:27오후
안녕하세요, 소켓 프로그래밍을 구현하다가 막막하게 막히는 부분이 있어서 문의 드립니다.
typedef struct packet
{
char *ip[256];
int port[256];
} packet;
이고 각각의 ip 및 포트는 클라이언트에서 얻어온 클라이언트의 주소와 포트번호를 저장하게 해놨습니다.
(ip는 inet_ntoa함수를 이용해서 얻어왔어요)
이렇게 얻어온 것을 다시 클라이언트에 보내려고 하거든요
(즉, 클라이언트가 현재 서버에 접속되어 있는 여러 클라이언트 정보를 얻을 수 있게 하는게 프로그램 목적이죠)
write함수와 read함수를 어떻게 조작을 해야 보내지는지 막막하네요
구조체 안에 포인터도 있고 배열도 선언되어 있으니, 더욱 막막하고요
이럴 경우 어떤 식으로 보낼 수 있는 테크닉이 있을까요??
ip는 더구나 포인터로 선언되어 있어서 보내는 방법이 있을지도 잘 모르겠네요
ip[0] = inet_ntoa(cli_addr)
로 얻어오는 바람에 부득이하게 포인터를 썼는데, 그냥 포트처럼 포인터 안쓰면 보내기 쉬울 꺼 같기도 한데..
변환을 하면 될지...
질문하다보니 질문이 2가지가 되어버렸네요..
아시는 분 가르침 부탁드립니다.
Forums:
포인터는 로컬
포인터는 로컬 머쉰에서만 유효합니다. ( 발달된 운영체제에서는 로컬 머쉰의 한 프로세스 내에서만 유효합니다. )
네트워크에 데이터를 보내고 받는 것은, 파일에 데이터를 저장하고 읽을 때와 동일하게 생각하시면 됩니다. 그래서 포인터가 가리키는 곳에 있는 정보가 클라이언트 서버간에 모두 필요한 정보라면 모두 보내고 받아야 합니다.
용어적으로 보면 직렬화(serialization) 과정을 거치는 것입니다.
이런 문제때문에, 통신 프로토콜을 정하는 과정이 중요하고, 그 작업 중 일부가 패킷 형식을 결정하는 것입니다.
Orion Project : http://orionids.org
감사합니다. 우선 한가지는 해결되었네요
포인터에 문제가 있는것을 지적해주셔서
주소는 unsigned long형으로 받고 나중에 클라이언트 측에서 그냥 inet_nota로 변환하는 방법이 나은 거 같아서
수정했습니다.
그러면 포인터 문제는 사라져서 다행인데,
아직 구조체+배열을 어떻게 클라이언트에 보내는지가 미지수네요..
이것에 대한 해결책은 없나요?
어디 글을 보니 memcpy를 이용하는 방법을 이용하시는 듯 하던데..
포인터가 포함되어
포인터가 포함되어 있지 않은 구조체는
그냥 문자열 주고받듯이 통째로 char형 배열로 취급해서 보내고 받으면 됩니다.
구조체 안의 고정크기의 배열은 구조체 크기 안에 포함이 됩니다.
하지만 서로 다른 컴퓨터 간에
1. 빅/리틀 엔디안
2. 각 기본 데이터형의 크기 - sizeof(int), sizeof(long)
3. 각 데이터형의 정렬제한
4. 구조체 내부 변수 사이의 빈공간의 크기
등이 서로 일치하지 않을 수 있고
그런 경우에는 구조체를 통째로 주고받을 경우 문제가 생기므로
되도록이면 위에 분께서 말씀하신 직렬화 과정을 거치시길 권합니다.
벡터함수를 쓰면 어떨지요
readv(),writev()를 사용하면 댈거 같은데요..
struct client_ipport {
전송할 때는 (sizeof(unsigned char) + sizeof(client_ipport) * size)크기만큼만 전송하고
받을 때는 sizeof(unsigned char)만큼의 size를 먼저 읽어서 (sizeof(client_ipport) * size)만큼 나머지를 읽어서 채운다면 되지않을까요?
ㅡ_ㅡ;
..
이렇게 하면 unsigned short인 port만 엔디안을 관리해주면 되잖아요.
ㅡ_ㅡ;
구조체를 네트워크로
구조체를 네트워크로 보내거나, 파일에 저장할 때 항상 직렬화가 필요한 이유는 다음 두 문제가 존재하기 때문입니다.
바이트 순서
정렬
말씀하신 것처럼 sizeof(구조체) 로 보내는 것은, 구조체 사이마다 있을 수 있는 pad 영역까지 보내는 것을 의미하는데, 이 pad 가 모든 시스템마다 동일하다고 가정할 수는 없습니다.
이를 위해 특별히 구조체 pack 옵션을 줄 수 있으나,
모든 컴파일러가 지원한다고 가정할 수 없고
이 구조체를 그대로 사용하는 경우 성능을 저하시킬 수 있습니다. (물론 직렬화 목적으로만 사용하는 구조체라면 얘기가 다르죠 )
구조체 각 멤버를 쭉 훑어서 바이트 순서 정렬하고 프로토콜대로 패킷을 직렬화하는 것이 정석입니다.
Orion Project : http://orionids.org
모두들 감사드립니다.
참 다양한 방법들이 있는데, 전 아무것도 몰랐네요~
답변 달아주셔서 감사드려요~
이것을 바탕으로 열심히 한번 구현해보겠습니다^^
댓글 달기