Microsoft MVP성태의 닷넷 이야기
안녕하세요 질문하나만드리겠습니다...! [링크 복사], [링크+제목 복사]
조회: 3977
글쓴 사람
김경한 (hwan4170 at naver.com)
홈페이지
첨부 파일
 

amespace MultiChatServer {
    public partial class ChatForm : Form {
        delegate void AppendTextDelegate(Control ctrl, string s);
        AppendTextDelegate _textAppender;
        Socket mainSock;
        IPAddress thisAddress;

        public ChatForm() {
            InitializeComponent();
            mainSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            _textAppender = new AppendTextDelegate(AppendText);
            DataTable table = new DataTable();
            table.Columns.Add("");
            table.Columns.Add("Number", typeof(int));
            table.Columns.Add("Data", typeof(float));
            table.Columns.Add("");
            table.Rows.Add("", "1", "99.5", "");
            table.Rows.Add("", "2", "24.2", "");
            table.Rows.Add("", "3", "53.2", "");

            dataGridView1.DataSource = table;
        }//선언
        
        void AppendText(Control ctrl, string s) {
            if (ctrl.InvokeRequired) ctrl.Invoke(_textAppender, ctrl, s);
            else {
                string source = ctrl.Text;
                ctrl.Text = source + Environment.NewLine + s;
            }
        }

        void OnFormLoaded(object sender, EventArgs e) {
            IPHostEntry he = Dns.GetHostEntry(Dns.GetHostName());

       
            foreach (IPAddress addr in he.AddressList) {
                if (addr.AddressFamily == AddressFamily.InterNetwork) {
                    thisAddress = addr;
                    break;
                }
            }

          
            if (thisAddress == null)
      
                thisAddress = IPAddress.Loopback;

            txtAddress.Text = thisAddress.ToString();
        }
        void BeginStartServer(object sender, EventArgs e) {
            int port;
            if (!int.TryParse(txtPort.Text, out port)) {
                MsgBoxHelper.Error("포트 번호가 잘못 입력되었거나 입력되지 않았습니다.");
                txtPort.Focus();
                txtPort.SelectAll();
                return;
            }

            IPEndPoint serverEP = new IPEndPoint(thisAddress, port);
            mainSock.Bind(serverEP);
            mainSock.Listen(10);

            
            mainSock.BeginAccept(AcceptCallback, null);
        }

        List<Socket> connectedClients = new List<Socket>();
        void AcceptCallback(IAsyncResult ar) {
           
            Socket client = mainSock.EndAccept(ar);

           
            mainSock.BeginAccept(AcceptCallback, null);

            AsyncObject obj = new AsyncObject(4096);
            obj.WorkingSocket = client;

          
            connectedClients.Add(client);
            
            AppendText(txtHistory, string.Format("사용자 (@ {0})가 연결되었습니다.", client.RemoteEndPoint));

            
            client.BeginReceive(obj.Buffer, 0, 4096, 0, DataReceived, obj);
        }

        void DataReceived(IAsyncResult ar) {
            AsyncObject obj = (AsyncObject)ar.AsyncState;

           
            //예외처리 구문 (튕김방지)
            string text = Encoding.UTF8.GetString(obj.Buffer);

            
            string[] tokens = text.Split(' ');
            string ip = tokens[0];
            string msg = tokens[0];

           
            AppendText(txtHistory, string.Format("[받음]{0}: {1}", ip, msg));
            
            
            for (int i = connectedClients.Count - 1; i >= 0; i--) {
                Socket socket = connectedClients[i];
                if (socket != obj.WorkingSocket) {
                    try { socket.Send(obj.Buffer); }
                    catch {
                       
                        try { socket.Dispose(); } catch { }
                        connectedClients.RemoveAt(i);
                    }
                }
            }

            try
            {
                int received = obj.WorkingSocket.EndReceive(ar);
            }
            catch (Exception e)
            {
                string Message = "서버가 끊어졌습니다" + e.Message;
                MessageBox.Show(Message);
                return;
            }


            obj.ClearBuffer();

         
            obj.WorkingSocket.BeginReceive(obj.Buffer, 0, 4096, 0, DataReceived, obj);
        }

        void OnSendData(object sender, EventArgs e) {
            
            if (!mainSock.IsBound) {
                MsgBoxHelper.Warn("서버오프라인 상태");
                return;
            }
            
            
            string tts = txtTTS.Text.Trim();
            if (string.IsNullOrEmpty(tts)) {
                MsgBoxHelper.Warn("텍스트가 입력되지 않았습니다!");
                txtTTS.Focus();
                return;
            }
            
           
            byte[] bDts = Encoding.UTF8.GetBytes(thisAddress.ToString() + '\x01' + tts);

           
            for (int i = connectedClients.Count - 1; i >= 0; i--) {
                Socket socket = connectedClients[i];
                try { socket.Send(bDts); } catch {
                   
                    try { socket.Dispose(); } catch { }
                    connectedClients.RemoveAt(i);
                }
            }

            
            AppendText(txtHistory, string.Format("[보냄]{0}: {1}", thisAddress.ToString(), tts));
            txtTTS.Clear();
        }

        private void lblPort_Click(object sender, EventArgs e)
        {

        }

        private void txtHistory_TextChanged(object sender, EventArgs e)
        {

        }

        private void lblAddress_Click(object sender, EventArgs e)
        {

        }

        private void tblMainLayout_Paint(object sender, PaintEventArgs e)
        {

        }

현재 제가 c#으로 tcp/ip 송수신프로그램을 만들어서 짜놓고 실행까지 구현을 해놓은 코드입니다.
다름이아니라 여기서좀더 나아가 옆에 데이타그리드를 통해 표를만들어
클라이언트 쪽에서 예를들어 [ 1, 99.9% ]
이런식으로 텍스트를 전송하게되면 조건문으로 걸어서 그리드쪽으로자동기입이되도록하고싶은데요..
어느부분에서 어떤함수를대략적으로 추가해야 그리드쪽으로 넘어가는지를 도통모르겠습니다..
조건문은 하다보면 될거같은데 넘어가도록 하는 코드를 어디에무엇을추가해야하는지모르겠어요...








[최초 등록일: ]
[최종 수정일: 9/6/2022]


비밀번호

댓글 작성자
 



2022-09-07 12시45분
이런 경우에는, 너무 조급하게 생각하지 마시고 코드를 하나씩 분리해서 실습해 보세요.

소켓 통신 코드 없이, 단순히 그리드만 올려 놓은 코드를 작성한 후 그것에 어떻게 항목을 삽입할 수 있는지 문서를 보시면 됩니다.

DataGrid Class
; https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.datagrid

그것 먼저 해보시고, 이후 소켓으로부터 전달받은 텍스트를 그리드에 추가하는 코드와 연동하면 됩니다. 분명히, 하실 수 있으니 ^^ 시도해 보세요. 그래도 안 되시면 그때까지의 소스 코드를 다시 올려주세요.
정성태
2022-09-07 02시16분
[김경한] 먼저 댓글에 감사드립니다 말씀하신대로 그리드만 먼저 공부를 진행하였는데 댓글에 달아주신 링크를
보아도 도통감이 잡히지를않습니다.. 도와주실수있을까요..
[guest]
2022-09-07 02시29분
아래의 글을 따라해 보세요.

C# DataGridView에 데이터 넣기 예제
; https://kinghell.tistory.com/57

그런 다음, 구체적으로 어느 부분을 모르겠는지 소스 코드와 함께 다시 질문해 주세요.
정성태
2022-09-07 02시41분
[김경한] 답변에감사드립니다 방금 링크해주신 데이터넣기예제도 구글링하다 찾아서 직접 실행까지해봤습니다 이예제는 무리없이 할수있지만

제가 위에 작성해논 tcp/ip 프로그램에서는 클라이언트측에서 서버측으로 대화를 보낼때 클라이언트쪽에서 [ number, data, ] 이런식으로하여금
보내주면 서버측에서는 별도의 저장없이 그리드표쪽으로 바로 조건물을 [ 이런식을 시작될떄 저장같은것으로 걸어서 그리드에저장되게하려고하는데요.
예제는 제가 데이터를 그리드자체에 넣는것이고 통수신에서 서버쪽에서조건문걸어서저장되게해야하는데 이부분이 어딜건드려야할지 감이전혀오질않습니다선생님
[guest]
2022-09-07 03시24분
정리해 보면, 클라이언트에서 (예를 들어) "[50, 99.9%]"라는 문자열로 보내오는데, 그렇게 "[" 대괄호로 시작하는 문자열이 오는 경우에는 서버에서 DataGrid로 보여주고 싶다는 거죠?

근데... 이미 프로그래밍을 대충 잘 하셨습니다. 작성하신 코드에 보면 AppendText 메서드가 사실상 들어온 문자열을 처리하고 있는 듯한데요, 단지 그것은 TextBox에 데이터를 넣는 것이니, 그 메서드에서만 DataGrid로 넣는 코드를 추가해 주시면 됩니다.

가령, DataGrid로 넣는 메서드를 AddTextToDataGrid로 만들었다고 했을 때 AppendText에는 이렇게만 추가하면 됩니다.

if (source[0] == '[')
{
    AddTextToDataGrid(source);
}

이해가 될 때까지 설명해 드릴 테니, 계속 모르는 사항들을 질문해 주세요.
정성태
2022-09-07 04시33분
[김경한] public ChatForm() {
            InitializeComponent();
            mainSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            _textAppender = new AppendTextDelegate(AppendText);
            DataTable table = new DataTable();
            table.Columns.Add("");
            table.Columns.Add("Number", typeof(int));
            table.Columns.Add("Data", typeof(float));
            table.Columns.Add("");
       

            dataGridView1.DataSource = table;
        }//선언
        
        void AppendText(Control ctrl, string s) {
            if (ctrl.InvokeRequired) ctrl.Invoke(_textAppender, ctrl, s);
            else {
                string source = ctrl.Text;
                ctrl.Text = source + Environment.NewLine + s;
            }
            if (source[0] == '[')
            {
                AddTextToDataTable(source);
            }


        }
항상감사드립니다
소스코드를보면 DataGrid로 넣는 메서드가 ... table로 잡아야하는거 같기도한데
만약테이블로잡고 저렇게 넣엇다고하면 if 문을 어디에넣어야하는지잘모르겠습니다..
연동시키는부분잡는게 너무어렵네요저한테는.. ㅜㅜ
[guest]
2022-09-07 06시08분
위와 같은 경우에는 if 문을 그 위에 ctrl.InvokeRequired의 else 절 내부에 넣는 것이 맞습니다.

void AppendText(Control ctrl, string s) {
    if (ctrl.InvokeRequired) ctrl.Invoke(_textAppender, ctrl, s);
    else {
        string source = ctrl.Text;
        ctrl.Text = source + Environment.NewLine + s;

        if (source[0] == '[')
        {
            AddTextToDataTable(source);
        }
    }
}
정성태
2022-09-08 09시10분
[김경한] 감사합니다 선생님말씀대로 위치는 잡았는데 서버와 클라이언트 접속을시키니까
if (source[0] == '[')
                {
                    AddTextToDataTable(source);
                }
            }

        }

'[' 쪽에서 인덱스배열범위를벗어난오류와
AddTextToDataTable(source);이 이름이현재컨텍스트에없다고 나오는데 위에선언을햇는데도 불구하고 이런오류가나오네요.....
[guest]
2022-09-08 09시22분
그 문제는, 해당 오류 메시지를 의미있게 해석해 보시면 분명히 이해할 수 있으니 스스로 해결하실 것을 권합니다. 현재 김경한 님의 상황을 봐서는 앞으로도 계속해서 오류가 발생할 텐데 그때마다 매번 질문으로 해결하면서 프로젝트를 진행할 수는 없습니다.

참고로, 아래의 영상은 자신의 소스 코드에서 왜 그런 동작을 하는지 비주얼 스튜디오를 이용해 진단하는데 도움을 줄 것입니다.

비주얼 스튜디오 디버그 기능 기초 활용
; https://www.youtube.com/watch?v=X3_OXIIDEec
정성태
2022-09-08 09시48분
[김경한] 알겠습니다 선생님 조언해주신대로 좀더 심도있게 고민하고 공부해보겟습니다.!
[guest]

1  2  3  4  5  6  7  8  9  [10]  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
5699갓경섭7/29/20224439C# 프로그램 느려짐 현상 [2]
5698kss7/29/20225210ValueTask 질문입니다. [5]
5697스팸7/28/20225201윈도우서버 Port 고갈문제 (Event ID 4227, 4231) [3]파일 다운로드1
5696유석7/27/20225486닷넷 4.X 와 닷넷 6.0 버전 차이 [6]
5695초보코더7/26/20224852[WCF] EndpointNotFoundException 기본 연결이 닫혔습니다. 원격 서버에 연결할 수 없습니다. [1]
5693차가워7/22/20224323socket 종료 시 reveive수신부에서 에러 나는거 처리 문의 [5]
5692도비7/21/20223935Ubuntu LVM 확장 관련 [1]파일 다운로드1
5691따봉이7/21/20224623Task 비동기 UI 크로스 쓰레딩 Err 관련 [1]
5690훈이7/20/20223863wpf질문입니다 [2]
5689질문7/20/20223656비동기 함수를 사용하는 방법에 대한 질문입니다 [1]
5688김정현7/11/20223746소스 디버깅(F5)시 프로그램 켜지지 않고 디버깅 가능한 상태 [1]
5687규철7/6/20223865개발업무 문서 관리 방법 문의 [3]
5686권용완7/5/20223834Linq Entites 에서 string[]에 담긴 데이터를 제외하는 방법 문의 [3]
5685차가워7/4/20224004메모리 선택 문의 [1]
5683김민혁7/1/20224549HttpWebRequest POST 전송 관련해서 질문 드립니다. [4]파일 다운로드1
5682김기헌6/20/20223989안녕하세요 서로 다른 스레드에서 동일 인스턴스의 메소드를 호출할때 질문드립니다 [2]
5681미래는투...6/19/20223875VC++ 빌드 관련 문의 (h파일이 바뀌었는데 컴파일을 꼭 하지 않아도 되나요?) [1]
5680Syong6/12/20224875EXE파일에 속성값 추가하는 방법이 있나요? [2]파일 다운로드1
5679차가워6/8/20224008tcpip socket 여러 랜카드 사용 시 연결 문의 [1]
5678차가워6/7/20223919원자적 실행 문의 [3]
5677장성욱6/7/20223942블루투스 포트와 시리얼포트 연결시 에러 [2]
5675차가워5/29/20224626윈도우설정 프로세스사용계획 옵션과 c# 스레드 [1]
5674민우5/29/20224497C++ 의 RTTI, Reflection 으로 객체 멤버변수, 멤버함수 목록 추출 문의 [2]
5673조은현5/25/20225434안녕하세요 선생님! c#에서 TCP/IP의 keep alive 기능의 사용법에 대해서 질문드리고 싶어요! [2]파일 다운로드2
5672game...5/23/20225331안녕하세요 GC를 일시적으로 중단시키는 방법이 있을까요? [5]
5671한예지 donator5/20/20224938델리게이트와 함수포인터 선언 시, 차이점 질문 있습니다. [3]
1  2  3  4  5  6  7  8  9  [10]  11  12  13  14  15  ...