Unity3d HttpWebRequest 비동기 형식 사용하기
프로그래밍 2018. 7. 26. 17:08
간단한 GET 형식으로 사용할 때는 WWW가 편하고 좋다.
하지만 일부 사이트는 User-Agent 값을 읽어 막는 곳이 있었다.
그래서 User-Agent값을 수정하려고 했지만, 지원하지 않았다.
아래 코드는 User-Agent값 수정이 자유롭고,
동기모드 사용시, 유니티 메인쓰레드가 멈춰 게임 화면이 멈추게 되는데,
Coroutine과 HttpWebResponse 비동기 모드를 사용하면 멈춤 현상을 해결할 수 있다.
비동기 모드 사용시 주의 점은 메인쓰레드가 아닌 곳에서 유니티 오브젝트 또는 함수를 사용하면
get_isActiveAndEnabled can only be called from the main thread. 같은 오류가 발생한다.
제대로 하려면 쓰레드간 통신을 위한 큐를 만들고
메인쓰레드가 그 큐를 읽어 처리를 하면 되겠지만,
간단히 웹에 대한 결과만 얻어오면 되니, 그냥 간단하게 만들었다.
코루틴 비동기 함수가 끝났는지를 체크할 수 있는 로컬 변수 isDone을 정의해 사용했다.
비동기 함수 완료 콜백함수(타 쓰레드)에서 가져올 데이터가 있다면 로컬 변수에 저장 시켜야 한다.
여기서는 text에 저장시켰다.
text에 저장시킨 후, 즉 사용할 모든 데이터를 저장시킨 후,
맨 마지막에 isDone을 true값으로 변경해야 원자성을 보장할 수 있겠다.
아래 코드를 참고해 적절히 수정해서 쓰면 좋을 것 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | [SerializeField] Text m_text; IEnumerator TestWWW( string url) { bool isDone = false ; string text = null ; /* using (WWW www = new WWW(url)) { yield return www; m_text.text = string.IsNullOrEmpty(www.error) ? "no error" : www.error; m_text.text = www.text; }*/ // for https ServicePointManager.ServerCertificateValidationCallback = delegate { return true ; }; /* // sync HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); httpWebRequest.UserAgent = ""; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { m_text.text = reader.ReadToEnd(); } */ // async HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url); httpWebRequest.BeginGetResponse( new AsyncCallback((IAsyncResult iarres) => { try { using (HttpWebResponse response = (HttpWebResponse)httpWebRequest.EndGetResponse(iarres)) { using (StreamReader streamReader = new StreamReader(response.GetResponseStream())) { // can only be called from the main thread //m_text.text = streamReader.ReadToEnd(); text = streamReader.ReadToEnd(); isDone = true ; } response.Close(); } } catch (Exception e) { } }), null ); while (!isDone) yield return null ; m_text.text = text; } |