Machineboy空
Http통신과 WebSocket 통신 본문
Http 통신 | WebSocket 통신 |
Client의 요청(Request)이 있을 때만 Server가 응답(Response)하여 해당 정보를 전송하고 곧바로 연결을 종료하는 방식 | Server와 Client가 특정 Port를 통해 실시간으로 양방향 통신하는 방식 |
요청을 보내서 server의 응답을 기다리는 어플리케이션 개발에 주로 사용 | 실시간 동영상 Streaming, 온라인 게임 |
- 01. Socket을 통한 실시간 통신
- 실시간 국제정거장(ISS)위치 정보를 1분 마다 받아오기 위해 활용했음
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//WebSocketSharp Plugins다운로드 후 라이브러리 사용
using WebSocketSharp;
//JSON 정보 구성
//{
// "iss_position": {
// "longitude":"-137.1979",
// "latitude":"-10.2846"
// },
// "timestamp":1693465485,
// "message":"success"
// }
//JSON 구조 똑같이 만들어 두기
//변수명 JSON의 키값과 완전히 동일해야 함.
[Serializable]
public struct ISSPosition
{
public string longitude;
public string latitude;
}
[Serializable]
public class ISSData
{
public ISSPosition iss_position;
public long timestamp;
public string message;
}
public class SocketTest : MonoBehaviour
{
public string ip = ""; //ip주소값
public string port = ""; //port: 서버에 접속하기 위한 플러그 같은 것
public WebSocket socket = null;
public ISSData issData;
// Start is called before the first frame update
void Start()
{
try
{
//192.168.1.48:3030
socket = new WebSocket("ws://" + ip + ":" + port);
//socket = new WebSocket("ws://7cd2-110-70-53-53.ngrok-free.app/iss");
socket.OnMessage += Recv;
socket.OnOpen += OnOpen;
socket.OnClose += OnClose;
socket.OnError += OnError;
Connect();
}
catch
{
print("1111111");
}
}
//Socket에 연결하기
public void Connect()
{
socket.Connect();
}
//Socket 서버에 연결 끊기
public void DisConnect()
{
if (socket.IsAlive)
{
socket.Close();
}
}
//WebSocket에 연결되었을 때 호출되는 이벤트
void OnOpen(object sender, EventArgs e)
{
print("2222");
}
//WebSocket에서 메시지가 날아왔을 때 호출되는 이벤트 (원래는 webSocket.onmessage가 내장이지만 매개 변수 형태 같게 하여 변형하여 씀)
public void Recv(object sender, MessageEventArgs e)
{
//print(e.Data);
try
{
issData = JsonUtility.FromJson<ISSData>(e.Data);
}
catch
{
}
}
//WebSocket이 닫히면 호출되는 이벤트
public void OnClose(object sender, CloseEventArgs e)
{
DisConnect();
}
//WebSocket에 에러가 나면 호출되는 이벤트
public void OnError(object sender, ErrorEventArgs e)
{
print( "error : " + e.Message);
//{
// "iss_position": {
// "longitude":"-137.1979",
// "latitude":"-10.2846"
// },
// "timestamp":1693465485,
// "message":"success"
// }
}
// Update is called once per frame
void Update()
{
}
//어플리케이션이 종료되면 자동으로 연결되지 않도록
private void OnApplicationQuit()
{
DisConnect();
}
}
01. | WebSocket용 플러그인, 라이브러리 다운로드 | using WebSocketSharp; | |
02. | 서버 JSON정보 구조와 같이 구조 짜두기 | ||
03. | 필요 변수 적어두기 | ip (internet Protocol) | 인터넷상에서 사용하는 주소체계 |
port | IP주소가 가리키는 PC에 접속할 수 있는 통로(채널) | ||
JSON 구조의 structure | |||
04. | Start함수에서 Connect ApplicationQuit에서 Disconnect |
||
05. | SocketSharp 라이브러리에서 사용하는 내장 함수들 | socket.Connect(); | Socket서버에 접속 |
socket.OnOpen(); | WebSocket에 연결되었을 때 호출되는 이벤트 | ||
socket.OnMessage(); | WebSocket에서 메세지가 날아오면 호출되는 이벤트 | ||
socket.OnError(); | WebSocket에 에러가 나면 호출되는 이벤트 | ||
socket.OnClose(); | WebSocket이 닫히면 호출되는 이벤트 | ||
socket.Disconnect(); | Socket서버에 연결 끊기 |
- Socket : 네트워크 통신에서 종단의 교신점, 서버에 접속하기 위한 연결 부분
- 예시) 전화 서비스: 송신자 - 전화 - 수신자
- 송신자: 전화번호를 누른다 (전화번호: 소켓 주소)
- 수신자: 수화기를 든다.
- 전화 = 소켓
- 예시) 전화 서비스: 송신자 - 전화 - 수신자
네트워크의 기본
특정 서버에 접속하기 위해서는 다른 PC를 가리키는 주소를 알아야 한다.
- IP(Internet Protocol) : 인터넷에 연결되어 있는 각 컴퓨터는 숫자로 이루어진 고유 주소를 가지며, 이를 IP 주소라고 한다.
- Port: IP내에서 애츨리케이션 상호 구분을 위해 사용하는 번호로, 포트 숫자는 IP주소가 가리키는 PC에 접숙할 수 있는 통로(채널)을 의미한다.
- 02. Http를 활용한 요청 시 통신
- 어플리케이션 접속 당시 시간이 낮인지 밤인지를 일출, 일몰 정보를 담은 서버를 활용해 UI 표시
- Http Method(8)
GET | 서버로부터 데이터를 취득한다. |
POST | 서버에 데이터를 추가,작성한다. |
PUT | 서버의 데이터를 갱신,작성한다. |
DELETE | 서버의 데이터를 삭제한다. |
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
//http 통신 활용 시 활용하는 라이브러리
using UnityEngine.Networking;
//JSON 구조 변수명 그대로 활용
[Serializable]
public class SunriseNSunset
{
public string sunrise;
public string sunset;
public string nowTime;
public bool isDay;
public bool isNight;
}
//Http Method (총 8개)
public enum EJRequestType
{
GET, //조회, 서버로부터 데이터를 취득
POST, //등록, 서버에 데이터를 추가, 작성 등
PUT, //수정, 서버의 데이터를 갱신, 작성
DELETE, //삭제, 서버의 데이터를 삭제
TEXTURE
}
public class EJHttpInfo
{
public EJRequestType EJRequestType;
public string url = "";
public string body;
public Action<DownloadHandler> onReceive;
//DownloadHandler: 데이터의 다운로드 제어
//UploadHandler: 데이터의 업로드 제어
public void Set(
EJRequestType type,
string u,
Action<DownloadHandler> callback, //데이터 다운로드 시, 실행할 콜백 함수?
bool useDefaultUrl = true)
{
EJRequestType = type;
if (useDefaultUrl) url = "http://172.16.16.228:3000";
//172.16.16.228:3000/api/weather/dayLight
url += u;
onReceive = callback;
}
}
public class EJhttpManager : MonoBehaviour
{
static EJhttpManager instance;
public static EJhttpManager Get()
{
if (instance == null)
{
GameObject go = new GameObject("EJhttpManager");
go.AddComponent<EJhttpManager>();
}
return instance;
}
private void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void SendRequest(EJHttpInfo httpInfo)
{
StartCoroutine(CoSendRequest(httpInfo));
}
IEnumerator CoSendRequest(EJHttpInfo httpInfo)
{
UnityWebRequest req = null;
switch (httpInfo.EJRequestType)
{
case EJRequestType.GET:
//Get방식으로 req 에 정보 셋팅
req = UnityWebRequest.Get(httpInfo.url);
break;
case EJRequestType.POST:
req = UnityWebRequest.Post(httpInfo.url, httpInfo.body);
byte[] byteBody = Encoding.UTF8.GetBytes(httpInfo.body);
req.uploadHandler = new UploadHandlerRaw(byteBody);
//헤더 추가
req.SetRequestHeader("Content-Type", "application/json");
break;
case EJRequestType.PUT:
req = UnityWebRequest.Put(httpInfo.url, httpInfo.body);
break;
case EJRequestType.DELETE:
req = UnityWebRequest.Delete(httpInfo.url);
break;
case EJRequestType.TEXTURE:
req = UnityWebRequestTexture.GetTexture(httpInfo.url);
break;
}
yield return req.SendWebRequest();
//만약에 응답이 성공했다면
if (req.result == UnityWebRequest.Result.Success)
{
//print("네트워크 응답 : " + req.downloadHandler.text);
if (httpInfo.onReceive != null)
{
httpInfo.onReceive(req.downloadHandler);
}
}
//통신 실패
else
{
print("네트워크 에러 : " + req.error);
}
}
}
1 | JSON 데이터 구조를 짜둔다. 변수명과 똑같이 | ||
2 | RequestType을 정해둔다. | (GET/ POST/ PUT/ DELETE/ TEXTURE) | |
3 | SendRequest | 서버에게 REST API를 요청하는 함수 | |
CoSendRequest | 서버에 요청을 보내고 응답이 올때까지 다른 일들을 처리하기 위해서 코루틴으로 작성 | ||
switch문으로 requestType별 동작 정리 | req = UnityWebRequest.Get(httpInfo.url) | ||
'Game > Unity' 카테고리의 다른 글
LayerMask.GetMask / LayerMask.NameToLayer (0) | 2023.09.12 |
---|---|
코루틴 없이 Lerp로 n초 동안 scale, position 변화 (0) | 2023.09.11 |
오브젝트 FadeOut으로 사라지게 하기, Material-Transparent활용 (0) | 2023.09.06 |
Unity Rendering Pipelines (0) | 2023.09.06 |
누적되는 Tips (0) | 2023.09.05 |