티스토리 툴바


L4를 통해 VIP로 UDP 통신하기 

에서 VIP 로 socket 을 binding 해서 응답을 보낼 수 있는데,
이때 real ip로는 역시 통신을 할 수 없기때문에 유연성이 떨어지게 되는 문제가 있다.

결국, socket header를 조작해서
req. socket 의 수신 IP를 res. socket 의 송신 IP로 셋팅해서 해결한다.

일반적으로 사용되는 recvfrom() 대신,
IP_PKTINFO 를 통해 socket header 에서 수신 IP를 받아올 수 있는 recvfromto() 쯤을 만들어서 사용한다.
ssize_t recvfromto(int s, void *buf, size_t len, int flags, 
			     struct sockaddr *from, socklen_t *fromlen, struct sockaddr_in *to)
{
	struct msghdr msg;
	struct iovec iov[1];
	int n;
	struct cmsghdr *cmptr;
	union {
		struct cmsghdr cm;
		char control[CMSG_SPACE(sizeof(struct in_addr)) +
					 CMSG_SPACE(sizeof(struct in_pktinfo))];
	} control_un;
	int on = 1;
	struct in_pktinfo pktinfo;
 
	/* Try to enable getting the return address */
	setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
	msg.msg_control = control_un.control;
	msg.msg_controllen = sizeof(control_un.control);
	msg.msg_flags = 0;
	msg.msg_name = from;
	msg.msg_namelen = *fromlen;
	iov[0].iov_base = buf;
	iov[0].iov_len  = len;
	msg.msg_iov = iov;
	msg.msg_iovlen = 1;
	if ( (n = recvmsg(s, &msg, flags)) < 0 )
		return n;	 /* Error */
	*addrlen = msg.msg_namelen;
	if ( to ) {
		bzero(to, sizeof(struct sockaddr_in));
		to->sin_family = AF_INET;
		if ( msg.msg_controllen < sizeof(struct cmsghdr) ||
			 (msg.msg_flags & MSG_CTRUNC) )
			return n;	 /* No information available */
		for ( cmptr = CMSG_FIRSTHDR(&msg) ; cmptr != NULL ;
			  cmptr = CMSG_NXTHDR(&msg, cmptr) ) {
			if ( cmptr->cmsg_level == IPPROTO_IP &&
				 cmptr->cmsg_type == IP_PKTINFO ) {
				memcpy(&pktinfo, CMSG_DATA(cmptr), sizeof(struct in_pktinfo));
				memcpy(&to->sin_addr, &pktinfo.ipi_addr, sizeof(struct in_addr));
			}
		}
	}
	return n;
}

그리고, 응답할때도 sendto() 대신,
socket header 에 송신 IP를 지정해서 보낼 수 있게, sendtofrom() 쯤을 만들어서 사용한다.
ssize_t sendtofrom(int  s,  const  void *buf, size_t len, int flags, 
			      const struct sockaddr *to, socklen_t tolen, struct sockaddr_in *from)
{
	struct iovec iov = { buf, len };
	struct {
		struct cmsghdr cm;
		struct in_pktinfo ipi;
	} cmsg = {
		.cm = {
			.cmsg_len = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo),
			.cmsg_level = SOL_IP,
			.cmsg_type = IP_PKTINFO,
		},
		.ipi = {
			.ipi_ifindex = 0,
			.ipi_spec_dst = from->sin_addr,
		},
	};
	struct msghdr m = {
		.msg_name = to,
		.msg_namelen = tolen,
		.msg_iov = &iov,
		.msg_iovlen = 1,
		.msg_control = &cmsg,
		.msg_controllen = sizeof(cmsg),
		.msg_flags = 0,
	};
 
	return sendmsg(s, &m, MSG_NOSIGNAL|MSG_DONTWAIT);
}

자, 이제 RIP든 VIP든 어디로 오던지, 자유롭게 통신을 할 수 있게 된다.

ps. 그런데, 이런 건 기본 library 에 포함되야 하는 것 아닌가??? ㅡㅡ
 
저작자 표시 비영리 변경 금지
TAG l4, socket, udp, VIP

L4를 통해 VIP로 UDP 통신하기

tech 2011/12/17 02:35 Posted by cman
udp 통신을 하던 서버의 가용성을 높이기 위해서 L4로 묶어서 VIP로 서비스를 하려던 중 문제가 발생했다!

Real IP로는 잘 서비스되던게, VIP로 붙으려니 안되는게 아닌가...

tcpdump를 떠보니, 클라이언트에 응답이 오지 않는다.


서버쪽에서는
09:48:56.904498 IP 10.64.66.227.43551 > 10.22.8.42.7708: UDP, length 36
09:48:56.908395 IP 10.99.112.26.7708 > 10.64.66.227.43551: UDP, length 45
와 같이, 요청이 와서 처리하고 응답을 하는 것 같은데

클라이언트쪽에서는
09:48:47.682630 IP 10.64.66.227.43551 > 10.22.8.42.7708: UDP, length 36
와 같이, 요청만 보내고 응답이 안 온다.



