C# TCPServer with WebSocket
public class TcpServerWS
{
private static TcpServerWS _instance;
public static TcpServerWS Instance { get { return _instance; } }
private TcpListener m_TcpListener;
private int _nPort = 13000;
private string _sIPAddress;
private List<DeviceTcpClient> m_Clients;
private Thread m_ListenThread;
public TcpServerWS()
{
this.m_Clients = new List<DeviceTcpClient>();
}
public void ServerStart()
{
m_ListenThread = new Thread(StartServer);
m_ListenThread.Start();
}
private void StartServer()
{
try
{
this.m_TcpListener = new TcpListener(IPAddress.Any, this._nPort);
this.m_TcpListener.Start();
Console.WriteLine("TV server has started.");
while (true)
{
TcpClient client = this.m_TcpListener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClient));
clientThread.Start(client);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
this.m_TcpListener.Stop();
Console.WriteLine("TV server has ended.");
}
}
private void HandleClient(object c)
{
TcpClient client = (TcpClient)c;
NetworkStream clientStream = client.GetStream();
byte[] message = new byte[client.ReceiveBufferSize];
int byteRead;
while (true)
{
byteRead = 0;
try
{
byteRead = clientStream.Read(message, 0, client.ReceiveBufferSize);
}
catch
{
break;
}
if (byteRead == 0)
{
break;
}
string receiveMessage = System.Text.ASCIIEncoding.GetEncoding("euc-kr").GetString(message, 0, byteRead);
var sb = new StringBuilder("new byte[] { ");
foreach (var b in message)
{
sb.Append(b + ", ");
}
sb.Append("}");
if (new System.Text.RegularExpressions.Regex("^GET").IsMatch(receiveMessage))
{
const string eol = "\r\n"; // HTTP/1.1 defines the sequence CR LF as the end-of-line marker
Byte[] response = Encoding.UTF8.GetBytes("HTTP/1.1 101 Switching Protocols" + eol
+ "Connection: Upgrade" + eol
+ "Upgrade: websocket" + eol
+ "Sec-WebSocket-Accept: " + Convert.ToBase64String(
System.Security.Cryptography.SHA1.Create().ComputeHash(
Encoding.UTF8.GetBytes(
new System.Text.RegularExpressions.Regex("Sec-WebSocket-Key: (.*)").Match(receiveMessage).Groups[1].Value.Trim() + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
)
)
) + eol
+ eol);
clientStream.Write(response, 0, response.Length);
}
else
{
string decodeMessage = DecodeMessageFromWebSockClient(message, byteRead);
//string decodeMessage = GetMessage(message);
Console.WriteLine("DecodeMessage : " + decodeMessage);
var messages = decodeMessage.Split('|');
string deviceID = "";
if (messages != null)
{
if (messages.Length == 2)
{
if (messages[0].ToLower() == "id")
{
deviceID = messages[1];
DeviceTcpClient deviceClient = new DeviceTcpClient { Client = client, DeviceID = deviceID };
this.m_Clients.Add(deviceClient);
Console.WriteLine(String.Format("[{0}] is logged in. Connected device count is {1}.", deviceID, this.m_Clients.Count));
//SendMessageToWebSocketClient(client, "HelloClient!!!!!");
}
}
}
}
}
client.Close();
DeviceTcpClient deleteItem = null;
foreach (var item in m_Clients)
{
if (item.Client == client)
{
deleteItem = item;
break;
}
}
if (deleteItem != null)
{
Console.WriteLine(String.Format("[{0}] is logged out. Connected device count is {1}.", deleteItem.DeviceID, this.m_Clients.Count - 1));
m_Clients.Remove(deleteItem);
}
}
public TcpClient FindDevice(string id)
{
TcpClient result = null;
foreach (var item in m_Clients)
{
if (item.DeviceID == id)
{
result = item.Client;
break;
}
}
return result;
}
private string DecodeMessageFromWebSockClient(Byte[] b, int len)
{
try
{
byte rLength = 0;
int rMaskIndex = 2;
int rDataStart = 0;
//b[0] is always text in my case so no need to check;
byte data = b[1];
byte op = (byte)127;
rLength = (byte)(data & op);
if (rLength == (byte)126) rMaskIndex = 4;
if (rLength == (byte)127) rMaskIndex = 10;
byte[] masks = new byte[4];
int j = 0;
int i = 0;
for (i = rMaskIndex; i < (rMaskIndex + 4); i++)
{
masks[j] = b[i];
j++;
}
rDataStart = rMaskIndex + 4;
int messLen = len - rDataStart;
byte[] message = new byte[messLen];
for (i = rDataStart, j = 0; i < len; i++, j++)
{
message[j] = (byte)(b[i] ^ masks[j % 4]);
}
var parseMessage = Encoding.UTF8.GetString(message);
return parseMessage;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return null;
}
public string DecodeMessage(Byte[] bytes)
{
string incomingData = string.Empty;
byte secondByte = bytes[1];
int dataLength = secondByte & 127;
int indexFirstMask = 2;
if (dataLength == 126)
indexFirstMask = 4;
else if (dataLength == 127)
indexFirstMask = 10;
IEnumerable<byte> keys = bytes.Skip(indexFirstMask).Take(4);
int indexFirstDataByte = indexFirstMask + 4;
byte[] decoded = new byte[bytes.Length - indexFirstDataByte];
for (int i = indexFirstDataByte, j = 0; i < bytes.Length; i++, j++)
{
decoded[j] = (byte)(bytes[i] ^ keys.ElementAt(j % 4));
}
return Encoding.UTF8.GetString(decoded, 0, decoded.Length);
}
public void SendMessageToClient(TcpClient c, string msg)
{
try
{
TcpClient client = (TcpClient)c;
NetworkStream clientStream = client.GetStream();
Byte[] buffer = System.Text.ASCIIEncoding.UTF8.GetBytes(msg);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public void SendMessageToWebSocketClient(TcpClient c, string msg)
{
TcpClient client = (TcpClient)c;
NetworkStream clientStream = client.GetStream();
byte[] rawData = System.Text.ASCIIEncoding.UTF8.GetBytes(msg);
int frameCount = 0;
byte[] frame = new byte[10];
frame[0] = (byte)129;
if (rawData.Length <= 125)
{
frame[1] = (byte)rawData.Length;
frameCount = 2;
}
else if (rawData.Length >= 126 && rawData.Length <= 65535)
{
frame[1] = (byte)126;
int len = rawData.Length;
frame[2] = (byte)((len >> 8) & (byte)255);
frame[3] = (byte)(len & (byte)255);
frameCount = 4;
}
else
{
frame[1] = (byte)127;
int len = rawData.Length;
frame[2] = (byte)((len >> 56) & (byte)255);
frame[3] = (byte)((len >> 48) & (byte)255);
frame[4] = (byte)((len >> 40) & (byte)255);
frame[5] = (byte)((len >> 32) & (byte)255);
frame[6] = (byte)((len >> 24) & (byte)255);
frame[7] = (byte)((len >> 16) & (byte)255);
frame[8] = (byte)((len >> 8) & (byte)255);
frame[9] = (byte)(len & (byte)255);
frameCount = 10;
}
int bLength = frameCount + rawData.Length;
byte[] reply = new byte[bLength];
int bLim = 0;
for (int i = 0; i < frameCount; i++)
{
reply[bLim] = frame[i];
bLim++;
}
for (int i = 0; i < rawData.Length; i++)
{
reply[bLim] = rawData[i];
bLim++;
}
clientStream.Write(reply, 0, reply.Length);
clientStream.Flush();
}
public void ServerClose()
{
if (m_Clients != null)
{
for (int i = 0; i < m_Clients.Count; i++)
{
TcpClient client = m_Clients[i].Client;
client.Close();
}
m_Clients.Clear();
}
if (m_TcpListener != null)
{
m_TcpListener.Stop();
}
if (m_ListenThread != null)
{
m_ListenThread.Abort();
}
}
}
'C# > Network' 카테고리의 다른 글
C# TCP Client (0) | 2020.08.14 |
---|---|
C# Multi Thread TcpServer (0) | 2020.08.14 |
C# UDP (0) | 2020.08.13 |
C# WOL 컴퓨터 원격 온오프 (0) | 2020.08.07 |
C# Ping 테스트, 해당 IP 장치 이름 가져오기 (0) | 2020.08.07 |