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 |