일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- c#
- 표준 라이브러리 함수
- c언어
- 캡슐화
- 네트워크 프로그래밍
- 원격 제어 프로그램
- 소스 코드
- Windows Forms
- 동영상 강의
- 실습
- 유튜브 동영상 강의
- 언제나휴일
- 파이썬
- 클래스 다이어그램
- 알고리즘
- 표준 입출력
- 소켓 통신
- 산책하기 좋은 곳
- 언제나 휴일
- 무료 동영상 강의
- 추천
- 실습으로 다지는 c#
- 동영상
- 안드로이드 앱 개발
- 졸업 작품
- 졸업 작품 소재
- 충남 천안
- 강의
- C++
- 프로젝트
Archives
- Today
- Total
프로그래밍 언어 및 기술 [언제나휴일]
P2P 메신저 – 인증 서비스 구현 및 마무리[C#] 본문
1. 공용 라이브러리 제작
1.1 유튜브 동영상 강의
1.2 구현 및 소스 코드
앞에서 P2P 메신저의 숏 메시지와 파일 송수신 부분을 구현했어요.
그리고 .NET 리모팅 서비스 제작 방법도 실습했었죠.
이번에는 P2P 메신저의 인증 서비스 부분을 구현해 볼 거예요.
현재 구현은 P2P에서 사용자가 상대 IP 주소와 포트 정보를 설정하고 있어요.
이 부분을 인증 서비스를 구현하여 상대 ID만 선택하여 메시지와 파일을 전송할 수 있게 할 거예요.
이를 위해 먼저 인증 서비스를 위한 공용 라이브러리를 제작합시다.
프로젝트는 클래스 라이브러리(.NET Framework)로 제작합니다.
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace EHAAALib
{
class UserInfo
{
internal string ID
{
get;
private set;
}
internal DateTime LastKA
{
get;
set;
}
internal string IPStr
{
get;
set;
}
internal int SPort
{
get;
set;
}
internal int FPort
{
get;
set;
}
internal int BPort
{
get;
set;
}
internal UserInfo(string id,string ip, int sport,int fport,int bport)
{
ID = id;
IPStr = ip;
SPort = sport;
FPort = fport;
BPort = bport;
}
}
public class EHAAA:MarshalByRefObject
{
const string sfname = "member.xsl";
const string dfname = "member.xml";
DataTable mtb = new DataTable("회원");
Dictionary<string, UserInfo> ui_dic = new Dictionary<string, UserInfo>();
Timer timer = null;
public EHAAA()
{
Initialize();
}
~EHAAA()
{
mtb.WriteXml(dfname);
}
private void Initialize()
{
timer = new Timer(CheckKeepAlive);
timer.Change(0, 3000);
if(File.Exists(sfname))
{
mtb.ReadXmlSchema(sfname);
if(File.Exists(dfname))
{
mtb.ReadXml(dfname);
}
}
else
{
DesignMTB();
}
}
private void DesignMTB()
{
DataColumn dc_id = new DataColumn("id", typeof(string));
dc_id.Unique = true;
dc_id.AllowDBNull = false;
mtb.Columns.Add(dc_id);
DataColumn dc_pw = new DataColumn("pw", typeof(string));
dc_pw.AllowDBNull = false;
mtb.Columns.Add(dc_pw);
DataColumn[] pkeys = new DataColumn[] { dc_id };
mtb.PrimaryKey = pkeys;
mtb.WriteXmlSchema(sfname);
}
void CheckKeepAlive(object state)
{
Console.Write(".");
List dlist = new List();
foreach(KeyValuePair<string,UserInfo> ui in ui_dic)
{
TimeSpan ts = DateTime.Now - ui.Value.LastKA;
if(ts.TotalSeconds>9)
{
dlist.Add(ui.Key);
}
}
foreach(string id in dlist)
{
ui_dic.Remove(id);
Logout2(id);
}
}
private void Logout2(string id)
{
try
{
foreach (UserInfo ui in ui_dic.Values)
{
string oip = ui.IPStr;
int obport = ui.BPort;
SendUserInfoAsync(oip, obport, id, "", 0, 0);
}
}
catch
{
}
}
public void Logout(string id)
{
if(ui_dic.ContainsKey(id) == false)
{
return;
}
ui_dic.Remove(id);
Logout2(id);
}
public bool Join(string id, string pw)
{
try
{
DataRow dr = mtb.NewRow();
dr["id"] = id;
dr["pw"] = pw;
mtb.Rows.Add(dr);
return true;
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
public void Withdraw(string id, string pw)
{
if(ui_dic.ContainsKey(id))
{
DataRow dr = mtb.Rows.Find(id);
if(dr == null)
{
return;
}
if(dr["pw"].ToString() == pw)
{
mtb.Rows.Remove(dr);
Logout(id);
}
}
}
public int Login(string id,string pw)
{
try
{
DataRow dr = mtb.Rows.Find(id);
if(dr == null)
{
return 1;//미가입 ID
}
if(ui_dic.ContainsKey(id) == false)
{
if(dr["pw"].ToString() == pw)
{
return 0;//로긴 성공
}
return 3;//비밀번호 틀림
}
return 2;//이미 로긴 중
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
return 3;//예외 발생
}
}
public void KeepAlive(string id)
{
try
{
if(ui_dic.ContainsKey(id))
{
ui_dic[id].LastKA = DateTime.Now;
}
}
catch
{
}
}
public void KeepAlive(string id,string ipstr,int sport,int fport,int bport)
{
Console.WriteLine("{0}의 첫 번째 KeepAlive,{1},{2}!!!", id, ipstr, bport);
try
{
UserInfo ui = new UserInfo(id, ipstr, sport, fport, bport);
foreach (UserInfo oui in ui_dic.Values)
{
Console.WriteLine("Other:{0}", oui.ID);
string oip = oui.IPStr;
int osport = oui.SPort;
int ofport = oui.FPort;
int obport = oui.BPort;
SendUserInfoAsync(oip, obport, id, ipstr, sport, fport);
SendUserInfoAsync(ipstr, bport, oui.ID, oip, osport, ofport);
}
ui_dic[id] = ui;
ui.LastKA = DateTime.Now;
}
catch
{
}
}
delegate void SUIDele(string oip, int obport, string id, string ipstr, int sport, int fport);
private void SendUserInfoAsync(string oip, int obport, string id, string ipstr, int sport, int fport)
{
SUIDele dele = SendUserInfo;
dele.BeginInvoke(oip, obport, id, ipstr, sport, fport, null, null);
}
private void SendUserInfo(string oip, int obport, string id, string ipstr, int sport, int fport)
{
try
{
Socket sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Parse(oip), obport);
sock.Connect(iep);
byte[] packet = new byte[1024];
MemoryStream ms = new MemoryStream(packet);
BinaryWriter bw = new BinaryWriter(ms);
bw.Write(id);
bw.Write(ipstr);
bw.Write(sport);
bw.Write(fport);
bw.Close();
ms.Close();
sock.Send(packet);
sock.Close();
}
catch
{
//로그 작성
}
}
}
}
2. 인증 서버 및 Peer 구현
2.1 유튜브 동영상 강의
앞에서 P2P 메신저의 숏메시지와 파일 송수신을 구현하였고 인증 서비스의 공용 라이브러리를 제작했어요.
이번에는 인증 서버 및 Peer 부분을 수정하는 작업을 진행할게요.
2.2 Peer 프로그램 - 컨트롤 배치
이전에 만들었던 Form1.cs를 MainForm.cs로 변경합니다.
세 개의 버튼에 이벤트 핸들러를 각각 등록합니다.
lbox_user 선택 변경 이벤트 핸들러를 등록합니다.
timer1의 Tick 이벤트 핸들러를 등록합니다.
폼의 Load 이벤트 핸들러를 등록합니다.
StartForm을 추가한 후 컨트롤 배치하세요.
두 개의 버튼에 클릭 이벤트 핸드러를 등록합니다.
3. Peer 프로그램 소스 코드
3.1 Program.cs 소스 코드
using System;
using System.Windows.Forms;
namespace P2P_예광탄_숏메시지
{
static class Program
{
///
/// 해당 애플리케이션의 주 진입점입니다.
///
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new StartForm());
}
}
}
3.2 StartForm.cs 소스 코드
using EHAAALib;
using System;
using System.Windows.Forms;
namespace P2P_예광탄_숏메시지
{
public partial class StartForm : Form
{
public StartForm()
{
InitializeComponent();
}
private void btn_join_Click(object sender, EventArgs e)
{
if(Eaaa.Join(tbox_id.Text,tbox_pw.Text))
{
MessageBox.Show("가입을 축하합니다.");
}
else
{
MessageBox.Show("가입 실패입니다.");
}
}
EHAAA Eaaa
{
get
{
return Activator.GetObject(
typeof(EHAAA),
"http://인증 서버 IP주소:10800/AAASVC"
) as EHAAA;
}
}
private void btn_login_Click(object sender, EventArgs e)
{
int re = Eaaa.Login(tbox_id.Text, tbox_pw.Text);
if(re == 0)
{
MainForm mf = new MainForm(tbox_id.Text, tbox_pw.Text);
mf.FormClosed += Mf_FormClosed;
this.Visible = false;
mf.ShowDialog();
}
else
{
MessageBox.Show(string.Format("로긴 실패 -{0}", re));
}
}
private void Mf_FormClosed(object sender, FormClosedEventArgs e)
{
this.Visible = true;
}
}
}
3.3 MainForm.cs 소스 코드
using EHAAALib;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Windows.Forms;
using 파일_수신_서버;
using 파일_전송_클라이언트;
namespace P2P_예광탄_숏메시지
{
public partial class MainForm : Form
{
string ID
{
get;
set;
}
string PW
{
get;
set;
}
public MainForm(string id,string pw)
{
ID = id;
PW = pw;
InitializeComponent();
}
private void Sms_SmsgRecvEventHandler(object sender, SmsgRecvEventArgs e)
{
AddMessage(string.Format("{0}:{1}→{2}", e.IPStr, e.Port, e.Msg));
}
delegate void MyDele(string msg);
private void AddMessage(string msg)
{
if(lbox_msg.InvokeRequired)
{
MyDele dele = AddMessage;
object[] objs = new object[] { msg };
lbox_msg.BeginInvoke(dele, objs);
}
else
{
lbox_msg.Items.Add(msg);
}
}
string other_ip;
int other_port=10300;
private void btn_send_Click(object sender, EventArgs e)
{
SmsgClient.SendMsgAsync(other_ip, other_port, tbox_msg.Text);
lbox_msg.Items.Add(string.Format("{0}:{1}←{2}", other_ip, other_port, tbox_msg.Text));
tbox_msg.Text = "";
}
private void lbox_msg_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.All;
}
private void lbox_msg_DragDrop(object sender, DragEventArgs e)
{
FileSendClient fsc = new FileSendClient(other_ip, other_fport);
fsc.SendFileDataEventHandler += Fsc_SendFileDataEventHandler;
string[] fs = e.Data.GetData(DataFormats.FileDrop) as string[];
foreach(string f in fs)
{
fsc.SendAsync(f);
string msg = string.Format("{0}:{1}에게 {2}파일 전송 시작", other_ip, other_fport);
AddMessage(msg);
}
}
private void Fsc_SendFileDataEventHandler(object sender, SendFileDataEventArgs e)
{
if(e.Remain ==0)
{
string msg = string.Format("{0}파일 {1}bytes 남음...", e.FileName, e.Remain);
AddMessage(msg);
}
}
Dictionary<string, FileStream> fsdic = new Dictionary<string, FileStream>();
private void Frs_RecvFileNameEventHandler(object sender, RecvFileNameEventArgs e)
{
string fname = e.FileName;
int index = fname.LastIndexOf(@"\");
if(index !=-1)
{
fname = fname.Substring(index + 1);
}
FileStream fs = File.Create(fname);
fsdic[e.FileName] = fs;
}
private void Frs_FIleLengthRecvEventHandler(object sender, FIleLengthRecvEventArgs e)
{
string msg = string.Format("{0}:{1}에서 파일{2},{3}bytes 전송 시작", e.RemoteEndPoint.Address, e.RemoteEndPoint.Port, e.FileName, e.Length);
AddMessage(msg);
}
private void Frs_FileDataRecvEventHandler(object sender, FileDataRecvEventArgs e)
{
FileStream fs = fsdic[e.FileName];
fs.Write(e.Data, 0, e.Data.Length);
if(e.RemainLength ==0)
{
string msg = string.Format("{0}:{1}에서 파일{2} 전송 완료", e.RemoteEndPoint.Address, e.RemoteEndPoint.Port, e.FileName);
AddMessage(msg);
fs.Close();
}
}
private void Frs_ClosedEventHandler(object sender, ClosedEventArgs e)
{
string msg = string.Format("{0}:{1}파일 전송을 마치고 연결 해제", e.IPStr, e.Port);
AddMessage(msg);
}
private void Frs_AcceptedEventHandler(object sender, AcceptedEventArgs e)
{
string msg = string.Format("{0}:{1}파일 전송을 위해 연결", e.IPStr, e.Port);
AddMessage(msg);
}
int other_fport;
EHAAA Eaaa
{
get
{
return Activator.GetObject(
typeof(EHAAA),
"http://인증 서버 IP주소:10800/AAASVC"
) as EHAAA;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
Eaaa.KeepAlive(ID);
}
private void btn_logout_Click(object sender, EventArgs e)
{
Eaaa.Logout(ID);
timer1.Enabled = false;
Close();
}
private void btn_withdraw_Click(object sender, EventArgs e)
{
Eaaa.Withdraw(ID, PW);
timer1.Enabled = false;
Close();
}
int sport = 10400;
int fport = 10200;
int bport = 10600;
private void MainForm_Load(object sender, EventArgs e)
{
timer1.Enabled = true;
MySSet();
MyFSet();
UserInfoCSServer ucbs = new UserInfoCSServer(DefAddress.ToString(), bport);
ucbs.UserInfoEventHandler += Ucbs_UserInfoEventHandler;
if(ucbs.Start()==false)
{
MessageBox.Show("허거거^^;;");
}
bport = ucbs.Port;
Eaaa.KeepAlive(ID, DefAddress.ToString(), sport, fport, bport);
}
private void Ucbs_UserInfoEventHandler(object sender, UserInfoEventArgs e)
{
if(e.FPort == 0)
{
UserInfoEventArgs ru = null;
foreach (UserInfoEventArgs uiea in lbox_user.Items)
{
if(uiea.ID == e.ID)
{
ru = uiea;
break;
}
}
if(ru != null)
{
lbox_user.Items.Remove(ru);
}
}
else
{
lbox_user.Items.Add(e);
}
}
IPAddress DefAddress
{
get
{
string hname = Dns.GetHostName();
IPHostEntry ihe = Dns.GetHostEntry(hname);
foreach(IPAddress ipaddr in ihe.AddressList)
{
if(ipaddr.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
return ipaddr;
}
}
return IPAddress.Any;
}
}
private void MyFSet()
{
FileRecvServ frs = new FileRecvServ(DefAddress.ToString(), fport);
frs.AcceptedEventHandler += Frs_AcceptedEventHandler;
frs.ClosedEventHandler += Frs_ClosedEventHandler;
frs.FileDataRecvEventHandler += Frs_FileDataRecvEventHandler;
frs.FIleLengthRecvEventHandler += Frs_FIleLengthRecvEventHandler;
frs.RecvFileNameEventHandler += Frs_RecvFileNameEventHandler;
if (frs.Start() == false)
{
MessageBox.Show("파일 수신 서버 가동 실패");
}
else
{
fport = frs.Port;
}
}
private void MySSet()
{
SmsgServer sms = new SmsgServer(DefAddress.ToString(), sport);
sms.SmsgRecvEventHandler += Sms_SmsgRecvEventHandler;
if (sms.Start() == false)
{
MessageBox.Show("숏메시지 서버 가동 실패!");
}
else
{
sport = sms.Port;
}
}
private void lbox_user_SelectedIndexChanged(object sender, EventArgs e)
{
UserInfoEventArgs uie = lbox_user.SelectedItem as UserInfoEventArgs;
other_ip = uie.IPStr;
other_port = uie.SPort;
other_fport = uie.FPort;
}
}
}
3.4 SmsgClient.cs 소스 코드
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace P2P_예광탄_숏메시지
{
public static class SmsgClient
{
public static void SendMsgAsync(string other_ip, int other_port, string text)
{
SendDele dele = SendMsg;
dele.BeginInvoke(other_ip, other_port, text, null, null);
}
delegate void SendDele(string other_ip, int other_port, string text);
public static void SendMsg(string other_ip, int other_port, string text)
{
try
{
byte[] packet = new byte[1024];
MemoryStream ms = new MemoryStream(packet);
BinaryWriter bw = new BinaryWriter(ms);
bw.Write(text);
bw.Close();
ms.Close();
Socket sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Parse(other_ip), other_port);
sock.Connect(iep);
sock.Send(packet);
sock.Close();
}
catch
{
}
}
}
}
3.5 SmsgRecvEventArgs.cs
using System;
using System.Net;
namespace P2P_예광탄_숏메시지
{
public delegate void SmsgRecvEventHandler(object sender, SmsgRecvEventArgs e);
public class SmsgRecvEventArgs:EventArgs
{
public IPEndPoint RemoteEndPoint
{
get;
private set;
}
public string Msg
{
get;
private set;
}
public string IPStr
{
get
{
return RemoteEndPoint.Address.ToString();
}
}
public int Port
{
get
{
return RemoteEndPoint.Port;
}
}
public SmsgRecvEventArgs(IPEndPoint remote,string msg)
{
RemoteEndPoint = remote;
Msg = msg;
}
}
}
3.6 SmsgServer.cs 소스 코드
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace P2P_예광탄_숏메시지
{
public class SmsgServer
{
public event SmsgRecvEventHandler SmsgRecvEventHandler = null;
public string IPStr
{
get;
private set;
}
public int Port
{
get;
private set;
}
public SmsgServer(string ipstr, int port)
{
IPStr = ipstr;
Port = port;
}
Socket sock;
public bool Start()
{
try
{
sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Parse(IPStr), Port);
bool check = true;
while(check)
{
try
{
sock.Bind(iep);
check = false;
}
catch
{
Port += 2;
iep = new IPEndPoint(IPAddress.Parse(IPStr), Port);
}
}
sock.Listen(5);
AcceptLoopAsync();
return true;
}
catch
{
return false;
}
}
delegate void AcceptDele();
private void AcceptLoopAsync()
{
AcceptDele dele = AcceptLoop;
dele.BeginInvoke(null, null);
}
private void AcceptLoop()
{
Socket dosock;
while(true)
{
dosock = sock.Accept();
DoIt(dosock);
}
}
private void DoIt(Socket dosock)
{
IPEndPoint remote = dosock.RemoteEndPoint as IPEndPoint;
byte[] packet = new byte[1024];
dosock.Receive(packet);
dosock.Close();
MemoryStream ms = new MemoryStream(packet);
BinaryReader br = new BinaryReader(ms);
string msg = br.ReadString();
br.Close();
ms.Close();
if(SmsgRecvEventHandler != null)
{
SmsgRecvEventHandler(this, new SmsgRecvEventArgs(remote,msg));
}
}
}
}
3.7 UserInfoCSServer.cs
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace P2P_예광탄_숏메시지
{
public class UserInfoCSServer
{
public event UserInfoEventHandler UserInfoEventHandler = null;
public string IPStr
{
get;
set;
}
public int Port
{
get;
set;
}
public UserInfoCSServer(string ipstr, int port)
{
IPStr = ipstr;
Port = port;
}
Socket sock = null;
public bool Start()
{
try
{
sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPAddress ipaddr = IPAddress.Parse(IPStr);
IPEndPoint iep = new IPEndPoint(ipaddr, Port);
bool check = true;
while(check)
{
try
{
sock.Bind(iep);
check = false;
}
catch
{
Port += 2;
iep = new IPEndPoint(ipaddr, Port);
}
}
sock.Listen(5);
AcceptLoopAsync();
return true;
}
catch
{
return false;
}
}
delegate void AcceptDele();
private void AcceptLoopAsync()
{
AcceptDele dele = AcceptLoop;
dele.BeginInvoke(null, null);
}
private void AcceptLoop()
{
Socket dosock;
while (true)
{
dosock = sock.Accept();
DoItAsync(dosock);
}
}
delegate void DoItDele(Socket dosock);
private void DoItAsync(Socket dosock)
{
DoItDele dele = DoIt;
dele.BeginInvoke(dosock, null, null);
}
private void DoIt(Socket dosock)
{
byte[] packet = new byte[1024];
dosock.Receive(packet);
MemoryStream ms = new MemoryStream(packet);
BinaryReader br = new BinaryReader(ms);
string id = br.ReadString();
string ip = br.ReadString();
int sport = br.ReadInt32();
int fport = br.ReadInt32();
br.Close();
ms.Close();
if(UserInfoEventHandler != null)
{
UserInfoEventHandler(this, new UserInfoEventArgs(id, ip, sport, fport));
}
dosock.Close();
}
}
}
3.8 UserInfoEventArgs.cs
using System;
namespace P2P_예광탄_숏메시지
{
public delegate void UserInfoEventHandler(object sender, UserInfoEventArgs e);
public class UserInfoEventArgs:EventArgs
{
public string ID
{
get;
private set;
}
public string IPStr
{
get;
private set;
}
public int SPort
{
get;
private set;
}
public int FPort
{
get;
private set;
}
public UserInfoEventArgs(string id, string ipstr, int sport,int fport)
{
ID = id;
IPStr = ipstr;
SPort = sport;
FPort = fport;
}
public override string ToString()
{
return ID;
}
}
}
4. 파일 송수신 라이브러리 수정
FileRecvServ.cs 파일 수정 후 소스 코드입니다.
/* https://ehpub.co.kr
* 파일 수신 서버
*/
using System;
using System.Diagnostics.Eventing.Reader;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace 파일_수신_서버
{
public class FileRecvServ
{
const int MAX_PACK_SIZE = 1024;
public event AcceptedEventHandler AcceptedEventHandler = null;
public event ClosedEventHandler ClosedEventHandler = null;
public event RecvFileNameEventHandler RecvFileNameEventHandler = null;
public event FIleLengthRecvEventHandler FIleLengthRecvEventHandler = null;
public event FileDataRecvEventHandler FileDataRecvEventHandler = null;
public string IPStr
{
get;
private set;
}
public int Port
{
get;
private set;
}
public FileRecvServ(string ip,int port)
{
IPStr = ip;
Port = port;
}
Socket sock;
public bool Start()
{
try
{
sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPAddress ipaddr = IPAddress.Parse(IPStr);
IPEndPoint iep = new IPEndPoint(ipaddr, Port);
bool check = true;
while (check)
{
try
{
sock.Bind(iep);
check = false;
}
catch
{
Port += 2;
iep = new IPEndPoint(ipaddr, Port);
}
}
sock.Listen(5);
AcceptLoopAsync();
}
catch
{
return false;
}
return true;
}
delegate void AcceptDele();
private void AcceptLoopAsync()
{
AcceptDele dele = AcceptLoop;
dele.BeginInvoke(null, null);
}
private void AcceptLoop()
{
while(true)
{
Socket dosock = sock.Accept();
DoItAsync(dosock);
}
}
Thread thread;
private void DoItAsync(object dosock)
{
ParameterizedThreadStart pts = DoIt;
thread = new Thread(pts);
thread.Start(dosock);
}
void DoIt(object osock)
{
Socket dosock = osock as Socket;
IPEndPoint rep = dosock.RemoteEndPoint as IPEndPoint;
if(AcceptedEventHandler != null)
{
AcceptedEventHandler(this, new AcceptedEventArgs(rep));
}
string fname = RecvFileName(dosock);
if(RecvFileNameEventHandler != null)
{
RecvFileNameEventHandler(this, new RecvFileNameEventArgs(fname, rep));
}
long length = RecvFileLength(dosock);
if(FIleLengthRecvEventHandler !=null)
{
FIleLengthRecvEventHandler(this, new FIleLengthRecvEventArgs(fname, rep, length));
}
RecvFile(dosock, fname, length);
dosock.Close();
if(ClosedEventHandler != null)
{
ClosedEventHandler(this, new ClosedEventArgs(rep));
}
}
private void RecvFile(Socket dosock, string fname, long length)
{
IPEndPoint rep = dosock.RemoteEndPoint as IPEndPoint;
byte[] packet = new byte[MAX_PACK_SIZE];
while(length>=MAX_PACK_SIZE)
{
int rlen = dosock.Receive(packet);
if(FileDataRecvEventHandler != null)
{
byte[] pd2 = new byte[rlen];
MemoryStream ms = new MemoryStream(pd2);
ms.Write(packet, 0, rlen);
FileDataRecvEventHandler(this, new FileDataRecvEventArgs(fname, rep, length, pd2));
}
length -= rlen;
}
dosock.Receive(packet, (int)length, SocketFlags.None);
if (FileDataRecvEventHandler != null)
{
byte[] pd2 = new byte[length];
MemoryStream ms = new MemoryStream(pd2);
ms.Write(packet, 0,(int)length);
FileDataRecvEventHandler(this, new FileDataRecvEventArgs(fname, rep, 0, pd2));
}
}
private long RecvFileLength(Socket dosock)
{
byte[] packet = new byte[8];
dosock.Receive(packet);
MemoryStream ms = new MemoryStream(packet);
BinaryReader br = new BinaryReader(ms);
long length = br.ReadInt64();
br.Close();
ms.Close();
return length;
}
private string RecvFileName(Socket dosock)
{
byte[] packet = new byte[MAX_PACK_SIZE];
dosock.Receive(packet);
MemoryStream ms = new MemoryStream(packet);
BinaryReader br = new BinaryReader(ms);
string fname = br.ReadString();
br.Close();
ms.Close();
return fname;
}
}
}
'C# > 네트워크 프로그래밍 C#' 카테고리의 다른 글
.NET 리모팅 [C#] (0) | 2024.01.09 |
---|---|
P2P 메신저 – 파일 송수신 기능 구현 [C#] (0) | 2024.01.08 |
P2P 메신저 - 파일 수신 서버 구현 [C#] (0) | 2024.01.07 |
P2P 메신저 - 파일 전송 클라이언트 구현 [C#] (0) | 2024.01.07 |
P2P 메신저 – 숏 메시지 송수신 예광탄 구현하기 [C#] (1) | 2024.01.06 |
TCP 통신 – Echo 서버 클래스 구현, 이벤트 정의 및 콜백 처리 [C#] (1) | 2024.01.05 |
TCP 통신 – echo 서버 및 클라이언트 구현 [네트워크 프로그래밍 C#] (2) | 2024.01.04 |