TheRyuzaki.Network v0.001 PreAlpha - Критика и оптимизация - C#
Формулировка задачи:
Client.cs
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace TheRyuzaki.Network
{
public class Client
{
public int build = 1;
public Dictionary<string, object> Cl = new Dictionary<string, object>();
#region Обьявление ссылок на функции
/// <summary>
/// Ссылка на функцию вызываемую при завершении действий по подключению к серверу.
/// </summary>
public Action ConnectToServer_Completed = null;
/// <summary>
/// Ссылка на функцию вызываемую при получении текста от сервера.
/// </summary>
public Action<string> ReadLineToServer = null;
/// <summary>
/// Ссылка на функцию вызываемую при завершении отключения от сервера.
/// </summary>
public Action DisconnectServer_Completed = null;
#endregion
/// <summary>
/// Класс для клиента по работе с сервером работающиго на TheRyuzaki.Network
/// </summary>
/// <param name="ip">IP Адрес до сервера работающиго на TheRyuzaki.Network</param>
/// <param name="port">Порт до сервера работающиго на TheRyuzaki.Network</param>
public Client(string ip, int port)
{
Cl["connect_status"] = false;
Cl["client_ip"] = ip;
Cl["client_port"] = port;
}
public void ConnectToServer()
{
Cl["client_thread"] = new Thread(delegate ()
{
if (!(bool)Cl["connect_status"])
try
{
Cl["client_tcp"] = new TcpClient((string)Cl["client_ip"], (int)Cl["client_port"]);
Cl["client_ns"] = (Cl["client_tcp"] as TcpClient).GetStream();
Cl["client_sr"] = new StreamReader((Cl["client_ns"] as NetworkStream));
Cl["client_sw"] = new StreamWriter((Cl["client_ns"] as NetworkStream));
Cl["connect_status"] = true;
}
catch
{
Cl["connect_status"] = false;
}
if (ConnectToServer_Completed != null) ConnectToServer_Completed();
Reading();
});
(Cl["client_thread"] as Thread).Start();
}
/// <summary>
/// Функция потокового прослушивания запросов от сервера
/// </summary>
private void Reading()
{
if ((bool)Cl["connect_status"])
try
{
while(true)
{
var request = (Cl["client_sr"] as StreamReader).ReadLine();
if (request.Length == 0) break;
var ex = request.Split(';');
switch (ex[0])
{
case "version":
WriteForServer("version;" + build);
break;
default:
if (ReadLineToServer != null) ReadLineToServer(request);
break;
}
}
Disconnect();
}
catch {
if ((Thread)Cl["client_thread"] != null) Disconnect();
}
}
/// <summary>
/// Функция отправки запроса на сервер
/// </summary>
/// <param name="request">Запрос</param>
/// <param name="WriteAllClients">Просто отправить всем клиентам</param>
public void WriteForServer(string request, bool WriteAllClients = false)
{
if (!(bool)Cl["connect_status"])
return;
if (WriteAllClients)
request = "WriteAllClients;" + request;
(Cl["client_sw"] as StreamWriter).WriteLine(request);
(Cl["client_sw"] as StreamWriter).Flush();
}
/// <summary>
/// Функция разрыва соеденения с сервером
/// </summary>
public void Disconnect()
{
Cl["client_thread"] = null;
try { (Cl["client_sr"] as StreamReader).Close(); } catch { }
try { (Cl["client_sw"] as StreamWriter).Close(); } catch { }
try { (Cl["client_ns"] as NetworkStream).Close(); } catch { }
try { (Cl["client_tcp"] as TcpClient).Close(); } catch { }
Cl["connect_status"] = false;
if (DisconnectServer_Completed != null) DisconnectServer_Completed();
}
}
}Server.cs
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace TheRyuzaki.Network
{
public class Server
{
private int build = 1;
public Dictionary<string, object> Config = new Dictionary<string, object>();
public Dictionary<string, object> Srv = new Dictionary<string, object>();
#region Ссылки на функции CallBack
/// <summary>
/// Ссылка на функцию которая вызывается при успешном запуске сервера
/// </summary>
public Action ServerStarted = null;
/// <summary>
/// Ссылка на функцию которая вызывается при остановке сервера
/// </summary>
public Action ServerStoped = null;
/// <summary>
/// Ссылка на функцию которая вызывается при подключении нового клиента
/// </summary>
public Action<int> ClientConnected = null;
/// <summary>
/// Ссылка на функцию которая вызывается при отключении клиента от сервера
/// </summary>
public Action<int, Dictionary<string, object>> ClientDisconnected = null;
/// <summary>
/// Ссылка на функцию которая вызывается при получении сообщения от клиента
/// </summary>
public Action<int, string> ClientSendedMessage = null;
#endregion
/// <summary>
/// Класс по работе Сервер-Клиент по сердствам TheRyuzaki.Network
/// </summary>
/// <param name="IP">IP адрес прослушки в формате IPAddress</param>
/// <param name="Port">Порт прослушиваемый</param>
public Server(IPAddress IP, int Port)
{
Config["server_ip"] = IP;
Config["server_port"] = Port;
Config["last_session"] = 0;
Srv["server_thread"] = null;
Srv["Server"] = new Dictionary<string, object>();
Srv["Users"] = new Dictionary<int, object>();
(Srv["Server"] as Dictionary<string, object>)["Listener"] = new TcpListener(IP, Port);
}
/// <summary>
/// Функция запуска сервера
/// </summary>
public void StartServer()
{
if ((Srv["server_thread"] as Thread) != null) return;
((Srv["Server"] as Dictionary<string, object>)["Listener"] as TcpListener).Start();
Srv["server_thread"] = new Thread(delegate ()
{
if (ServerStarted != null) ServerStarted();
while (true)
{
Socket Soc = null;
try { Soc = ((Srv["Server"] as Dictionary<string, object>)["Listener"] as TcpListener).AcceptSocket(); } catch { break; }
if (Soc.Connected)
{
Config["last_session"] = (int)Config["last_session"] + 1;
var id_session = (int)Config["last_session"];
(Srv["Users"] as Dictionary<int, object>)[id_session] = new Dictionary<string, object>();
((Srv["Users"] as Dictionary<int, object>)[id_session] as Dictionary<string, object>)["Thread"] = new Thread(delegate ()
{
try
{
((Srv["Users"] as Dictionary<int, object>)[id_session] as Dictionary<string, object>)["Soc"] = Soc;
((Srv["Users"] as Dictionary<int, object>)[id_session] as Dictionary<string, object>)["NS"] = new NetworkStream(Soc);
((Srv["Users"] as Dictionary<int, object>)[id_session] as Dictionary<string, object>)["SR"] = new StreamReader((((Srv["Users"] as Dictionary<int, object>)[id_session] as Dictionary<string, object>)["NS"] as NetworkStream));
((Srv["Users"] as Dictionary<int, object>)[id_session] as Dictionary<string, object>)["SW"] = new StreamWriter((((Srv["Users"] as Dictionary<int, object>)[id_session] as Dictionary<string, object>)["NS"] as NetworkStream));
if (ClientConnected != null) ClientConnected(id_session);
while (true)
{
var request = (((Srv["Users"] as Dictionary<int, object>)[id_session] as Dictionary<string, object>)["SR"] as StreamReader).ReadLine();
if (request.Length == 0) break;
request = "WriteAllClients;" + request;
var ex = request.Split(';');
switch (ex[0])
{
case "version":
if (build.ToString() != ex[1]) CloseSession(id_session);
break;
case "WriteAllClients":
request = request.Replace("WriteAllClients;", "");
(new Thread(delegate ()
{
foreach (var r in GetUsers())
if ((Srv["Users"] as Dictionary<int, object>).ContainsKey(r.Key))
SendMessage(request, r.Key);
})).Start();
break;
default:
if (ClientSendedMessage != null) ClientSendedMessage(id_session, request);
break;
}
}
CloseSession(id_session);
}
catch
{
CloseSession(id_session);
}
});
(((Srv["Users"] as Dictionary<int, object>)[id_session] as Dictionary<string, object>)["Thread"] as Thread).Start();
}
}
});
(Srv["server_thread"] as Thread).Start();
}
/// <summary>
/// Функция остановки сервера
/// </summary>
public void StopServer()
{
if ((Srv["server_thread"] as Thread) == null) return;
((Srv["Server"] as Dictionary<string, object>)["Listener"] as TcpListener).Stop();
foreach(var r in GetUsers())
if ((Srv["Users"] as Dictionary<int, object>).ContainsKey(r.Key))
CloseSession(r.Key);
(Srv["server_thread"] as Thread).Abort();
Srv["server_thread"] = null;
if (ServerStoped != null) ServerStoped();
}
/// <summary>
/// Функция завершения сеанса сессии.
/// Возвращает ответ:
/// 0 = Закрыт успешно.
/// 1 = Такой сессии не существует.
/// 2 = Возникла ошибка при закрытии сесии.
/// </summary>
public int CloseSession(int id, bool NotRemove = false)
{
int i = 0;
if ((Srv["Users"] as Dictionary<int, object>).ContainsKey(id))
try
{
try { (((Srv["Users"] as Dictionary<int, object>)[id] as Dictionary<string, object>)["Soc"] as Socket).Close(); } catch { }
if (ClientDisconnected != null) ClientDisconnected(id, ((Srv["Users"] as Dictionary<int, object>)[id] as Dictionary<string, object>));
Thread tmp = (((Srv["Users"] as Dictionary<int, object>)[id] as Dictionary<string, object>)["Thread"] as Thread);
if (!NotRemove) (Srv["Users"] as Dictionary<int, object>).Remove(id);
tmp.Abort();
}
catch
{
i = 2; // Записываем про чтоизошла ошибка
}
else
i = 1;
return i;
}
/// <summary>
/// Функция отправки сообщения на клиент
/// </summary>
/// <param name="message">Само сообщение</param>
/// <param name="id_session">ID сессии</param>
public void SendMessage(string message, int id_session)
{
(((Srv["Users"] as Dictionary<int, object>)[id_session] as Dictionary<string, object>)["SW"] as StreamWriter).WriteLine(message);
(((Srv["Users"] as Dictionary<int, object>)[id_session] as Dictionary<string, object>)["SW"] as StreamWriter).Flush();
}
/// <summary>
/// Функция получения списка ID сессий активных пользователей. Желательно проверять при работе на достоверность if ((Srv["Users"] as Dictionary<int, object>).ContainsKey(r.Key))
/// </summary>
/// <returns>Dictionary<int, bool> - массив содержащий ID в ключе</returns>
public Dictionary<int, bool> GetUsers()
{
var k =(Srv["Users"] as Dictionary<int, object>).Keys;
Dictionary<int, bool> keys = new Dictionary<int, bool>();
foreach(var r in k)
keys.Add(r, true);
return keys;
}
}
}Решение задачи: «TheRyuzaki.Network v0.001 PreAlpha - Критика и оптимизация»
textual
Листинг программы
public void SendMessage(string message, int id_session)
{
(((Srv["Users"] as Dictionary<int, object>)[id_session] as Dictionary<string, object>)["SW"] as StreamWriter).WriteLine(message);
(((Srv["Users"] as Dictionary<int, object>)[id_session] as Dictionary<string, object>)["SW"] as StreamWriter).Flush();
}