Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 30 | 31 |
Tags
- Optimistic Lock
- annotation
- component
- JPA 동시성
- 스마일게이트
- flask
- 개발
- Android
- JPA 낙관적락
- 안드로이드
- 암호화
- Redis
- spring
- bean
- spring security
- Transaction isolation level
- spring security 인증
- JPA Lock
- JPA
- 낙관적락 비관적락 차이
- 스프링
- 서버개발캠프
- 디자인 패턴
- 캠프
- 스프링 log
- JPA 비관적락
- 서버
- Pessimistic Lock
- 스프링 로그
- Inno DB
Archives
- Today
- Total
모르는게 많은 개발자
[스마일게이트 서버 개발 캠프 4기]#2 게임 채팅 서버 구현(로그인, 채팅) 본문
반응형
캠프에서 유일하게 게임 개발 프로젝트를 하게 되었다. 서버 담당을 맡은 나는 두번째 개인과제에서 개발한 로그인 시스템을 이용해 유저끼리 간단히 파이썬 소켓 서버를 통해 클라이언트끼리 채팅하는 프로그램을 구현하였다.
1. 로그인 화면
간단하게 이메일과 비밀번호를 입력할 수 있는 씬을 제작.
2. HTTP 통신 구현
개인과제에서 Flask를 이용한 로그인 시스템을 구현했기 때문에 Flask서버를 그대로 이용해 게임 로그인에 적용했다. 일단 C#에서 HTTPManager클래스를 만들어 서버와의 통신을 구현했다.
using System.Net;
using System.IO;
using System.Text;
public class HTTPManager
{
string url;
string res = string.Empty;
string postData = string.Empty;
byte[] sendData;
HttpWebRequest request;
HttpWebResponse resp;
Stream requestStream;
public HTTPManager()
{
url = "http://localhost:8082/";
}
//이메일과 비밀번호를 입력받아 Flask서버로 로그인 요청
public string LoginReq(string email, string pw)
{
request = Init("clientlogin"); //URL 경로 이름
request.Method = "POST";
postData = string.Format("email={0}&password={1}", email, pw); //데이터 포맷 방법.
SendData(postData);
return ReceiveData(request);
}
public string UserCacheReq(string email)
{
request = Init("clientusercache");
request.Method = "POST";
postData = string.Format("email={0}", email);
SendData(postData);
return ReceiveData(request);
}
//URL Path를 입력받아 request객체 생성
private HttpWebRequest Init(string req)
{
HttpWebRequest tmp;
tmp = (HttpWebRequest)WebRequest.Create(url + req);
tmp.Timeout = 30 * 1000;
tmp.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
return tmp;
}
//C#에서 서버로 데이터를 보내기 위해 byte로 변환후 전송.
private void SendData(string data)
{
sendData = UTF8Encoding.UTF8.GetBytes(data);
requestStream = request.GetRequestStream();
requestStream.Write(sendData, 0, sendData.Length);
requestStream.Close();
}
//Response데이터 받아오기
private string ReceiveData(HttpWebRequest req)
{
using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
{
HttpStatusCode status = resp.StatusCode;
Stream stream = resp.GetResponseStream();
using (StreamReader sr = new StreamReader(stream))
{
res = sr.ReadToEnd();
return res;
}
}
}
}
3. 채팅 소켓 서버
import socket
from _thread import *
HOST = '127.0.0.1'
PORT = 3098
#소켓 서버 설정
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
server_socket.bind((HOST, PORT))
server_socket.listen()
#서버에 접속한 유저 소켓 리스트 저장
list_of_clients = []
print('server start')
#각 클라이언트 소켓 쓰레드
def client_thread(user_socket):
while True:
try:
#클라이언트에서 온 데이터 수신
message = str(str(user_socket[2]) + ":").encode() + user_socket[0].recv(2048)
if not message:
remove(user_socket)
break
print(message)
#클라이언트에서 온 데이터를 다른 클라이언트에게도 전달
broadcast(message, user_socket[1][1])
except:
continue
def broadcast(message, user):
for clients in list_of_clients:
try:
clients[0].send(message)
except:
clients[0].close()
remove(clients)
def remove(connection):
if connection in list_of_clients:
print("asdasdasd")
list_of_clients.remove(connection)
for row in list_of_clients:
print(row)
while True:
print('waiting new client..')
client_socket, addr = server_socket.accept() #소켓
print(addr[0] + ' ' + str(addr[1]) + ' connected')
user_email = client_socket.recv(2048)
list_of_clients.append([client_socket, addr, user_email])
#쓰레드 시작
start_new_thread(client_thread, (list_of_clients[-1],))
server_socket.close()
4. 정보 입력
위의 세팅을 토대로 정보를 입력한다.
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class LogInManager : MonoBehaviour
{
UserInfo userInfo;
HTTPManager httpManager;
[Header("InputFields")]
public InputField idInput;
public InputField pwInput;
[Header("Buttons")]
public Button signInButton;
public Button signUpButton;
// Start is called before the first frame update
void Start()
{
Debug.Log("awda");
userInfo = GameObject.Find("UserInfoObject").GetComponent<UserInfo>();
httpManager = new HTTPManager();
}
// 로그인 버튼 클릭시 이벤트 발생 함수
public void SignInBtn()
{
userInfo.userData = JsonUtility.FromJson<UserData>(httpManager.LoginReq(idInput.text, pwInput.text));
Debug.Log(userInfo.userData.login);
//로그인 성공시
if (userInfo.userData.login == "true")
{
SceneManager.LoadScene("Chatting");
}
}
// 회원가입 버튼 클릭시 이벤트 발생 함수
public void SignUpBtn()
{
// 회원가입 페이지 or 씬으로 이동.
}
}
Sign In 버튼 클릭시 SignInBtn() 함수가 실행되면서 서버로 로그인 request를 보낸다.
로그인이 성공하면 채팅화면으로 이동한다.
5. 채팅 입력
채팅 입력후 send버튼을 누르게 되면 아래 사진처럼 클라이언트에서 서버로 메세지가 전달이 된다. 그리고 현
현재 클라이언트에서 서버로 보낸 메세지가 모든 클라이언트에게 다시 전송하므로 결과는 내가 입력한 hello world와 내가 서버로 보낸 메세지가 다시 출력되어 아래 사진처럼 두개의 메세지가 출력되게 된다.
반응형
'스마일게이트서버캠프4기' 카테고리의 다른 글
[스마일게이트 서버 개발 캠프 4기]#6 후기 (0) | 2020.03.08 |
---|---|
[스마일게이트 서버 개발 캠프 4기]#5 몬스터 HP 동기화(TCP 소켓 통신중 의도치 않은 패킷 받을 때) (0) | 2020.02.29 |
[스마일게이트 서버 개발 캠프 4기]#4 리눅스 ssh를 꺼도 프로세스 유지방법 (nohup) (0) | 2020.02.24 |
[스마일게이트 서버 개발 캠프 4기]#3 두번째 개인과제 리뷰(로그인 인증 서버개발) (0) | 2020.02.10 |
[스마일게이트 서버 개발 캠프 4기]#1 첫번째 개인과제 리뷰(Shortening URL) (0) | 2020.01.18 |
Comments