/// <summary> /// 데이터 수신시 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ReceiveCompleted(object sender, SocketAsyncEventArgs e) { // 클라이언트 소켓 얻어오기 및 뷰어 얻어오기 Socket clientSock = sender as Socket; Viewer viewer = findViewerBySocket(clientSock, Viewers); // 소켓 데이터 SocketData data = e.UserToken as SocketData; if (viewer != null) { viewer.LastConnected = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; } try { if (clientSock.Connected && e.BytesTransferred > 0) { data.Data = e.Buffer; // 인증 처리 if (!viewer.Authorized) { if (data.Code == NET_START) { viewer.Authorized = true; logln($"클라이언트 {viewer.Socket.RemoteEndPoint.ToString()} 인증됨.", true); SocketAsyncEventArgs args = new SocketAsyncEventArgs(); args.SetBuffer(UTF8.GetBytes(NET_START), 0, 8); clientSock.SendAsync(args); } } else if (viewer.Authorized && !viewer.LoggedIn) { // 로그인 처리 if (data.Code == NET_LOGIN) { int pnSize = BitConverter.ToInt32(data.Data, 8); string paneNumber = UTF8.GetString(data.Data, 12, pnSize).Replace("\0", ""); int nickSize = BitConverter.ToInt32(data.Data, 12 + pnSize); string nick = UTF8.GetString(data.Data, 12 + pnSize + 4, nickSize); nick = nick.Replace("\0", "").Trim(); logln($"클라이언트 {viewer.Socket.RemoteEndPoint.ToString()} 로그인 중...", true); viewer.PaneNumber = paneNumber; viewer.IpAddr = getIPAddress(BitConverter.ToUInt32(((IPEndPoint)viewer.Socket.RemoteEndPoint).Address.GetAddressBytes(), 0)); viewer.Nick = nick; viewer.LoggedIn = true; logln("로그인 성공!\n" + $"PaneNumber: {paneNumber}\n" + $"IpAddr: {viewer.IpAddr}\n" + $"Nick: {viewer.Nick}", true); SocketAsyncEventArgs args = new SocketAsyncEventArgs(); byte[] arr = new byte[9]; UTF8.GetBytes(NET_LOGIN).CopyTo(arr, 0); arr[8] = 0x01; args.SetBuffer(arr, 0, 9); clientSock.SendAsync(args); } } // 채팅 처리 if (viewer.Authorized && viewer.LoggedIn) { switch (data.Code) { // 방 리스트 전송 case NET_ROOM_LIST: { SendRoomList(Rooms, viewer); break; } // 방 입장 처리 case NET_ROOM_ENTER: { EnterRoom(Rooms, viewer, data); break; } // 방 퇴장 처리 case NET_ROOM_EXIT: try { LeaveRoom(viewer, Rooms); SocketAsyncEventArgs args = new SocketAsyncEventArgs(); byte[] arr = new byte[9]; UTF8.GetBytes(NET_ROOM_EXIT).CopyTo(arr, 0); arr[9] = 0x01; args.SetBuffer(arr, 0, 9); clientSock.SendAsync(args); } catch (Exception ee) { SocketAsyncEventArgs args = new SocketAsyncEventArgs(); byte[] arr = new byte[5]; UTF8.GetBytes(NET_ROOM_EXIT).CopyTo(arr, 0); arr[9] = 0xFF; args.SetBuffer(arr, 0, 9); clientSock.SendAsync(args); logln($"{viewer.Nick}({viewer.IpAddr})님께서 {findRoomByPaneNumber(viewer.PaneNumber, Rooms).RoomID}번 방에서 퇴장 중에 알 수 없는 에러 발생:\n{ee.ToString()}"); } break; // 방 생성 처리 case NET_ROOM_CREATE: { try { SocketAsyncEventArgs args = new SocketAsyncEventArgs(); MemoryStream stream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stream); writer.Write(UTF8.GetBytes(NET_ROOM_CREATE)); if (!Utility.IsRoomExists(viewer.PaneNumber, Rooms)) { RoomInfo Room = new RoomInfo(); Room.PaneNumber = viewer.PaneNumber; Room.CreatedAt = DateTime.Now; Room.Owner = viewer; Rooms.Add(Room); writer.Write((byte)0x01); //logln($"{viewer.Nick}({viewer.IpAddr})에서 방 생성 요청 수락됨", true); } else { writer.Write((byte)0xFF); } args.SetBuffer(stream.ToArray(), 0, stream.ToArray().Length); stream = new MemoryStream(); writer = new BinaryWriter(stream); clientSock.SendAsync(args); break; } catch (Exception ee) { logln(ee.ToString(), true, true); break; } break; } case NET_ROOM_KICK: { int paneLen = BitConverter.ToInt32(data.Data, 8); string panenumber = UTF8.GetString(data.Data, 12, paneLen); Viewer target = findViewerByPaneNumber(panenumber, findRoomByPaneNumber(viewer.PaneNumber, Rooms)?.Viewer); try { if (target != null) { SystemRoom(viewer.RoomInfo, $"{target.Nick}<{target.PaneNumber}>님이 추방되었습니다."); MemoryStream stream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stream); writer.Write(target.PaneBytes.Length); writer.Write(target.PaneBytes); writer.Write(UTF8.GetBytes(target.Nick).Length); writer.Write(UTF8.GetBytes(target.Nick)); writer.Write(UTF8.GetBytes(target.IpAddr).Length); writer.Write(UTF8.GetBytes(target.IpAddr)); BroadcastRoom(NET_ROOM_KICK, viewer.RoomInfo, stream.ToArray()); LeaveRoom(target, Rooms); } } catch (Exception ee) { Console.WriteLine(ee.ToString()); } break; } case NET_ROOM_DESTROY: { int lenPane = BitConverter.ToInt32(data.Data, 8); string pane = UTF8.GetString(data.Data, 12, lenPane); MemoryStream stream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stream); writer.Write(lenPane); writer.Write(UTF8.GetBytes(pane)); writer.Write((byte)0x01); BroadcastMessage(NET_ROOM_DESTROY, Rooms, stream.ToArray()); DestroyRoom(pane, Rooms); break; } case NET_CHAT_MESSAGE: { if (viewer.RoomInfo != null) { int chatLen = BitConverter.ToInt32(data.Data, 8); string chat = UTF8.GetString(data.Data, 12, chatLen); chat = chat.Replace("\0", "").Trim(); RoomChatMsg(viewer, chat); RoomInfo curRoom = viewer.RoomInfo; MemoryStream stream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stream); writer.Write(UTF8.GetByteCount(curRoom.PaneNumber)); writer.Write(UTF8.GetBytes(curRoom.PaneNumber)); BroadcastMessage(NET_PUSH_NEWMSG, Rooms, stream.ToArray()); } break; } case NET_CHAT_NOTICE: { int type = BitConverter.ToInt32(data.Data, 8); int lenPane = BitConverter.ToInt32(data.Data, 12); string paneNumber = UTF8.GetString(data.Data, 16, lenPane); int lenNotice = BitConverter.ToInt32(data.Data, 16 + lenPane); string notice = UTF8.GetString(data.Data, 20 + lenPane, lenNotice); if (type == 1) { NotifyAll(Rooms, notice); } else if (type == 2) { var room = findRoomByPaneNumber(paneNumber, Rooms); NotifyRoom(room, notice); } break; } case NET_LOGOUT: { LeaveRoom(viewer, Rooms); SocketAsyncEventArgs args = new SocketAsyncEventArgs(); args.SetBuffer(UTF8.GetBytes(NET_LOGOUT), 0, 8); viewer.Socket.SendAsync(args); break; } } } data = new SocketData(); data.initData(1024); e.SetBuffer(data.Data, 0, 1024); clientSock.ReceiveAsync(e); } //else //{ // // 연결 끊김 처리 // logln($"클라이언트 {clientSock.RemoteEndPoint.ToString()}의 연결이 끊겼습니다.", true); // clientSock.Disconnect(false); // clientSock.Close(); // clientSock.Dispose(); // Viewer remove = null; // foreach (Viewer v in Viewers) // { // if (v.Socket == clientSock) // { // remove = v; // break; // } // } // Viewers.Remove(remove); //} } catch (SocketException ee) { logln($"소켓 에러\n{ee.ToString()}"); } catch (Exception ee) { logln($"알 수 없는 에러\n{ee.ToString()}"); } }
/// <summary> /// 연결 수립시 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ClientAccepted(object sender, SocketAsyncEventArgs e) { // 클라이언트 소켓 얻기 logln("연결 요청 확인됨.", true); Socket clientSock = e.AcceptSocket; if (clientSock != null && clientSock is Socket) { // 소켓 데이터 설정 logln("대상: " + clientSock.RemoteEndPoint.ToString(), true); SocketAsyncEventArgs recvE = new SocketAsyncEventArgs(); // 소켓 데이터 초기화 SocketData data = new SocketData(); data.initData(1024); recvE.UserToken = data; recvE.SetBuffer(data.Data, 0, 1024); recvE.Completed += new EventHandler<SocketAsyncEventArgs>(ReceiveCompleted); clientSock.ReceiveAsync(recvE); // 뷰어 초기화 Viewer viewer = new Viewer(); viewer.Socket = clientSock; viewer.SocketData = data; Viewers.Add(viewer); } else { logln("연결을 수립하는 중 에러 발생\n" + e.ToString(), true, true); } // 다음 연결 수립 대기 Socket server = sender as Socket; e.AcceptSocket = null; server.AcceptAsync(e); }