Dart/Flutter

[Dart/Flutter] HttpException: Connection closed while receiving data 문제 해결

Flask를 사용하여 로컬 서버를 만들어, 이를 공용 IP로 접속하여 데이터를 받으려고 하는데, 

HttpException: Connection closed while receiving data 라는 에러가 발생하였습니다.

이걸 해결하기 위해 했던 여러가지 방법을 소개해드리겠습니다! 제가 시도했던 방법들을 순서대로 나열할 것이기 때문에, 어느 순서에서 되게 될지는 모르겠습니다

 

1. 안드로이드 스튜디오 에뮬레이터 proxy 설정

이걸로 해결했다는 분들 많으시던데, 저는 이걸로 안되더라구요. 실패!

 

 

2. 안드로이드 스튜디오 에뮬레이터(플러터) 보안 설정

// xml/network-security-config.xml
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">example.com</domain>
    </domain-config>
</network-security-config>
// AndroidManifest.xml
<application
    android:networkSecurityConfig="@xml/network_security_config"
    ... >
    ...
</application>

 android/app/src/main/res에 xml 폴더를 추가하시고, network-security-config.xml 파일을 만들어주세요.

그리고 첫번째 부분의 코드를 적고 저장한 뒤, AndroidManifest.xml에 두번째 부분의 코드를 적고 저장해주세요. 

(개발중에만 사용하고, 실제 배포시에는 빼주시는게 좋아요)

 

 

3. Dio 사용 함수 변경

Future<void> play(String url) async {
    try {
      Map<String, String> header = {'Content-Type': "audio/wav'", "Connection": "keep-alive"};
      Directory tempDir = await getTemporaryDirectory();
      String tempPath = '${tempDir.path}/temp_audio.wav';
      Response response = await Dio(
        BaseOptions(
          connectTimeout: Duration(seconds: 60),
          receiveTimeout: Duration(seconds: 60),
          sendTimeout: Duration(seconds: 60),
          headers: header,
          persistentConnection: true,
          method: 'GET',
          responseType: ResponseType.bytes
        ),
      ).download(url, tempPath,
          options: Options(
            headers: header,
            persistentConnection: false,
          ), onReceiveProgress: (received, total) {
        if (total != -1) {
          print('Downloading: ${(received / total * 100).toStringAsFixed(0)}%');
        }
      });
      print('Download Completed: ${response.statusCode}');

      } else {
        print('File does not exist at path: $tempPath');
      }
    } on DioError catch (e) {
      print('Dio error: $e');
      if (e.response != null) {
        print('Dio error response data: ${e.response?.data}');
        print('Dio error response headers: ${e.response?.headers}');
        print('Dio error response statusCode: ${e.response?.statusCode}');
      } else {
        print('Dio error request: ${e.requestOptions}');
        print('Dio error message: ${e.message}');
      }
    } catch (e) {
      print('Error starting player: $e');
    }
  }

connectionTimeout, receiveTimeout, sendTimeout 등을 바꿨는데, 사실 이거는 굳이 안건드리셔도 될것 같습니다! 이거 바꿨어도 어차피 안됬었거든요… 그래도 적어봤습니다.

 

여기까지가 클라이언트 측에서 수정한 내용들이고, 이후 수정은 서버에서 하였습니다!

 

4. Flask 서버 환경 개선

flask에 gunicorn을 추가하면 여러가지 설정이 가능합니다.
먼저 gunicorn을 설치해주세요.
pip install gunicorn

기존의 flask 실행할 때 python app.py 라면, gunicorn을 사용하여 실행할 때는 아래와 같이 실행하면 됩니다.

gunicorn app.app

하지만 우리는 추가 설정을 하기 위해 gunicorn을 설치한 것이니, 추가 설정을 해보도록 하겠습니다.

실행 파일과 같은 위치에 ‘service_config.py’를 만들어주세요.

# service_config.py

# 서버 바인딩 설정
bind = '0.0.0.0:8000'

# 워커 설정
workers = 4  # 워커 프로세스 수
worker_class = 'gevent'  # 워커 클래스 (gevent 사용 예시)
worker_connections = 1000  # gevent 워커당 최대 연결 수

# 타임아웃 설정
timeout = 30  # 타임아웃 설정 (초)
keepalive = 2  # 유지 시간 설정 (초)

# 로그 설정
accesslog = '/path/to/access.log'  # 접근 로그 파일 경로
errorlog = '/path/to/error.log'  # 에러 로그 파일 경로
loglevel = 'info'  # 로그 레벨 (debug, info, warning, error, critical)

# 보안 설정
limit_request_line = 4094  # 요청 라인 제한 (바이트)
limit_request_fields = 100  # 요청 헤더 필드 수 제한
limit_request_field_size = 8190  # 요청 헤더 필드 크기 제한 (바이트)

# 기타 설정
preload_app = False  # 앱 미리 로드 여부
max_requests = 0  # 워커가 재시작되기 전에 처리할 최대 요청 수
max_requests_jitter = 0  # max_requests에 대한 지터 값 (랜덤하게 추가되는 최대 값)
graceful_timeout = 30  # 우아한 종료를 위한 타임아웃 (초)

본인이 원하는 설정대로 설정하시면 됩니다! 저는 아래와 같이 설정했어요.

# service_config.py

bind = '0.0.0.0:8000'
workers = 4
keepalive = 30
timeout = 30
workers_class = 'gthread'
thread = 10
worker_connections = 10000
timeout = 30

그리고 아래와 같이 실행하시면 됩니다.

gunicorn -c service_config.py app:app

이렇게 4가지 방법을 HttpException: Connection closed while receiving data 문제를 해결했습니다.

아마도 서버의 대역폭 또는 설정이 미흡하여 저런 문제가 생겼던것 같아요.

저와 비슷한 문제를 겪으신 분에게 도움이 되셨으면 좋겠습니다.

읽어주셔서 감사합니다!

Info-Geon

Recent Posts

관절 건강에 좋다는 MSM의 모든 것

MSM은 건강 보조제로 널리 사용되며, 특히 관절 건강을 개선하고 통증을 완화하는 데 도움을 준다고 알려져…

3주 ago

칼슘 보충제 섭취 전 꼭 알아야 할 6가지 필수 정보

칼슘은 우리 몸에서 가장 풍부하게 존재하는 미네랄로, 전체 체중의 약 1-2%를 차지하며 주로 뼈와 치아에…

3주 ago

혈당과 체중 조절을 위해 주목받는 크롬 보충제의 모든 것

크롬은 필수 미량 원소 중 하나로, 인체 내에서 다양한 생화학적 반응에 관여하는 영양소입니다. 주로 혈당…

3주 ago

레시틴은 꼭 알아야 할 6가지 사실

레시틴은 자연적으로 나타나는 물질로, 대개 달걀 노른자, 콩, 해바라기 씨와 같은 식품에서 발견됩니다. 이 물질은…

3주 ago

L-글루타민, 운동 후 근육통과 면역력 저하를 겪고 있는 당신에게 추천하는 영양제

L-글루타민은 우리 몸에 존재하는 아미노산 중 하나로, 단백질 합성과 면역 기능에 중요한 역할을 합니다. 이천년대…

3주 ago

아스타잔틴, 심혈관 건강과 피부에 모두 도움이 된다?

아스타잔틴은 자연에서 발견되는 카로티노이드 계열의 강력한 항산화제입니다. 일반적으로 홍합, 새우, 그리고 특히 연어와 같은 해양…

3주 ago