1. 개요
SocketIOClient를 사용하여 유니티 에디터에서 비동기 소켓 프로그램을 작성하고 테스트 하여본다.
[참고] 안드로이드 플랫폼에서는 동작이 안되는 것 같다. 맨 아래 후기 참조.
2. 유니티에 nuget 패키지 관리자 설치하기
Window 메뉴>Packet Manager
좌측 상단 + 클릭하고 'Add package from git URL 선택
https://github.com/GlitchEnzo/NuGetForUnity.git?path=/src/NuGetForUnity
입력하고 Add를 클릭하면 설치가 진행되고 설치가 완료되면 유니티 에디터에 NuGet 메뉴탭이 추가됩니다.
3. nuget을 이용하여 SocketIOClient 설치하기
nuget을 실행하고 검색창에 SocketIOClient 검색하고 설치하기 버튼을 클릭한다.
[추가] Newtonsoft.json도 함께 설치한다.
4. 스크립트 작성하기
유니티 Scene에서 Main Camera에 Add Compoent하기를 하여 MySocketIOClient.cs 스크립트를 아래와 같이 추가한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using SocketIOClient;
using System;
using System.Threading.Tasks;
using Newtonsoft.Json;
public class MySocketIOClient : MonoBehaviour
{
SocketIOClient.SocketIO socket;
async void Start()
{
System.Net.ServicePointManager.SecurityProtocol =
System.Net.SecurityProtocolType.Tls12 |
System.Net.SecurityProtocolType.Tls11 |
System.Net.SecurityProtocolType.Tls;
socket = new SocketIOClient.SocketIO("http://localhost:3000");
Debug.Log("Start #1");
socket.OnConnected += async (sender, e) =>
{
Debug.Log("OnConnected..");
};
await socket.ConnectAsync();
Debug.Log("Start #2");
await SendMessage("student", "myroom/12345", "history", "history","unity useer");
}
public async Task SendMessage(string role, string room, string classId, string userId, string userName)
{
try
{
var message = new
{
role,
room,
class_id = classId,
user_id = userId,
user_name = userName
};
string jsonMessage = JsonConvert.SerializeObject(message);
Debug.Log($"Sending message: {jsonMessage}");
await socket.EmitAsync("create or join", jsonMessage);
Debug.Log("Message sent successfully");
}
catch (Exception ex)
{
Debug.LogError($"Error sending message: {ex.Message}");
}
}
// Update is called once per frame
void Update()
{
}
}
5. node.js 의 server.js 서버 프로그램은 디음과 같이 작성한다.
const http = require('http');
const socketIo = require('socket.io');
const fs = require('fs');
const path = require('path');
// HTTP 서버를 생성합니다.
const server = http.createServer((req, res) => {
// 간단한 HTML 파일을 제공하는 코드입니다.
if (req.url === '/') {
fs.readFile(path.join(__dirname, 'index.html'), (err, data) => {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(data);
});
} else {
res.writeHead(404);
res.end('Not Found');
}
});
// Socket.IO 서버를 HTTP 서버에 연결합니다.
const io = socketIo(server);
// 클라이언트가 접속하면 실행되는 이벤트 핸들러입니다.
io.on('connection', (socket) => {
console.log('New client connected');
// 클라이언트로부터 메시지를 받으면 실행되는 이벤트 핸들러입니다.
socket.on('create or join', (message) => {
console.log('Message received:', message);
// 받은 메시지를 모든 클라이언트에게 브로드캐스트합니다.
io.emit('message', message);
});
// 클라이언트가 연결을 끊으면 실행되는 이벤트 핸들러입니다.
socket.on('disconnect', () => {
console.log('Client disconnected');
});
});
// 3000번 포트에서 서버를 시작합니다.
const port = process.env.PORT || 3000;
server.listen(port, () => console.log(`Listening on port ${port}`));
유니티에서 서버로 메시지 전송이 되는지 확인한다.
[추가] SocketIOClient 를 사용한 위 코드는 유니티 에디터에서 https를 이용한 소켓통신을 하는데 연결이 안되고 reconnect만 반복되면서 실패를 하였다. 위에서 사용한 라이브러리가 security protocol을 지원한다고는 하는데 서버 설정을 바꾸어 보아도 도저히 연결이 안된다. 즉 https://server_url 와 같이 연결을 시도하였다. 파이썬 코드에서는서버 접속이 잘 된다. 서버 문제는 아닌다. 그러나 유니티 에디터에서는 안된다. 결국 nginx에서 proxy를 사용하여 redirect한 포토번호를 직접 이용하여 연결하였다. 즉 https가 아닌 http://server_url:6080 이런식으로 ... 하여야 했다. 또한 다음 단계로 유니티 에디터에서 안드로이드 프로젝트로 export하여 오큘러스에서 사용하려고 시도 하였다. 퍼미션을 아무리 수정해도 안드로이드에서는 위 방식도 연결이 안된다. SocketIOClient는 안드로이드에서는 사용이 어려운것 같다. 결국 유료 Asset인 BestHTTP를 사용하였다.