마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

코틀린으로 Socket.io를 구현하면서, 여러 애로사항들이 발생합니다.

0 추천

정보

1. 서버의 구성은 Nest.js를 이용하여 제작되었습니다.

import {
  ConnectedSocket,
  MessageBody,
  SubscribeMessage,
  WebSocketGateway,
} from "@nestjs/websockets";

import { Socket } from "socket.io";
import { PrismaService } from "./prisma.service";
import { getSubByToken } from "./util/token";

@WebSocketGateway(81, { namespace: "chat" })
export class ChatGateway {
  constructor(private prisma: PrismaService) {}

  

  @SubscribeMessage("setting")
  async connectSocket(
    @MessageBody() data: string,
    @ConnectedSocket() client: Socket
  ) {
    const [token] = data;
    const sub: string = getSubByToken(token);
    const user = await this.prisma.user.findFirst({ where: { sub } });
    const roomIdList = await this.prisma.chattingParticipant.findMany({
      select: { chattingId: true },
      where: { userId: user.id },
    });

    roomIdList.map((room) => {
      client.join(String(room.chattingId));
    });
  }

  @SubscribeMessage("join")
  async connectSomeone(
    @MessageBody() data: string,
    @ConnectedSocket() client: Socket
  ) {
    const [token, roomId] = data;
    const user = await this.prisma.user.findUnique({
      where: { sub: getSubByToken(token) },
    });
    await this.prisma.chattingParticipant.create({
      data: { chattingId: Number(roomId), userId: user.id },
    });
    client.join(roomId);
    const entryMessage = `${user.name}`;
    client.broadcast.to(roomId).emit("entryUser", entryMessage);
  }

  @SubscribeMessage("sendMessage")
  async sendMessage(
    @MessageBody() data: string,
    @ConnectedSocket() client: Socket
  ) {
    const [token, roomId, message] = data;
    const clientUser = await this.prisma.user.findUnique({
      where: { sub: getSubByToken(token) },
    });
    client.broadcast
      .to(roomId)
      .emit("sendMessage", [clientUser.name, clientUser.profileImg, message]);
  }

  @SubscribeMessage("leave")
  async leaveChattingChanel(
    @MessageBody() data: string,
    @ConnectedSocket() client: Socket
  ) {
    const [token, roomId] = data;
    const sub: string = getSubByToken(token);
    const user = await this.prisma.user.findFirst({ where: { sub } });
    await this.prisma.chattingParticipant.deleteMany({
      where: { userId: user.id, chattingId: Number(roomId) },
    });
    client.leave(roomId);
  }

  @SubscribeMessage("disconnect")
  async disConnectSocket(@ConnectedSocket() client: Socket) {
    client.disconnect();
  }
}

서버의 중요 구성은 다음과 같습니다.

2. 여기서 발생하는 에러는 다음과 같습니다.

error: io.socket.engineio.client.EngineIOException: xhr poll error 

3. 코틀린 소켓 io 연동 주요코드는 다음과 같습니다.

        try {
            socket = App.get()
            socket.connect()

            socket.on(Socket.EVENT_CONNECT_ERROR, onConnectError)
            socket.on(Socket.EVENT_CONNECT, onConnectSuccess)
            Log.d(TAG, "onCreate: ${socket.toString()}")

            emitSetting()
            emitJoin()
            socket.on("sendMessage", sendMessage)

        } catch (e: URISyntaxException) {
        Log.d(TAG, "onCreate:  에러 ${e.printStackTrace()}")
        e.printStackTrace()
    } catch (ioe: IOException) {
        // 소켓 생성 과정에서 I/O 에러 발생.
        Log.e(TAG, "onCreate: ${ioe}", )
    } catch (uhe: UnknownHostException ) {
        // 소켓 생성 시 전달되는 호스트(www.unknown-host.com)의 IP를 식별할 수 없음.
        Log.e(TAG, "onCreate: ${uhe}", )
    } catch (se:SecurityException ) {
        Log.e(TAG, "onCreate: ${se}", )

        // security manager에서 허용되지 않은 기능 수행.
    } catch (se:IllegalArgumentException ) {
        Log.e(TAG, "onCreate: ${se}", )
        // 소켓 생성 시 전달되는 포트 번호(65536)이 허용 범위(0~65535)를 벗어남.
    }

    catch (se: SocketTimeoutException) {
        Log.e(TAG, "onCreate tiemout: ${se}", )
        // 소켓 생성 시 전달되는 포트 번호(65536)이 허용 범위(0~65535)를 벗어남.
    }
    catch (se: IllegalBlockingModeException) {
        Log.e(TAG, "onCreate : ${se}", )
        // 소켓 생성 시 전달되는 포트 번호(65536)이 허용 범위(0~65535)를 벗어남.
    }
    catch (se: SocketException) {
        Log.e(TAG, "onCreate : ${se}", )
        // 소켓 생성 시 전달되는 포트 번호(65536)이 허용 범위(0~65535)를 벗어남.
    }
    catch (se: NullPointerException) {
        Log.e(TAG, "onCreate : ${se}", )
        // 소켓 생성 시 전달되는 포트 번호(65536)이 허용 범위(0~65535)를 벗어남.
    }


----------



@HiltAndroidApp
class App : Application() {
    companion object {
        private lateinit var socket: Socket
        fun get(): Socket {
            try {
                socket = IO.socket("http://192.168.167.182:3000")
            } catch (e: URISyntaxException) {
                Log.e("socket", "get: ${e}")
                e.printStackTrace();
            }

            return socket
        }
    }
}

4. 안드로이드는 10버전을 사용하고, 타겟버전은 30입니다.

혹시 다음과 같은 증상을 겪으시거나, 해결하신 분은 답변 부탁드립니다.

hifl (670 포인트) 님이 2021년 11월 25일 질문

1개의 답변

0 추천

커넥션 문제는 제가 테스트해본 결과로는 라이브러리를 업데이트 해주어야 하는 것 같습니다.

implementation ('io.socket:socket.io-client:2.0.1')

몇 번 테스트 후 확인해 보니, 10.0.2.2에서도 에러없이 잘 연결이 됩니다.

spark (227,530 포인트) 님이 2021년 11월 25일 답변
spark님이 2021년 11월 25일 수정
지금 라이브러리 버전이 2.0.1인데도 똑같은 오류가 뜹니다
저 같은 경우는 Github 예제에 라이브러리 버전만 업데이트를 하니 잘 동작을 합니다.]
NodeJS server: https://github.com/socketio/socket.io/tree/master/examples/chat
Android Client: https://github.com/nkzawa/socket.io-android-chat
...