1. 유튜브 동영상 강의
이번 강의는 파일 수신 서버 구현 실습이예요.
이전 글(P2P 메신저 - 파일 전송 클라이언트 구현 [C#]) 이 필요하겠네요.
2. 이벤트 인자 및 대리자 소스 코드
2.1 연결 요청 수락 이벤트 인자 및 대리자
using System;
using System.Net;
namespace 파일_수신_서버
{
public delegate void AcceptedEventHandler(object sender, AcceptedEventArgs e);
public class AcceptedEventArgs:EventArgs
{
public IPEndPoint RemoteEndPoint
{
get;
private set;
}
public string IPStr
{
get
{
return RemoteEndPoint.Address.ToString();
}
}
public int Port
{
get
{
return RemoteEndPoint.Port;
}
}
public AcceptedEventArgs(IPEndPoint rep)
{
RemoteEndPoint = rep;
}
}
}
2.2 연결 종료 이벤트 인자 및 대리자
using System.Net;
namespace 파일_수신_서버
{
public delegate void ClosedEventHandler(object sender, ClosedEventArgs e);
public class ClosedEventArgs
{
public IPEndPoint RemoteEndPoint
{
get;
private set;
}
public string IPStr
{
get
{
return RemoteEndPoint.Address.ToString();
}
}
public int Port
{
get
{
return RemoteEndPoint.Port;
}
}
public ClosedEventArgs(IPEndPoint rep)
{
RemoteEndPoint = rep;
}
}
}
2.3 파일 이름 수신 이벤트 인자 및 대리자
using System;
using System.Net;
namespace 파일_수신_서버
{
public delegate void RecvFileNameEventHandler(object sender, RecvFileNameEventArgs e);
public class RecvFileNameEventArgs:EventArgs
{
public IPEndPoint RemoteEndPoint
{
get;
private set;
}
public string FileName
{
get;
private set;
}
public RecvFileNameEventArgs(string fname,IPEndPoint rep)
{
FileName = fname;
RemoteEndPoint = rep;
}
}
}
2.4 파일 길이 수신 이벤트 인자 및 대리자
using System;
using System.Net;
namespace 파일_수신_서버
{
public delegate void FIleLengthRecvEventHandler(object sender, FIleLengthRecvEventArgs e);
public class FIleLengthRecvEventArgs:EventArgs
{
public IPEndPoint RemoteEndPoint
{
get;
private set;
}
public string FileName
{
get;
private set;
}
public long Length
{
get;
private set;
}
public FIleLengthRecvEventArgs(string fname,IPEndPoint rep,long length)
{
FileName = fname;
RemoteEndPoint = rep;
Length = length;
}
}
}
2.4 파일 데이터 수신 이벤트 인자 및 대리자
using System;
using System.Net;
namespace 파일_수신_서버
{
public delegate void FileDataRecvEventHandler(object sender, FileDataRecvEventArgs e);
public class FileDataRecvEventArgs:EventArgs
{
public IPEndPoint RemoteEndPoint
{
get;
private set;
}
public string FileName
{
get;
private set;
}
public long RemainLength
{
get;
private set;
}
public byte[] Data
{
get;
private set;
}
public FileDataRecvEventArgs(string fname,IPEndPoint rep, long rlen,byte[] data)
{
FileName = fname;
RemoteEndPoint = rep;
RemainLength = rlen;
Data = data;
}
}
}
3. 파일 수신 서버 클래스 소스 코드
/* 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);
sock.Bind(iep);
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;
}
}
}
4. Program.cs 소스 코드
/* https://ehpub.co.kr
* 파일 수신 서버
*/
using System;
using System.IO;
namespace 파일_수신_서버
{
class Program
{
static void Main(string[] args)
{
FileRecvServ fs = new FileRecvServ("192.168.219.106", 10340);
fs.AcceptedEventHandler += Fs_AcceptedEventHandler;
fs.ClosedEventHandler += Fs_ClosedEventHandler;
fs.RecvFileNameEventHandler += Fs_RecvFileNameEventHandler;
fs.FIleLengthRecvEventHandler += Fs_FIleLengthRecvEventHandler;
fs.FileDataRecvEventHandler += Fs_FileDataRecvEventHandler;
fs.Start();
Console.ReadKey();
}
static long length;
static FileStream fs;
private static void Fs_FileDataRecvEventHandler(object sender, FileDataRecvEventArgs e)
{
Console.WriteLine("{0}:{1}에서 {2} 남은 길이:{3}", e.RemoteEndPoint.Address, e.RemoteEndPoint.Port, e.FileName, e.RemainLength);
fs.Write(e.Data, 0, e.Data.Length);
if(e.RemainLength==0)
{
fs.Close();
}
}
private static void Fs_FIleLengthRecvEventHandler(object sender, FIleLengthRecvEventArgs e)
{
Console.WriteLine("{0}:{1}에서 {2} 길이:{3}", e.RemoteEndPoint.Address, e.RemoteEndPoint.Port, e.FileName,e.Length);
length = e.Length;
}
private static void Fs_RecvFileNameEventHandler(object sender, RecvFileNameEventArgs e)
{
Console.WriteLine("{0}:{1}에서 {2}전송 시작", e.RemoteEndPoint.Address, e.RemoteEndPoint.Port, e.FileName);
fs = File.Create(e.FileName);
}
private static void Fs_ClosedEventHandler(object sender, ClosedEventArgs e)
{
Console.WriteLine("{0}:{1}와 연결 해제", e.IPStr, e.Port);
}
private static void Fs_AcceptedEventHandler(object sender, AcceptedEventArgs e)
{
Console.WriteLine("{0}:{1}와 연결", e.IPStr, e.Port);
}
}
}
'C# > 네트워크 프로그래밍 C#' 카테고리의 다른 글
P2P 메신저 – 인증 서비스 구현 및 마무리[C#] (0) | 2024.01.09 |
---|---|
.NET 리모팅 [C#] (0) | 2024.01.09 |
P2P 메신저 – 파일 송수신 기능 구현 [C#] (0) | 2024.01.08 |
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 |