백엔드는 php코드와 apache서버를 이용하였으며

Mingw를 사용해서 전달 받은 코드를 컴파일한다.

 

 

 

 

 

 

'잡동사니' 카테고리의 다른 글

2018/12/01 졸업작품 영상  (0) 2018.12.01
2018/12/01 졸업작품 Doxygen  (0) 2018.12.01
다이렉트x 과제  (0) 2018.06.24
마지막 팀프  (0) 2018.06.24
팀프3  (0) 2018.06.24

환경

서버 : c++

클라 : 유니티

마샬링이 아닌 바이트스트림으로 Serialize 통신

 

 

채팅기능을 구현하여 클라이언트간 한글 통신을 하게 하려고 할때

 

클라이언트에서 Encoding.UTF8.GetBytes(str) 이와같은 형태로 Byte를 얻어 c++ 서버로 보내는 형식을 취했었는데

 

유니티에서 UTF8 로 Encoding시 "안녕" 이라는 문자열이 6개의 바이트로 표현되는 것으로 나타났다.

 

즉 한글 한 문자당 3바이트를 차지한다는 것이다. (지금까지 2바이트로 알고 있었는데 말이죠..)

 

찾아보니 

(1) 보통의 한국어 텍스트 문서: 이것은 아스키 문서이며 유니코드가 아닙니다. 영문/숫자/기호는 1바이트. 한글과 한자는 2바이트로 표현됩니다. euc-kr 또는 ksc_c_5601-1987 로 불리는 인코딩이며 웹페이지 작성에 사용할 수 있습니다. 특수한 외국어 문자나 일본식/중국식 한자는 표현할 수 없습니다.

다음의 2개가 유니코드입니다:

(2) 일반 유니코드(Unicode): 모든 글자를 2바이트로 표현합니다. 전세계 모든 글자들을 한꺼번에 표현할 수 있습니다. 인터넷에 HTML 파일로 올릴 수 없습니다. 즉 웹페이지 작성에 쓸 수 없습니다.

(3) UTF-8 유니코드: 영문/숫자/기호는 1바이트로, 한글과 한자 등은 3바이트로 표현합니다. 전세계 모든 글자들을 한꺼번에 표현할 수 있습니다. 웹페이지 작성에 쓸 수 있습니다. (저의 mwultong.blogspot.com 이 블로그도 UTF-8 로 되어 있습니다)

http://mwultong.blogspot.com/2006/05/unicode-utf-8.html 

 

일반 유니코드(Unicode)와 'UTF-8 유니코드'의 차이점, 차이

 

mwultong.blogspot.com

 

라고 설명되어 있었다. 즉 c++ 에서 받은 나는 일반 유니코드이므로 2바이트로 한글을 읽고 유니티에서는 3바이트로

한글을 읽으니 유니티에서 보낸 문자열이 제대로 표현이 되지않았다.

 

그럼 유니티에서 보낼때 제대로 보내면 되지않는가? ==> 제대로 서버에서도 제대로 받는 함수로는Encoding.Default.GetBytes(str) 가 있었는데 분명 잘 되던게 빌드파일로 돌릴때는 한글이 다시 3바이트로 표현돼서 들어왔다.

 

그런데 사실 내 서버에서는 굳이 채팅 문자열을 콘솔창에 찍어서 보아도 관련 기능이 딱히 없어서 그냥 받는 3바이트 그대로 다시 다른 클라이언트에 넘겨 줌으로써 다른 클라이언트들에게 한글문자열을 보여주게 했다..

 

https://trowind.tistory.com/61 이쪽에서는 만약 UTF-8 로 변환해서 보고 싶으면 도와주는 것을 설명하고 있다.

'유니티' 카테고리의 다른 글

중간 발표, 피드백  (0) 2018.05.29
게임 내 출석부 구현  (0) 2018.05.27
UI OnOff Sprite Change  (0) 2018.05.27
UI : Canvas VS CameraScreen  (0) 2018.05.27

내 서버에서 DisconnectEx 와 함께 CreateIOCompletionport 를 쓰는 일반적인 코드에서

 

접속을 종료할 때 DisconnectEx로 걸어준 뒤 다음 재접속 할때 CreateIoCompletionPort 를 한번 더 걸어줄시 

 

에러 오류가 나오는 것을 확인 했다.

 

이미 걸려있는 소켓에 대해 한번 더 걸어줄시  나타나는 현상으로 보인다.

 

TF_REUSE_SOCKET 의 인자를 사용하면서 SOCKET을 재사용하게 되면 이러한 점을 참고해서 해야겠다고 생각한다.

 

ps. DisconnectEx를 해당 소켓에 걸어준다고 바로 해제되는 것이 아니라, 클라이언트 쪽에서 closesocket을 불러야만

 

이 함수가 작동한다.  setsockopt 에서 TF_REUSE_SOCKET 을 쓰는 것에 비해 장점은 서버쪽에서 클라이언트 소켓을

 

강제 종료함으로써 생기는 오류의 최소화가 아닐까 생각한다.

내가 만든 게임서버들의 패킷송수신량을 파이썬의 plotly라는 라이브러리를 통해 시각화하기 위해서 간단하게 클라이언트와 서버간 통신을 할 수 있는 프로그램이 필요했다.

 

서버는 스레드를 이용해 계속적으로 recv를 받는 형태, 클라이언트는 send를 통해 계속 보내는 형태로 구성하였다.

 

 

서버 코드

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

from socket import *

import threading

 

clientSockets = [];

