아... 오늘 이것땜에 하루종이 헤맸다... 사실 이거 혼자만은 아니고 wireshark (packet capture program)도 한몫했지만...

어쨌든, linux로 돌아가는 PC를 client로 삼고, linux 말고 ucos가 올라간 STB이 server가 되어 통신을 할일이 있었다.  물론 간단하게 socket programming interface를 택했다.  그러기 위해서 일단... PC와 PC끼리의 packet 이동 경로를 wireshark를 이용해서 확인해보고, 그 packet을 그대로 들고가면 되는 거였다. 

Server의 port는 7000, client의 port는 9000.

PC와 STB의 통신이 이루어지는데 wireshark에 잡히는 packet 모양이 이상했다.  PLCI (Packet Cable Lawful Intercept)라고... 대충 해석해보니 합법적인 packet 가로채기??? 하튼 wireshark가 이건 이상한 packet이라고 불그죽죽하게 색깔을 칠해버렸다... 이상한데??? 더군다나 황당한건 PC에서 recvfrom()을 사용해서 UDP packet을 읽는데 첫번째/두번째는 성공하는데 세번째부터 Invalid argument가 나는거다...! 문제의 소스는

  ssize_t recv_len;
  socklen_t peer_addr_len;
  struct sockaddr_in peer_addr;

  ...

  recv_len = recvfrom (sock_fd, (void *)pkt, sizeof (struct pkt_buf), 0, (struct sockaddr *)&peer_addr, &peer_addr_len);

  ...

사실 이전에 socklen_t를 안쓰고 그냥 int 했다가 통신이 되지 않는 어처구니 없는 실수로 한 3일 까먹은 기억이 있어서 manpage에 나오는 그대로의 prototype을 지켜냈다.  더군다나 첫번째 / 두번째 packet이 무사히 지나갔기에 이게 문제가 있을거라고는 꿈에도 생각못했고, wireshark에 표시되는 내용을 분석하기 시작했다.  음... DDoS 공격할 때 쓰고 어쩌고 저쩌고...

아... 뭐야... 근데 도저히 모르겠다.  저녁을 먹고 검도부 모임에 다녀온 뒤 다시 코드를 붙잡았다.  Wireshark에서 protocols in frame에 PCLI가 표시되어있었으므로 당연히 ehternet frame에 문제가 있는 건줄 알고 STB쪽 소스를 이잡듯이 뒤졌지만 문제가 없다... 아.. 뭐지?

그러다가 client program을 실행시킬 때 실수로 port 번호를 8000으로 넣었다.  -_-;; 젠장.. 그랬더니 PCLI는 어딜가고 OICQ라는 중국애들이 쓰는 메신저 protocol이라고 변경되는거 아닌가!!! 뭐야... 이거...

port 번호를 한 30,000으로 넣었더니 wireshark에서 정상적인 UDP packet이라고 인정해준다.  아... ㅆㅂ...

안도의 한숨을 다 쉬기도 전에 근데 왜 recvfrom ()은 EINVAL인거야??? 뒤지고뒤지고 뒤지고 뒤졌는데 진짜 자료가 없다... 아... 뭐지... 잘못된 argument는 눈을 씻고 찾아봐도 찾아볼 수가 없다.

열심히 구글링중 KLDP에서의 하나의 쓰레드를 발견했다.

혹시나 해서... 그걸 적용해봤다.  물론 sendto ()와 recvfrom ()의 prototype이 틀리므로 적용방법은 아래와 같이...

  ssize_t recv_len;
  socklen_t peer_addr_len;
  struct sockaddr_in peer_addr;

  ...

  peer_addr_len = sizeof (struct sockaddr_in);

  recv_len = recvfrom (sock_fd, (void *)pkt, sizeof (struct pkt_buf), 0, (struct sockaddr *)&peer_addr, &peer_addr_len);

  ...

아... 된다.................... -_- 이런 망할 manpage! 왜 안알려준거야!! 했지만 이건 나의 무지였다... manpage를 잘 읽어보니...

The address_len argument is a value-result argument, initialized to the size of the
buffer associated with
address, and modified on return to indicate the actual size of
the address stored there.


라고 쓰여져있다... 결국 manpage 대충 읽은 댓가로 오늘 12시간을 이렇게 보내버렸다... -.-
Posted by 강군님

댓글을 달아 주세요

  1. Favicon of https://trickman.net 트릭맨 2019.09.02 12:00 신고  댓글주소  수정/삭제  댓글쓰기

    몇 시간? 헤메다가 님의 글을 보고 해결했습니다.
    UDP를 오랫동안 했지만 이런문제는 없었는데...ㅋㅋ