Microsoft MVP성태의 닷넷 이야기
안녕하세요 질문하나만드리겠습니다...! [링크 복사], [링크+제목 복사]
조회: 699
글쓴 사람
김경한 (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분
[김경한] 알겠습니다 선생님 조언해주신대로 좀더 심도있게 고민하고 공부해보겟습니다.!
[손님]

... [16]  17  18  19  20  21  22  23  24  25  26  27  28  29  30  ...
NoWriterDateCnt.TitleFile(s)
5406질문자11/10/20203080안녕하세요 wcf nettcpbinding의 timeout에 관해서 질문이 있습니다. [2]
5405민성11/9/20203480안녕하세요 이번에도 또 어려운 질문 같습니다. [1]
5404박진우11/6/20203736안녕하세요. SqlParameter 생성자 관련 질문 있습니다. [1]
5403민성11/5/20203631그리고 한가지만 죄송하지만 더 질문 드리겠습니다. [1]
5402민성11/5/20203618안녕하세요 책을 보고 질문하나만 드릴깨요 [2]
5401민성11/3/20203395안녕하세요 이번에도 질문 하나만 드리겠습니다. [2]
5400진우10/29/20203240SQL Server 관련 몇가지 문의 [2]
5399Wp...10/21/20203491Binding 된 항목의 갱신 시 간헐적 끊어짐 발생 문제. [2]
5397나그네10/15/20203061.net Core 3.1 에서 Entity Framework 와 ADO.NET 선택에 관해 여쭤봅니다. [2]
5396여정욱10/15/20203111CLR heap 관련 질문 2 [2]
5395여정욱10/14/20203616CLR heap 관련 질문 [2]
5394진우10/12/20206871닷넷코어 (닷넷5) winform wpf는 리눅스/맥에서도 가능한가요? [2]
5393김세용9/23/20204142C#에서 대량의 클래스를 빠르게 생성하는 방법이 없을까요? [6]
5392전경호9/22/20203498WPF에서 WindowsFormsHost의 메모리 누수 문제 때문에 문의드립니다. [1]파일 다운로드1
5391민성9/22/20203548안녕하세요 항상 감사드립니다. 하나 질문 드리겠습니다. [1]
5390al...9/18/20205033System.AccessViolationException 보호된메모리 부분 예외처리 [1]
5389C#...9/18/20203879후위 증감 연산자 오버로딩 방법 좀 알려주세요 [4]
5388영귤9/17/20204162Nullable reference type 에 Non-nullable reference type 을 대입해도 경고가 발생하지 않습니다. [2]
5387하태9/17/20203559안녕하세요! 비동기 통신과 관련하여 질문하나만 드리겠습니다! [3]
5386박민웅9/16/20204141정성태 스승님 안녕하세요 !! [1]
5385영귤9/12/202032413항 연산자에 ref 지원? [1]
5384손님9/10/20203006시작하세요! C# 8.0 프로그래밍 책에 오타가 있는 것 같습니다. [3]
5383민성9/8/20204206안녕하세요 자주 도움을 주셔서 감사드립니다. WPF에서 크롬 브라우저 삽입에 대하여 [1]
5382정씨9/4/20203877[C#] 시리얼통신 수신된 데이터를 그리드뷰에 뿌르는데 일정 시간이 지나면 버벅 거리는 이유가 뭘까요?? [3]
5381질문...9/4/20203660웹으로 사용하는 c#과 응용프로그램으로 사용하는 c#이 많이 다른가요?? [2]
5380ye...9/3/20203491winform 의 datagridview는 바인딩이 안 되나요? [1]
... [16]  17  18  19  20  21  22  23  24  25  26  27  28  29  30  ...