Files
SocketStudy/SocketStudy/PComm/PClient.cs

206 lines
5.4 KiB
C#
Raw Normal View History

2022-11-15 18:16:17 +09:00
using PUtility;
using System;
2022-11-11 18:03:57 +09:00
using System.Collections.Generic;
using System.Diagnostics;
2022-11-14 18:20:31 +09:00
using System.IO;
2022-11-15 18:16:17 +09:00
using System.IO.Compression;
2022-11-11 18:03:57 +09:00
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace PComm
{
public class PClient
{
private readonly int BUFF_SIZE = 8192;
2022-11-14 18:20:31 +09:00
public delegate void ClientReceivedHandler(PClient sender, PDataType dataType, byte[] data);
2022-11-11 18:03:57 +09:00
public event ClientReceivedHandler OnReceived;
public delegate void ClientDisconnectedHandler(PClient sender);
public event ClientDisconnectedHandler Disconnected;
2022-11-14 18:20:31 +09:00
public string ID { get; set; }
2022-11-11 18:03:57 +09:00
public IPEndPoint EndPoint { get; private set; }
public bool Connected { get { return socket.Connected; } }
private Socket socket;
2022-11-14 18:20:31 +09:00
public PClient(string ip, int port, string id = null)
2022-11-11 18:03:57 +09:00
{
2022-11-14 18:20:31 +09:00
if (string.IsNullOrEmpty(id))
id = Guid.NewGuid().ToString();
2022-11-11 18:03:57 +09:00
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
2022-11-14 18:20:31 +09:00
this.ID = id;
2022-11-11 18:03:57 +09:00
this.EndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
2022-11-15 18:16:17 +09:00
socket.Connect(this.EndPoint);
2022-11-11 18:03:57 +09:00
2022-11-14 18:20:31 +09:00
// send ID
this.Send(PDataType.ClientID, Encoding.UTF8.GetBytes(this.ID));
2022-11-11 18:03:57 +09:00
socket.BeginReceive(new byte[] { 0 }, 0, 0, 0, AcceptCallback, null);
}
public PClient(Socket accepted)
{
2022-11-14 18:20:31 +09:00
if (string.IsNullOrEmpty(this.ID))
this.ID = Guid.NewGuid().ToString();
2022-11-11 18:03:57 +09:00
socket = accepted;
this.EndPoint = (IPEndPoint)socket.RemoteEndPoint;
socket.BeginReceive(new byte[] { 0 }, 0, 0, 0, AcceptCallback, null);
}
2022-11-15 18:16:17 +09:00
public void Reconnect()
{
if (socket.Connected)
return;
socket.Connect(this.EndPoint);
this.Send(PDataType.ClientID, Encoding.UTF8.GetBytes(this.ID));
socket.BeginReceive(new byte[] { 0 }, 0, 0, 0, AcceptCallback, null);
}
private int SendData(byte[] data)
{
byte[] toSendData;
// 데이터 크기 100B 이하 또는 50MB 이상 압축하지 않음 (CPU 부하시간 더 큼)
// 압축한 경우 1 전송, 아닌경우 0 전송
if (data.Length <= 100 || data.Length >= 50000000)
{
byte[] isCompressed = BitConverter.GetBytes(false);
socket.Send(isCompressed, SocketFlags.None);
toSendData = data;
}
else
{
byte[] isCompressed = BitConverter.GetBytes(true);
socket.Send(isCompressed, SocketFlags.None);
toSendData = PUtil.CompressBytes(data, CompressionLevel.Optimal);
}
byte[] length = BitConverter.GetBytes(toSendData.Length);
socket.Send(length, 0, 4, SocketFlags.None);
return socket.Send(toSendData, SocketFlags.None);
}
2022-11-11 18:03:57 +09:00
public int Send(string msg)
{
2022-11-14 18:20:31 +09:00
socket.Send(BitConverter.GetBytes((int)PDataType.SimpleString), 0, 4, 0);
byte[] data = Encoding.UTF8.GetBytes(msg);
2022-11-15 18:16:17 +09:00
//byte[] length = BitConverter.GetBytes(data.Length);
//socket.Send(length, 0, 4, 0);
2022-11-14 18:20:31 +09:00
2022-11-15 18:16:17 +09:00
//return socket.Send(data, SocketFlags.None);
return SendData(data);
2022-11-11 18:03:57 +09:00
}
2022-11-14 18:20:31 +09:00
public int Send(PDataType dataType, byte[] data)
2022-11-11 18:03:57 +09:00
{
2022-11-14 18:20:31 +09:00
socket.Send(BitConverter.GetBytes((int)dataType), 0, 4, 0);
2022-11-15 18:16:17 +09:00
//byte[] length = BitConverter.GetBytes(data.Length);
//socket.Send(length, 0, 4, 0);
2022-11-14 18:20:31 +09:00
2022-11-15 18:16:17 +09:00
//return socket.Send(data, SocketFlags.None);
return SendData(data);
2022-11-11 18:03:57 +09:00
}
private void AcceptCallback(IAsyncResult ar)
{
try
{
socket.EndReceive(ar);
2022-11-14 18:20:31 +09:00
// get data type
byte[] dataTypeBuff = new byte[4];
socket.Receive(dataTypeBuff, dataTypeBuff.Length, SocketFlags.None);
PDataType dataType = (PDataType)BitConverter.ToInt32(dataTypeBuff, 0);
2022-11-11 18:03:57 +09:00
2022-11-15 18:16:17 +09:00
// check compressed
byte[] isCompressedBuff = new byte[1];
socket.Receive(isCompressedBuff, isCompressedBuff.Length, SocketFlags.None);
bool isCompressed = BitConverter.ToBoolean(isCompressedBuff, 0);
2022-11-14 18:20:31 +09:00
// get data size
byte[] sizeBuff = new byte[4];
socket.Receive(sizeBuff, sizeBuff.Length, SocketFlags.None);
int dataSize = BitConverter.ToInt32(sizeBuff, 0);
2022-11-15 18:16:17 +09:00
2022-11-14 18:20:31 +09:00
using (MemoryStream ms = new MemoryStream())
2022-11-11 18:03:57 +09:00
{
2022-11-14 18:20:31 +09:00
while (dataSize > 0)
{
byte[] buff;
if (dataSize < BUFF_SIZE)
buff = new byte[dataSize];
else
buff = new byte[BUFF_SIZE];
2022-11-11 18:03:57 +09:00
2022-11-14 18:20:31 +09:00
int receiveSize = socket.Receive(buff, buff.Length, SocketFlags.None);
ms.Write(buff, 0, buff.Length);
dataSize -= receiveSize;
}
2022-11-15 18:16:17 +09:00
byte[] receivedData = ms.ToArray();
byte[] data;
if (isCompressed)
data = PUtil.DecompressBytes(receivedData);
else
data = receivedData;
2022-11-14 18:20:31 +09:00
if (OnReceived != null)
OnReceived(this, dataType, data);
2022-11-15 18:16:17 +09:00
socket.BeginReceive(new byte[] { 0 }, 0, 0, 0, AcceptCallback, null);
}
2022-11-11 18:03:57 +09:00
}
catch (Exception ex)
{
2022-11-15 18:16:17 +09:00
Debug.WriteLine($"[ERROR] CleintAcceptCallback: {ex.Message}");
PFileManager.Instance.WriteLog($"[ERROR] CleintAcceptCallback: {ex.Message}");
if (CheckSocketConnection(socket))
{
socket.BeginReceive(new byte[] { 0 }, 0, 0, 0, AcceptCallback, null);
}
else
{
Debug.WriteLine($"[ERROR] Close socket {socket.RemoteEndPoint.ToString()}");
PFileManager.Instance.WriteLog($"[ERROR] Close socket {socket.RemoteEndPoint.ToString()}");
2022-11-11 18:03:57 +09:00
2022-11-15 18:16:17 +09:00
Close();
2022-11-11 18:03:57 +09:00
2022-11-15 18:16:17 +09:00
if (Disconnected != null)
Disconnected(this);
}
2022-11-11 18:03:57 +09:00
}
}
2022-11-15 18:16:17 +09:00
private bool CheckSocketConnection(Socket socket)
{
bool availability = socket.Available == 0;
bool poll = socket.Poll(1000, SelectMode.SelectRead);
if (availability && poll)
return false;
else
return true;
}
2022-11-11 18:03:57 +09:00
public void Close()
{
socket.Close();
socket.Dispose();
}
}
}