clientAddressList = [];

serverSock = socket(AF_INET, SOCK_STREAM);

serverSock.bind(('',9000));

serverSock.listen(5);

 

shutdown = False;

 

def recvData(connectionSocket, clientAddr):

while(True):

data = connectionSocket.recv(1024);

print(str(clientAddr) + " : " , data.decode("utf-8") );

 

 

 

def StartNetwork():

while(shutdown == False):

connectionSocket, clientAddr = serverSock.accept();

clientSockets.append(connectionSocket);

clientAddressList.append(clientAddr);

print(str(clientAddr) + " requested Connection!! " );

threading.Thread(target = recvData, args=(connectionSocket,clientAddr)).start();

 

 

StartNetwork();

 

Colored by Color Scripter

 

클라 코드

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

from socket import *

import threading

 

clientSockets = [];

clientAddressList = [];

serverSock = socket(AF_INET, SOCK_STREAM);

serverSock.bind(('',9000));

serverSock.listen(5);

 

shutdown = False;

 

def recvData(connectionSocket, clientAddr):

while(True):

data = connectionSocket.recv(1024);

print(str(clientAddr) + " : " , data.decode("utf-8") );

 

 

 

def StartNetwork():

while(shutdown == False):

connectionSocket, clientAddr = serverSock.accept();

clientSockets.append(connectionSocket);

clientAddressList.append(clientAddr);

print(str(clientAddr) + " requested Connection!! " );

threading.Thread(target = recvData, args=(connectionSocket,clientAddr)).start();

 

 

StartNetwork();

 

Colored by Color Scripter

서버1에 1, 2, 3 


서버2에 4, 5, 6을 가지고 있고.


서버1의 로드한계를 1000,


서버2의 로드한계를 10000으로 설정,


룸 1, 2, 3에 100명의 인원을 고르게 분산하여 할당,


룸 하나당 5000~6000사이의 패킷송수신량이 발생함


즉, 서버1은 패킷송수신량이 조금이라도 있다면 룸을 서버2에 넘겨주고


서버2에서는 자신이 소유한 룸의 갯수가 2개이상이 됀다면 서버1에게 룸을 전달함.


(예외처리가 좀더 필요한 상태.)


과정 1) 더미클라이언트 100대를 서버 1에 룸1:33, 룸2:34 룸3:33 으로 분산함.


과정 2) 서버1에서 로드가 발생하여 패킷송수신량이 가장 많은 룸2를 서버2에 할당함


과정 3) 서버1에서 로드가 발생하여 패킷송수신량이 가장 많은 룸1을 서버2에 할당함.


과정 4, 5) 서버 1에서 로드가 발생하여 패킷송수신량이 가장 많은 룸3을 서버2에 할당함, 


서버2에서 로드가 발생하여 패킷송수신량이 가장 많은 룸2를 서버1에 할당함.


최종 : 서버1 : 2    서버2 : 1,3 을 소유하게 됌. 





'Linux' 카테고리의 다른 글

Linux FTP 연결  (0) 2018.09.22

프로그래밍을 하다가 보면 visual studio 에서 에러가 뜰 때가 아주 많다.


그런데 그 중에서도 악질은 디버깅에도 잡히지 않고 메시지로 뜨는 놈이다..


list.. index. 뭐시기 하면서 error 뜬다..


그런데 이런 것의 대부분은 stl 의 사용에서 보통 오류가 있었던 것 같다.


자기가 아무리 동기화를 통해 push pop을 잘했다고 헌들... 어디선가 자꾸 구멍이 있긴 한가보다


대체로 없는 것에 대해 find() 하거나 비어있는 queue에 pop하거나 할때


에러가 난다. 찾기가 어렵지만.


심지어 unordered_set 같은 경우는 내부 구조가 tree로 되어있기 때문에


자신이 insert , erase를 동기화 처리를 해놨더라도 멀티 스레드가 동작할 때는


find()를 하는 곳에서 이런 에러가 날 수도 있다.


때문에 예외처리 , 동기화는 매우 꼼꼼히 해야겠다..

처음 대학교에 입학해서 생소했던 C,C++


엄청 오래 배우고 썼다고 생각했는데, 하면 할 수록 더 부족해지고 더 알고 싶어진다.


배우고 사용하다 보니 모르는 것들이 점점 구체화되고 상세해지면서 


구글링을 하게 되면, 이젠 첫 페이지부터 영어로 설명한 글들이 가득해진다.


분명 전보다 언어에 대한 지식이 넓어지고 깊어졌을 텐데


선뜻 상, 중, 하로 분류하라고 한다면 아직도 중간 수준을 못 벗어난 기분이다.


혹여나 아직도 내가 모르는게 산재되어있지는 않을까, 아직 그 정도 수준이 아니라서 모르는게 아닐까


다양한 언어, 프로그래밍, API들을 접하고 알파고의 등장.. IOT의 활성화.. 블록체인.. 


너무 많은 분야들이 점점 더 위로 솟구쳐 올라가 가지를 뻗는데


난 아직 뿌리를 헤엄치고 있는 기분이다.


이게 이렇게 깊었나 싶으면서..


빨리빨리 더더 잘해지면서 여러가질 해보고 싶다.


여러 프로토콜도 다루고,  통신에 대해 더 알고 싶고, 알고리즘, 인공지능, 빅데이터 , IOT, 네트워크, 운영체제


한 가지를 알면 해보고 싶은게 두 가지씩 늘어나는 것 같다.


 

+ Recent posts