Microsoft MVP성태의 닷넷 이야기
안녕하세요 질문하나만드리겠습니다...! [링크 복사], [링크+제목 복사]
조회: 697
글쓴 사람
김경한 (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)
5544이상호8/18/20211995C# Graphics 객체 저장 가능 여부 [2]
5543정형지8/18/20211968c# outofmemoryexception [3]
5542영귤8/11/20213175C#9.0 886쪽 오류 발생 안 해요 [2]
5541서지훈8/11/20213793C# 응용프로그램(Winform)의 비정상 종료(Exit Code) [2]
5540산들...8/11/20212315C# 많은 Control(Label 300개) Update 관련 문의 [2]파일 다운로드1
5539초초...8/9/20211513c# textbox 입력값이 다름 [1]파일 다운로드1
5538VS8/7/20211762vsmacros 확장자 파일을 사용하는 방법을 알 수 있을까요? [2]
5537민성8/6/20211710안녕하세요 WPF에서 이미 있는창이 있다면 안띠우게 하는 방법 [1]
55358/5/20212429안녕하세요. 초보 웹 개발자입니다. [10]파일 다운로드2
5534하영7/28/20211955clrprofiler 를 사용하여 세션정보 접근 [6]파일 다운로드1
5533함준혁7/20/20211691.net fpspread 관련 질문입니다.. [1]
5532조윤상7/15/20212343바인딩은 성공 했습니다. 그런데 브라우저에서 인증서가 없다고 나옵니다. [2]
5530ocm7/14/20212341pthread_create [7]파일 다운로드1
5529ksc7/13/20212008Source Generator 관련 질문이 있습니다. [1]
5528초심...7/9/20212300MDI 에서 USB 연결해제 알림이 안되는 문제 질문 드려봅니다. [7]파일 다운로드1
5527wu...7/7/20211810제어관련 고민을하다가 소캣방식 선택 [2]
5526이성열7/7/20212572wpf x64로 만든 메인 프로그램에서 dll로 된 UserControl 속성이 디자인타임에 잘 안보이는 문제 [10]파일 다운로드2
5525Wu...7/7/20212840제가 만든 배포파일은 window에서 막는걸까요? [2]파일 다운로드1
5524하이...7/2/20212355특정 이벤트에서 다른 이벤트 호출 관련 문의 [3]
5523민우7/1/20215134도커 사용시 윈도우 이미지 생성도 가능한가요? [2]
5522질문6/28/20213025WPF에서 splash screen이 나타나는 위치를 변경할 수 있나요? [3]
5521김민혁6/24/20212553.exe 파일 에러에 관한 질문 입니다. [3]
5520한예지6/21/20212477랜덤함수 질문있습니다!! [2]
5519리얼킴6/19/20212050.net framwork 4.0 에서 4.8로 꼭 가야할까요?? [1]
5518한예지6/18/20212477ArrayList, IList에 대해 질문 있습니다. [3]
5517wu...6/18/20212828winform에서 Button 활성화, 비활성화 [4]
1  2  3  4  5  6  7  8  9  10  [11]  12  13  14  15  ...