2017-10-30 13 views
0

나는 우분투 상자의 파이썬에서 vxworks 컴퓨터의 C 프로그램으로 UDP 메시지를 보냈습니다. vxworks 컴퓨터의 엔디안이 네트워크 바이트 순서와 일치하지 않으므로 ntohs, ntohl 등을 사용하여 바이트 순서를 바꿔야합니다.네트워크 바이트 순서 sin_family에 대해서

UDP 연결에서 읽은 다음 "패밀리 "그래서 내가 IPV4 나 IPV6을 해독해야하는지 안다. 이런 식으로하고 싶습니다 ...하지만 작동하지 않습니다.

struct sockaddr data = {}; 
char udp_ip[INET6_ADDRSTRLEN] = {0}; 
// ... (recvfrom ...) 
if (AF_INET == data.sa_family) 
{ 
    struct sockaddr_in*s = (struct sockaddr_in *)&data; 
    const char *addr = inet_ntop(AF_INET, &s->sin_addr, udp_ip, sizeof(udp_ip)); 
    udp_port = ntohs(s->sin_port); 
    ... 
} 
if (AF_INET6 == data.sa_family) 
{ 
    struct sockaddr_in6 *s = (struct sockaddr_in *)&data; 
    const char *addr = inet_ntop(AF_INET6, &s->sin6_addr, udp_ip, sizeof(udp_ip)); 
    udp_port = ntohs(s->sin6_port); 
    ... 
} 

포트를 보는 데 익숙하지 만 비슷한 필드가 스왑되었지만 패밀리가 멀티 바이트 필드라는 것을 알았습니다. 내 sa_family 값이 범위를 벗어나기 때문에 코드가 작동하지 않는 것을 발견했습니다. 이 컴퓨터의 헤더에서 가장 큰 AF_ * 값은 40입니다. 500을 초과하는 값이 표시됩니다. sa_family의 바이트가 스왑 된 것처럼 보이고 바이트 순서도 바꿔야합니다. 예 :

const sa_family_t family = ntohs(data.sa_family); 

그런 다음 if 변수에 해당 변수를 사용합니다. 질문이 : 이것은 합리적인가요? 나는 전에 가족에게 한 일을 본 적이 없다. 멀티 바이트 (sizeof (data.sa_family) == 2)입니다.

나는

udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
udp_sock.bind(('', 0)) 
data = self.create_data() 
udp_sock.sendto(data, (ip, port))  

전송 된 데이터는 심지어 데이터와 문제를 분석하기 위해 도착하기 전에 내가 붙어있어 같은 종류의 관계가 .. 내 파이썬 코드는 관련이 있지만, 완성도 생각하지 않는다 데이터가 "FOO"와 같이 간단하다면 그 자체를 제시합니다.

다른 기사 내가 확인한 : what kind of fields in network packets should be converted to network byte orderNetwork byte order and endianness issues.

나는 또한 이것을 읽었는데, 이는 내가 보는 것을 모순하는 것처럼 보입니다. struct sockaddr_in member byte order for bind()

반대로, (메시지가 표시되지 않은 경우) 내 vxworks (네트워크가 아닌 바이트 순서 기계)에서 메시지를 보낼 때 다른 기계로 되돌려 보낼 때 (메시지가 표시 될 때까지) 나는 htons (AF_INET)를 사용해야합니다. 작동하지 않습니다. 나는 모순 된 충고를 여기에서 볼 때 혼란 스러울뿐입니다. 그래서 저는 근본적으로 잘못된 것을하고 있다고 생각합니다. 질문 : 가족 (htons/ntohs)을 전환 할 필요가 없다는 조언이 있으면 무엇을 잘못하고 있습니까?

+1

질문과 관련이 없으면 여기에서 두 개의 피연산자를'if (AF_INET6 == data.sa_family)'로 바꿔야합니다. 그렇습니다. 다른 방법은 정상적인 방법입니다. 즉,'variable == constant' –

+0

어디에서'data' 변수를 채울 수 있습니까? 파이썬 코드가 전송하기 전에 모든 것을 네트워크 바이트 순서로 변환하고 있는지 확인하고 있습니까? –

+1

당신은 패밀리 필드가 변환 할 필요가 없다고 말합니다. 네트워크를 통해 전송되지는 않지만 드라이버가 패킷을 작성하는 방법을 알기 위해 사용합니다. –

답변

0

가족을 변환 할 필요가 없습니다. 그것은 본질적으로 전달되지 않습니다. 참조 :

https://en.wikipedia.org/wiki/IPv4

https://en.wikipedia.org/wiki/IPv6

를 버전 값이 ... 그 IP 버전 ==, IPV4 4 4 인 경우. 해당 버전 == 6 .. 다음 IPV6.

실제 문제는 내가 크로스 컴파일 중이었고 잘못된 버전의 대상 헤더 파일이 있다는 것입니다. 나는 구조가 같았다을했다 :

/* 
* Structure used by kernel to store most 
* addresses. 
*/ 
struct sockaddr { 
    unsigned char sa_len;  /* total length */ 
    sa_family_t  sa_family; /* address family */ 
    char   sa_data[14]; /* actually longer; address value */ 
}; 
#define SOCK_MAXADDRLEN 255  /* longest possible addresses */ 

여분의 문자와 엔디안 내 문제의 원인이었다, 실제 시스템에, 구조가 다른 필드를 포함

struct sockaddr { 
    u_short sa_family;    /* address family */ 
    char sa_data[14];   /* up to 14 bytes of direct address */ 
}; 

. 나는 528과 같은 가치를보고 있었다.그것은 길이가 "10"이고 패밀리가 "2"인 조합으로 바이트가 결합되어 서명되지 않은 2 바이트로 처리 될 때입니다.