Exemple #1
0
        /// <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()}");
            }
        }
Exemple #2
0
        /// <summary>
        /// 방 리스트에서 해당 방이 몇 번째 요소에 있는지 알아냄
        /// </summary>
        /// <param name="Room">방</param>
        /// <param name="Rooms">방 리스트</param>
        /// <returns></returns>
        public static int getRoomIdByRoom(RoomInfo Room, List<RoomInfo> Rooms)
        {
            for (int i = 0; i < Rooms.Count; i++)
            {
                if (Rooms[i].PaneNumber == Room.PaneNumber)
                {
                    return i;
                }
            }

            return -1;
        }
Exemple #3
0
        /// <summary>
        /// 특정 방 모두에게 코드 송신
        /// </summary>
        /// <param name="message">코드</param>
        /// <param name="room">방</param>
        /// <param name="data">(선택)데이터</param>
        public static void BroadcastRoom(string message, RoomInfo room, byte[] data = null)
        {
            foreach (Viewer v in room.Viewer)
            {
                if (v.Socket.Connected)
                {
                    SocketAsyncEventArgs args = new SocketAsyncEventArgs();

                    MemoryStream stream = new MemoryStream();
                    BinaryWriter writer = new BinaryWriter(stream);

                    stream.Write(UTF8.GetBytes(message), 0, 8);

                    if (data != null)
                    {
                        stream.Write(data, 0, data.Length);
                    }

                    args.SetBuffer(stream.ToArray(), 0, stream.ToArray().Length);

                    v.Socket.SendAsync(args);
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// 해당 뷰어가 특정 방에 있는지 확인
        /// </summary>
        /// <param name="viewer">뷰어</param>
        /// <param name="room">방</param>
        /// <returns></returns>
        public static bool IsViewerInRoom(Viewer viewer, RoomInfo room)
        {
            foreach (Viewer v in room.Viewer)
            {
                if (v.PaneNumber.Equals(viewer.PaneNumber))
                {
                    return true;
                }
            }

            return false;
        }
Exemple #5
0
        /// <summary>
        /// 방에 공지사항 띄우기
        /// </summary>
        /// <param name="target">방</param>
        /// <param name="message">공지 문자열</param>
        public static void SystemRoom(RoomInfo target, string message)
        {
            if (target == null)
            {
                return;
            }
            foreach (Viewer v in target.Viewer)
            {
                try
                {
                    SocketAsyncEventArgs args = new SocketAsyncEventArgs();
                    MemoryStream stream = new MemoryStream();
                    BinaryWriter writer = new BinaryWriter(stream);

                    writer.Write(UTF8.GetBytes(NET_CHAT_SYSTEM));
                    writer.Write(UTF8.GetBytes(message).Length);
                    writer.Write(UTF8.GetBytes(message));

                    args.SetBuffer(stream.ToArray(), 0, stream.ToArray().Length);
                    v.Socket.SendAsync(args);
                }
                catch (Exception e)
                {
                    logln($"{target.RoomID}의 {v.Nick}({v.IpAddr})에게 시스템 메세지를 전송하는 중 에러 발생!\n{e.ToString()}", true);
                }
            }
            logln($"SYSTEM({target.RoomID}번 방): {message}", true);
        }