본문 바로가기

C#/공부

C# 실력 늘리기 11일차

196~198. 채팅하기: 채팅 프로그램을 만들어보자

 

Server (Console): Listener의 IP를 IPAdress.Any로 수정

 

using System;
using System.Collections;
using System.IO;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;

namespace ConsoleServer
{
    class Program
    {
        static void Main(string[] args)
        {
            Server server = new Server();
            server.Echo();
        }
        public class Server
        {
            public const int PORT = 5555;
            TcpListener listener = null;
            public static ArrayList handleList = new ArrayList(10);
            public Server()
            {
                handleList.Clear();
            }
            public void Echo()
            {
                try
                {
                    IPAddress address = Dns.GetHostEntry("").AddressList[0];
                    //listener = new TcpListener(address, PORT);
                    listener = new TcpListener(IPAddress.Any, PORT);
                    listener.Start();
                    Console.WriteLine("Server ready 1-------");
                    while (true)
                    {
                        TcpClient client = listener.AcceptTcpClient(); //클라이언트 개당 소켓생성
                        EchoHandler handler = new EchoHandler(this, client);
                        Add(handler);
                        handler.start();
                    }
                }
                catch (Exception ee)
                {
                    Console.WriteLine("2--------------------");
                    System.Console.WriteLine(ee.Message);
                }
                finally
                {
                    Console.WriteLine("3--------------------");
                    listener.Stop();
                }
            }
            public void Add(EchoHandler handler)
            {
                lock (handleList.SyncRoot)
                    handleList.Add(handler);
            }
            public void broadcast(String str)
            {
                lock (handleList.SyncRoot)
                {
                    string dstes = DateTime.Now.ToString() + " : ";
                    Console.Write(dstes);
                    Console.WriteLine(str);
                    foreach (EchoHandler handler in handleList)
                    {
                        EchoHandler echo = handler as EchoHandler;
                        if (echo != null)
                            echo.sendMessage(str);
                    }
                }
            }
            public void Remove(EchoHandler handler)
            {
                lock (handleList.SyncRoot)
                    handleList.Remove(handler);
            }
        }
        public class EchoHandler
        {
            Server server;
            TcpClient client;
            NetworkStream ns = null;
            StreamReader sr = null;
            StreamWriter sw = null;
            string str = string.Empty;

            string clientName;
            public EchoHandler(Server server, TcpClient client)
            {
                this.server = server;
                this.client = client;
                try
                {
                    ns = client.GetStream();
                    Socket socket = client.Client;
                    clientName = socket.RemoteEndPoint.ToString();
                    Console.WriteLine(clientName + " 접속");
                    sr = new StreamReader(ns, Encoding.Default);
                    sw = new StreamWriter(ns, Encoding.Default);
                }
                catch (Exception) { Console.WriteLine("연결 실패"); }
            }
            public void start()
            {
                Thread t = new Thread(new ThreadStart(ProcessClient));
                t.Start();
            }
            public void ProcessClient()
            {
                try
                {
                    while ((str = sr.ReadLine()) != null)
                        server.broadcast(str);
                }
                catch (Exception)
                {
                    Console.WriteLine(clientName + " 접속해제");
                    sw.Flush();
                }
                finally
                {
                    server.Remove(this);
                    sw.Close();
                    sr.Close();
                    client.Close();
                }
            }
            public void sendMessage(string message){
                sw.WriteLine(message);
                sw.Flush();
            }
        }
    }
}

 

