2016. 6. 8. 17:23
2016-06-04일에 심사를 넣었더니 reject이 되면서 아래처럼 메일이 왔다
Apps are reviewed on an IPv6 network. Please ensure that your app supports IPv6 networks, as IPv6 compatibility is required.
For additional information about supporting IPv6 Networks, please refer to Supporting iPv6 DNS64/NAT64 Networks.
링크된 내용을 보면 NAT64 기반 Networks에서 제대로 접속이 되지 않는다는 내용이다.
2016-06-01 이후로 ipv6만 지원되는 네트웍에 대응하는 코드를 넣지 않으면 reject 되는 정책으로 바뀌었다고 한다.
즉 client에서 ipv6 대응을 하라는 거다.
( ipv6대응이 선택사항이 아니고 무조건 해야된다는 애플의 정책이 맞는건지 모르겠지만... )
이번 프로젝트의 경우 cocos3.4 에서 작업을 하고 있고 , game server에 접속은 직접 만든 socket 라이브러를 사용하고 있다.
따라서 두가지 update를 해야 한다
1. cocos 3.4 에서 사용하는 curl 의 업데이트
2. 직접 만든 tcp/ip socket library 업데이트
언제나 그렇지만 간단한 내용이지만 이래저래 하루 소비했다.
1. cocos 3.4 에서 사용하는 curl 의 업데이트
cocos 3.10버전 이후로 curl에서 ipv6를 지원한다기에
해당 소스와 라이브러만 받아서 직접 업데이트를 했다
첨부한 파일을 받아서 각각 아래 폴더에 복사하면 된다
curl.zip -> 프로젝트루트/cocos2d/external/curl/include/ios/curl
prebuilt.zip -> 프로젝트루트/cocos2d/external/curl/prebuilt/ios
xcode에서 컴파일했을때 아무런 오류가 없었고, Nat64 기반 네트웍에서도 문제 없이 접속이 되었다.
Nat64 네트워크 기반 환경에서 테스트 하는 방법은 아래 URL 보면 Mac에서 설정하는 방법이 나와있다.
Mac은 무조건 El Capitan 버전 이어야 셋팅이 가능하다. ( 짜증나 ~~~~~ )
2. 직접 만든 tcp/ip socket library 업데이트
아래 URL의 내용을 참고로 수정하였다.
// 주소 정보를 가져온다
struct addrinfo * ResolveAddress(const char *addr, char *port, int af, int type, int proto)
{
struct addrinfo hints,
* res = NULL;
int rc = -1;
memset(&hints, 0, sizeof(hints));
if (proto == 0)
{
hints.ai_flags = AI_PASSIVE;
// 이번에 ipv6 작업을 하면서 hints.ai_protocol 값을 넣지 않고, 정보를 가져오게 해서
// ipv6 정보까지 가져오게 하였다
}
else
{
hints.ai_flags = ((addr) ? 0 : AI_PASSIVE);
hints.ai_protocol = proto;
}
hints.ai_family = af;
hints.ai_socktype = type;
// 도메인을 IP주소로 변환하거나, 지정된 도메인 주소의 정보를 가져온다
rc = getaddrinfo(
addr,
port,
&hints,
&res
);
if (rc != 0)
{
return NULL;
}
return res;
}
// 서버에 접속을 한다.
bool Connect(const char * pszAddress, int nPort)
{
struct addrinfo *resremoteAry = NULL; // 원격주소지에 대한 배열 개체
struct addrinfo *resremoteOne = NULL;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
char buf[100] = { 0x00, };
int rc; // return code
char szPort[100];
sprintf(szPort, "%d", nPort);
// Resolve the server's name
#if (_SD_DEV_MOBILE == _SD_DEF_APL)
// iOS에서는 0 값으로 주어서 ipv4, ipv6 모두를 찾게 한다 2016-06-07
resremoteAry = ResolveAddress(pszAddress, szPort, AF_UNSPEC, SOCK_STREAM, 0);
#else
resremoteAry = ResolveAddress(pszAddress, szPort, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
#endif
if (resremoteAry == NULL)
{
assert(!"resremoteAry=NULL");
return false;
}
m_Sock = INVALID_SOCKET;
// ipv6 적용에 따른 루프와 조건분기 추가 2016-06-07
for (resremoteOne = resremoteAry; resremoteOne; resremoteOne = resremoteOne->ai_next)
{
if (resremoteOne->ai_family == AF_INET)
{
sin = (sockaddr_in *)resremoteOne->ai_addr;
inet_ntop(resremoteOne->ai_family, &sin->sin_addr, buf, sizeof(buf));
printf("<server: %d %d %s>\n", resremoteOne->ai_protocol, resremoteOne->ai_socktype, buf);
}
else if (resremoteOne->ai_family == AF_INET6)
{
sin6 = (sockaddr_in6 *)resremoteOne->ai_addr;
inet_ntop(resremoteOne->ai_family, &sin6->sin6_addr, buf, sizeof(buf));
printf("<server: %d %d %s>\n", resremoteOne->ai_protocol, resremoteOne->ai_socktype, buf);
}
// 소켓 생성
m_Sock = socket(resremoteOne->ai_family, resremoteOne->ai_socktype, resremoteOne->ai_protocol);
if (m_Sock == INVALID_SOCKET)
{
assert(!"m_Sock == INVALID_SOCKET");
continue;
}
if (resremoteOne->ai_family == AF_INET6)
{
sin6 = (struct sockaddr_in6*)resremoteOne->ai_addr;
if (nPort > 0 && sin6->sin6_port == 0)
sin6->sin6_port = htons(nPort);
rc = connect(m_Sock, (struct sockaddr*)sin6, resremoteOne->ai_addrlen);
}
else
rc = connect(m_Sock, resremoteOne->ai_addr, resremoteOne->ai_addrlen);
if (rc == SOCKET_ERROR)
{
//assert(!"connection failed"); // 막아 두었음
closesocket(m_Sock);
m_Sock = INVALID_SOCKET;
continue;
}
// 여기까지 왔으면 정상적으로 연결이 되었다는 의미
break;
}
if (resremoteAry)
freeaddrinfo(resremoteAry); // 사용이 끝난 메모리 삭제
if (m_Sock == INVALID_SOCKET) // 이때까지 소켓에 값이 없으면 오류 상황
return false;
......
정상적으로 접속되었으니 기타 필요한 작업들을 한다
return true;
}
★ 중요한점 , 아래 코드를 한 이유
if (nPort > 0 && sin6->sin6_port == 0)
sin6->sin6_port = htons(nPort);
address를 도메인으로 주었을 경우는 문제 없고 sin6_port 에 포트값이 들어 있지만
ip주소를 주어서 접속을 할때는 sin6_port 값이 비어 있는 문제가 발생해 서버 접속이 되지 않는 문제가 있었다.
대상 서버가 Amazon AWS 였는데 , 해당 서버의 셋팅이 문제 인지 정확한 사유는 모르겠지만 위와 같은 코드를 넣어서 문제를 해결 했다.
댓글 없음:
댓글 쓰기