tcp 통신과 비교를 해보니,
12:28:02.890518 IP 119.205.250.30.48738 > 10.25.233.27.7708: P 1:23(22) ack 1 win 5840
12:28:02.890522 IP 10.25.233.27.7708 > 119.205.250.30.48738: . ack 23 win 5840
와 udp 를 다시 보니,
12:13:17.340230 IP 10.64.66.227.38715 > 10.22.8.42.7708: UDP, length 36
12:13:17.344213 IP 10.99.112.26.7708 > 10.64.66.227.38715: UDP, length 45
tcp에서는 VIP로 요청을 받고, VIP로 응답을 하는데,
udp에서는 VIP로 요청을 받고, RIP로 응답을 하고 있는 것이다.


udp는 기본적으로 단방향 통신이기 때문에, 응답이라는 것도 사실 새로운 전달일 뿐인 것이다.
다시말해, socket이 특정 IP로 binding 되지 않았다면,
응답시에 RIP로 binding 되어서 응답하지 않았나 하는 것이다.


간단한 테스트를 해보았다.

사용하는 iMac에 유선/무선 2개 IP를 할당받아, nc로 udp 통신을 해보았다.
$ echo OK | nc -u -l 7708
와 같이 default binding을 하자,
클라이언트에서 iMac의 1번 IP에 대해 요청하자, 요청도 1번, 응답도 1번으로 잘 응답하였지만,
2번 IP에 대해서, iMac에서 요청을 2번으로 받았지만, 응답을 1번으로 하는 것이 아닌가!!

그래서, 직접 2번 IP로 binding해서 서버를 올려보았다.
$ echo OK | nc -u -l 10.64.66.216 7708
역시, 직접 2번 IP로 binding을 하니,
클라이언트에서 2번 IP에 대해 요청을 했을때, 요청도 2번, 응답도 2번으로 제대로 응답하는 것을 확인할 수 있었다!


이 기본적인 것 때문에, 일주일동안 한참을 헤매고, 여러사람을 괴롭혔다.
기본에 충실하자!!
 
저작자 표시 비영리 변경 금지
TAG l4, udp, VIP

15살 E36 318is 정비 노트

life 2011/10/24 23:20 Posted by cman
한때,, speed limit 까지 찍어봤던 나의 비머가~

저번주, 정기검사에서 NOx 과다 배출로 빠꾸를 먹었다.ㅠㅠ

바로 옆, 성산AS센터에 입고하였는데,

점검항목이 너무 광범위하다고 우선, 검사료 3만원을 청구한다. 쩝~

그리고, 오후에 전화로 검사하기도 전에 엔진 가스켓 누유로 점화플러그 오염이 심하다고,

그것부터 보자고 한다. 아무래도 점화플러그 오염으로 연소에 문제가 있으면,...

견적이 대략 80~ ㅠㅠ


문제 확인도 안되었는데, 그냥 한번 해보기에는 비용이 너무 크다고 생각되어,

우선, 그냥 출고... 다행히(?) 검사도 안해봐서 검사료는 면제.

그리고, 인터넷을 좀 뒤져서 "양천수입차전문공업사"를 찾았다.


여기에서는, 배출가스 중 NOx 만 높은 건 비정상적인 것 같다고,

그냥 촉매 예열이 좀 덜 되어 그렇지 않았겠냐고,

일단, 센터 얘기를 하니, 스캔을 함 보자고 한다.


앗! 바로,

(062) 3E MISFIRE SEVERAL CYLINDERS

라고 뜬다. (센터에선 머지?? 스캔 한번이면 바로 나오는데... ㅡㅡ)

어쩐지,, 최근에 힘도 딸리고...


암튼, 그래서 가스켓쪽 손을 보기로 했는데,

아직 딱딱하게 굳은 정도가 아니라 실리콘으로 틈새만 좀더 막기로 했다.

 (아래쪽 볼트부분이 검게 누유되어 찌든 모습.. ㅠㅠ)


그런데,, 막상 뚜껑을 열어보자...

 (역시나,, 점화플러그쪽 밸브를 뽑으니, 흥건히 오일이 묻어 나오는... ㅡㅡ) 
 
 안쪽을 들여다보니,,

 (점화플러그룸에 오일이 흥건하네... 이러니, 제대로 연소가 안되지...)

점화플러그는...

 (우메~ 이런 상태가 된 줄도 모르고...)

암튼, 깨끗이 갈고 닦고...

부품 교체 없이~ 잘 정비해서...

재검에 패쓰!~ ^^


정비료는 단돈 8만원!

 (두분이 1시간가량 작업했으니... 시간당 4만원???)


암튼, 공인센터는 편안히 "서비스"를 받을 수 있는 장점이 있는 반면,,

공업사에서는 직접 보면서, 차 상태를 파악하는데 도움이 되는 것 같다. (가격도 저렴하고~ ^^)


언제, 또 한번 speed limit 까지 함 달려 줘야 하는데~


PS. 집에 와서 엔진에서 왠 쇠소리가 덜거덕거려서...ㅠㅠ
     걱정하며, 또 언제 가 보나 했는데,,
     혹시~하고 본넷을 열어보니,, 엔진 고정 나사가 덜 조여있는게 아닌가! ㅡㅡ
     마무리가~ @@
     암튼,, 공업사에서 열심히 보고 배웠으니,, 복습하라는 건가~
     잘 조이고,, 이젠 씽씽~~