Microsoft MVP성태의 닷넷 이야기
안녕하세요 질문하나만드리겠습니다...! [링크 복사], [링크+제목 복사]
조회: 566
글쓴 사람
김경한 (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분
[김경한] 먼저 댓글에 감사드립니다 말씀하신대로 그리드만 먼저 공부를 진행하였는데 댓글에 달아주신 링크를
보아도 도통감이 잡히지를않습니다.. 도와주실수있을까요..
[손님]
2022-09-07 02시29분
아래의 글을 따라해 보세요.

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

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

제가 위에 작성해논 tcp/ip 프로그램에서는 클라이언트측에서 서버측으로 대화를 보낼때 클라이언트쪽에서 [ number, data, ] 이런식으로하여금
보내주면 서버측에서는 별도의 저장없이 그리드표쪽으로 바로 조건물을 [ 이런식을 시작될떄 저장같은것으로 걸어서 그리드에저장되게하려고하는데요.
예제는 제가 데이터를 그리드자체에 넣는것이고 통수신에서 서버쪽에서조건문걸어서저장되게해야하는데 이부분이 어딜건드려야할지 감이전혀오질않습니다선생님
[손님]
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 문을 어디에넣어야하는지잘모르겠습니다..
연동시키는부분잡는게 너무어렵네요저한테는.. ㅜㅜ
[손님]
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);이 이름이현재컨텍스트에없다고 나오는데 위에선언을햇는데도 불구하고 이런오류가나오네요.....
[손님]
2022-09-08 09시22분
그 문제는, 해당 오류 메시지를 의미있게 해석해 보시면 분명히 이해할 수 있으니 스스로 해결하실 것을 권합니다. 현재 김경한 님의 상황을 봐서는 앞으로도 계속해서 오류가 발생할 텐데 그때마다 매번 질문으로 해결하면서 프로젝트를 진행할 수는 없습니다.

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

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

[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
5765ho...12/1/2022134Winform(.Net6) 클라이언트에서 SignalR Core 웹서버에 접속시 인증서 문제 [3]파일 다운로드1
5764요한11/30/2022166c++ 동일한 객체인지 비교 방법문의 [2]
5763고필석11/30/2022128시작하자마자 비정상 종료하는 프로세스에 대한 문제 해결 조언 요청 드립니다. [3]
5762흰털...11/30/2022140wpf mvvm ui update 로딩중 표시 [1]
5761민성11/29/2022118죄송하지만 한가지만 더 여쭈어 보겠습니다 [1]
5760민성11/29/2022112안녕하세요 [2]
5759문정환11/28/2022137c# socket 통신할때 빅엔디언으로 바꿔줘야 하나요? [1]
5758라떼11/28/2022153Linux 에서 winform UI 어플리케이션 실행하기 [3]
5757흰털...11/25/2022181asp.net core EF AddDbContext,AddDbContextFactory 차이점 알려주세요 [1]
5756흰털...11/25/2022136asp.net core web api에서 json 특정 property 무시하는 방법 문의 드립니다. System.Text.Json 사용중입니다. [1]
5755문정환11/24/2022299싱글스레드 프로그램도 컨텍스트 스위칭이 생길 수 있나요? [4]
5754초급11/24/2022221c# 소켓통신 [1]
5753흰털...11/24/2022233List와 ObservableCollection을 비교 해서 다른 값 추출 FirstOrDefault 객체 비교 [4]파일 다운로드1
5752푸헐11/15/2022341app.config 에 connectionStrings를 aspnet_regiis로 enctyption [4]
5751차가워11/8/2022495vs2022 preview net7 AOT 콘솔 실행 성능 [7]
5749차가워11/4/2022585전처리 지시문 #if DEBUG 배포시 실행 여부 [1]
5748김기헌11/3/2022591안녕하세요 선생님 싱글톤 패턴을 꼭 이렇게 사용해야 하나요? [6]
5747김기헌11/2/2022412안녕하세요 선생님 네트워크 관련 용어 중 IP 주소가 왜 논리적 주소라고 표현되는 건가요? [2]
5746물냉...11/2/2022465서로 다른 클래스에 있는 동일 함수의 일괄 호출 방법에 대해 궁금합니다. [3]
5745흰털...11/1/2022425.net core web api 사용 제한에 관한 질문 입니다. [2]
5744차가워10/31/2022412윈폼 Console.WriteLine(); 연산 문의 [1]
5743흰털...10/27/2022446reflection, static, override 질문입니다. [1]
5742차가워10/27/2022398하나의 socket에 여러 스레드가 접근 하는 경우 [1]
5741조호상10/27/2022450OpenCVSharp4 구현 가능 문의 [1]
5740혜성10/26/2022532Visual Studio 2022 C# 콘솔 프로그램 기본 코드 변경된 이유는 무엇인가요? [2]
[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...