Client (WinForm): 쓸데없는 기능들은 제외하고, 필요한 기능들만 구현

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace Chatting
{
    public partial class Form1 : Form
    {
        string serverIP, dialogName;
        int serverPort;
        bool isAlive = false;
        NetworkStream ns = null;
        StreamReader sr = null;
        StreamWriter sw = null;
        TcpClient client = null;

        public Form1()
        {
            InitializeComponent();
            IPHostEntry hostIP = Dns.GetHostByName(Dns.GetHostName());
            serverIP = hostIP.AddressList[0].ToString();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            this.txtPort.Text = 5555.ToString();
            this.txtIP.Text = serverIP.ToString();
            this.txtPort.Enabled = false;
            this.txtIP.Enabled = false;
        }
        private void btnConnect_Click(object sender, EventArgs e)
        {
            dialogName = this.txtName.Text;
            if (string.IsNullOrEmpty(dialogName))
            {
                MessageBox.Show("대화명을 입력하세요.");
                return;
            }
            if (string.IsNullOrEmpty(serverIP))
            {
                MessageBox.Show("주소를 입력하세요.");
                return;
            }
            if (string.IsNullOrEmpty(this.txtPort.Text))
            {
                MessageBox.Show("포트를 입력하세요.");
                return;
            }
            serverPort = Int32.Parse(this.txtPort.Text);
            isAlive = true;
            try
            {
                this.Echo();
                sendMessage("[" + dialogName + " 입장]");
                //this.txtSend.Focus();
            }
            catch (Exception)
            {
                this.txtName.Clear();
                this.isAlive = false;
            }
        }
        private void txtSend_KeyPress(object sender, KeyPressEventArgs e)
        {
            if ((int)Keys.Enter == e.KeyChar)
            {
                string message = this.txtSend.Text;
                sendMessage("[" + dialogName + "] " + message.Trim());
                this.txtSend.Clear();
                this.txtSend.SelectionStart = 0;
            }
        }
        private void btnExit_Click(object sender, EventArgs e)
        {
            try
            {
                sendMessage("[" + dialogName + " 퇴장]");
                sr.Close();
                sw.Close();
                ns.Close();
            }
            catch { }
            finally
            {
                this.Dispose();
            }
        }
        public void Echo()
        {
            try
            {
                client = new TcpClient(this.serverIP, this.serverPort);
                ns = client.GetStream();
                sr = new StreamReader(ns, Encoding.Default);
                sw = new StreamWriter(ns, Encoding.Default);
                Thread receiveThread = new Thread(new ThreadStart(run));
                receiveThread.IsBackground = true;
                receiveThread.Start();
            }
            catch (Exception e)
            {
                MessageBox.Show("서버 시작 실패");
                throw e;
            }
        }
        public void run()
        {
            string message = "start";
            try
            {
                if (client.Connected && sr != null)
                    while ((message = sr.ReadLine()) != null)
                        AppendMessage(message);
            }
            catch (Exception) { MessageBox.Show("error"); }
        }
        public void AppendMessage(string message)
        {
            if (this.txtDialog != null && this.txtSend != null)
            {
                this.txtDialog.AppendText(message + "\r\n");
                this.txtDialog.Focus();
                this.txtDialog.ScrollToCaret();
            }
        }
        private void sendMessage(string message)
        {
            try
            {
                if (sw != null)
                {
                    sw.WriteLine(message);
                    sw.Flush();
                }
            }
            catch (Exception) { MessageBox.Show("전송실패"); }
        }
    }
}

 

MessageBox 잔상이 심령사진급

 

 

 

199~200. 학생 정보 관리하기: 데이터베이스를 이용하여 학생의 정보를 관리해 보자.

 

