/// <summary> /// 클라이언트가 보내온 데이터를 기다리고 /// 정해진 약속에 따라 해석하고 처리하는 함수 /// </summary> /// <param name="sockData">담당 소켓관련 객체</param> void ThreadRecv(object sockData) { SocketData clientData = sockData as SocketData; while (true) { try { string data = clientData.sr.ReadLine(); // 클라이언트가 보내올 때까지 무한대기 //ProcessPacket(data, clientData); SendAllData(data, clientData); // 자신을 제외한 나머지 클라이언트에 모두 전송 //AddRecvListBox(String.Format("[{0}] {1}", clientData.ip, data)); } catch (Exception ex) // 거의 99%이상은 접속이 끊어졌을 때 발생한다 { AddRecvListBox("Exception: " + ex.Message); DeleteClientFromList(clientData); DeleteClientAddressFromListView(clientData); break; } } }
//강퇴기능인지? /// <summary> /// 접속자를 관리하는 ListView에서 해당 클라이언트를 삭제 /// </summary> /// <param name="client">삭제할 대상 클라이언트 정보</param> void DeleteClientAddressFromListView(SocketData client) { if (lbUserList.InvokeRequired) { // 사용중일 때는 .NET에 등록하게 처리를 맡긴다 Invoke(delClientAddressFromListView, new object[] { client }); } else { foreach (ListViewItem lvi in lbUserList.Items) { string ip = lvi.SubItems[0].Text; string port = lvi.SubItems[1].Text; if (ip == client.ip && port == client.port) { lbUserList.Items.Remove(lvi); break; } } } }
/* 구분자 패킷 설계 * 1) 크게 명령, 구분자, 데이터 3부분으로 나눈다 * 2) 명령에 따라 데이터를 어떻게 해석할지 정한다 * 3) 명령이 먼저 나온다 * 4) 예시 * 4-1) 명령의 종류 C : 채팅 * S : 정해진 초 이후에 나를 해제 * B : WinForm의 배경색 * 4-2) 구분자 : | * 4-3) C|안녕하세요 * S|3 * B|Gold * P|100|100 */ /// <summary> /// 정해진 약속에 따라 패킷을 처리하는 함수 /// </summary> /// <param name="srcData">클라이언트가 보내온 전체 데이터</param> /// <param name="sendClient">데이터를 보낸 클라이언트</param> void ProcessPacket(string srcData, SocketData sendClient) { string[] datas = srcData.Split(new char[] { '|' }); switch (datas[0]) { case "C": AddRecvListBox(String.Format("[채팅] [{0}] {1}", sendClient.ip, srcData)); SendAllData(srcData, sendClient); break; case "S": { AddRecvListBox(String.Format("[해제] [{0}] {1}", sendClient.ip, srcData)); int sec = Int32.Parse(datas[1]); // 정해진 초 후에 처리할 스레드에 전달할 인자 SocketCloseData scd = new SocketCloseData(); scd.client = sendClient; scd.sec = sec; Thread tClose = new Thread(new ParameterizedThreadStart(ThreadClose)); tClose.Start(scd); } break; case "B": AddRecvListBox(String.Format("[배경] [{0}] {1}", sendClient.ip, srcData)); Color color = Color.FromName(datas[1]); this.BackColor = color; break; case "P": AddRecvListBox(String.Format("[좌표] [{0}] {1}", sendClient.ip, srcData)); SendAllData(srcData, sendClient); break; } }