정보
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입니다.
혹시 다음과 같은 증상을 겪으시거나, 해결하신 분은 답변 부탁드립니다.