마지막 문제다...

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Database
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            gbShow.Visible = false;
            gbInsert.Visible = false;
            gbDelete.Visible = false;
        }
        private void rbShow_CheckedChanged(object sender, EventArgs e)
        {
            if (rbShow.Checked)
                gbShow.Visible = true;
            else
                gbShow.Visible = false;
        }
        private void rbInsert_CheckedChanged(object sender, EventArgs e)
        {
            if (rbInsert.Checked)
                gbInsert.Visible = true;
            else
                gbInsert.Visible = false;
        }
        private void rbDelete_CheckedChanged(object sender, EventArgs e)
        {
            if (rbDelete.Checked)
                gbDelete.Visible = true;
            else
                gbDelete.Visible = false;
        }
        private void btnShowAll_Click(object sender, EventArgs e)
        {
            this.studentTableAdapter.Fill(this.studentDataSet.Student);
        }
        private void btnShowEX_Click(object sender, EventArgs e)
        {
            this.studentTableAdapter.FillByAll(this.studentDataSet.Student);
        }
        private void btnID_Click(object sender, EventArgs e)
        {
            string id = txtID.Text;
            if (string.IsNullOrEmpty(id))
            {
                MessageBox.Show("아이디를 입력하세요");
                return;
            }
            try
            {
                studentTableAdapter.FillByID(studentDataSet.Student, id);
                int count = studentTableAdapter.GetDataByID(id).Rows.Count;
                if (count <= 0)
                {
                    throw new Exception("찾는 학생이 없습니다.");
                }
            }
            catch (Exception ee) { MessageBox.Show(ee.Message); }
        }
        private void btnName_Click(object sender, EventArgs e)
        {
            string name = txtName.Text;
            if (string.IsNullOrEmpty(name))
            {
                MessageBox.Show("이름을 입력하세요");
                return;
            }
            try
            {
                studentTableAdapter.FillByName(studentDataSet.Student, "%" + name + "%");
                int count = studentTableAdapter.GetDataByName("%" + name + "%").Rows.Count;
                if (count <= 0)
                {
                    throw new Exception("찾는 학생이 없습니다.");
                }
            }
            catch (Exception ee) { MessageBox.Show(ee.Message); }
        }
        private void btnInsert_Click(object sender, EventArgs e)
        {
            string id = txtID.Text;
            string name = txtName.Text;
            string phone = txtPhone.Text;
            string address = txtAddress.Text;
            if (string.IsNullOrEmpty(id) || string.IsNullOrEmpty(name)
                || string.IsNullOrEmpty(phone) || string.IsNullOrEmpty(address))
            {
                MessageBox.Show("빈칸이 존재합니다.");
                return;
            }
            int count = 0;
            try
            {
                count = studentTableAdapter.InsertQuery(id, name, phone, address);
                studentTableAdapter.FillByID(studentDataSet.Student, id);
                MessageBox.Show("학생을 추가했습니다.");
            }
            catch { MessageBox.Show("추가 실패"); }
        }
        private void btnUpdate_Click(object sender, EventArgs e)
        {
            string id = txtID.Text;
            string name = txtName.Text;
            string phone = txtPhone.Text;
            string address = txtAddress.Text;
            if (string.IsNullOrEmpty(id) || string.IsNullOrEmpty(name)
                || string.IsNullOrEmpty(phone) || string.IsNullOrEmpty(address))
            {
                MessageBox.Show("빈칸이 존재합니다.");
                return;
            }
            int count = 0;
            try
            {
                count = studentTableAdapter.UpdateQuery(name, phone, address,id);
                studentTableAdapter.FillByID(studentDataSet.Student, id);
                MessageBox.Show("갱신했습니다.");
            }
            catch { MessageBox.Show("갱신 실패"); }
        }
        private void btnDelete_Click(object sender, EventArgs e)
        {
            string id = txtDelete.Text;
            if (string.IsNullOrEmpty(id))
            {
                MessageBox.Show("아이디를 입력하세요");
                return;
            }
            try
            {
                studentTableAdapter.DeleteQuery(id);
                int count = studentTableAdapter.GetDataByID(id).Rows.Count;
                if (count > 0)
                    throw new Exception("삭제 실패");
                MessageBox.Show("삭제되었습니다.");
            }
            catch (Exception ee) { MessageBox.Show(ee.Message); }
            this.studentTableAdapter.FillByAll(this.studentDataSet.Student);
        }
        private void btnExit_Click(object sender, EventArgs e)
        {
            string id = txtDelete.Text;
            if (string.IsNullOrEmpty(id))
            {
                MessageBox.Show("아이디를 입력하세요");
                return;
            }
            try
            {
                studentTableAdapter.ExitID(id);
                int count=studentTableAdapter.GetDataByExitID(id).Rows.Count;
                if (count <= 0)
                    throw new Exception("탈퇴 실패");
                MessageBox.Show("탈퇴되었습니다.");
            }
            catch (Exception ee) { MessageBox.Show(ee.Message); }
            this.studentTableAdapter.FillByAll(this.studentDataSet.Student);
        }
    }
}

 

테이블과 쿼리 정보

 

 

 

 

C# 실력 늘리기 시리즈는 일단은 이게 마지막이다.

향후 계획은 여기저기 흩어져 있는 프로젝트를 정리한 후, 안드로이드나 C++을 연재할 생각이다.

'C# > 공부' 카테고리의 다른 글

C# 실력 늘리기 10일차  (0) 2022.08.01
C# 실력 늘리기 9일차  (0) 2022.07.29
C# 실력 늘리기 8일차  (0) 2022.07.28
C# 실력 늘리기 7일차  (0) 2022.07.27
C# 실력 늘리기 6일차  (0) 2022.07.26