Мне нужно реализовать клиентское приложение TCP.Клиент и сервер отправляют сообщения друг другу.Я хочу сделать эту программу достаточно масштабируемой, чтобы обрабатывать подключения к нескольким серверам одновременно.Кажется, что асинхронные сокеты - путь для этого.Я новичок в C #, поэтому я уверен, что не знаю, что я здесь делаю.Я написал несколько классов и простую консольную программу для начала.В конце концов, я хочу создать приложение Windows Forms, но сначала я хочу начать с малого и просто.Класс Client работает в своем собственном потоке.Это все потокобезопасно и правильно сделано?Это много кода, и я попытался вырезать жир
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace FastEyeClient
{
public class Server
{
private ServerManager m_Manager;
private string m_Hostname;
private bool m_IsLive;
private class StateObject
{
public Socket AsyncSocket = null;
public const int BufferSize = 1024;
public byte[] Buffer = new byte[BufferSize];
public StringBuilder Builder = new StringBuilder();
}
public Server(ServerManager manager, Socket socket)
{
try
{
m_Manager = manager;
IPEndPoint endPoint = (IPEndPoint)socket.RemoteEndPoint;
IPAddress ipAddress = endPoint.Address;
IPHostEntry hostEntry = Dns.GetHostEntry(ipAddress);
Hostname = hostEntry.HostName;
IsLive = false;
StateObject state = new StateObject();
state.AsyncSocket = socket;
socket.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
}
catch (Exception)
{
}
}
public string Hostname
{
get
{
return m_Hostname;
}
set
{
m_Hostname = value;
}
}
public bool IsLive
{
get
{
return m_IsLive;
}
set
{
m_IsLive = value;
}
}
private void ReceiveCallback(IAsyncResult result)
{
try
{
StateObject state = (StateObject)result.AsyncState;
Socket socket = state.AsyncSocket;
int read = socket.EndReceive(result);
if (read > 0)
{
state.Builder.Append(Encoding.ASCII.GetString(state.Buffer, 0, read));
if (state.Builder.Length > 1)
{
string messages = state.Builder.ToString();
ParseMessages(messages);
}
}
StateObject newState = new StateObject();
newState.AsyncSocket = socket;
socket.BeginReceive(newState.Buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), newState);
}
catch (Exception)
{
}
}
private void ParseMessages(string messages)
{
string[] messagesArray = messages.Split('\n');
foreach (string message in messagesArray)
{
string[] tokens = message.Split(',');
if (tokens[0].Contains("@"))
{
ParseServerMessage(tokens);
}
}
}
private void ParseServerMessage(string[] tokens)
{
tokens[0].Remove(0, 1);
if (tokens[0] == "4")
{
bool status;
if (tokens[1] == "0")
{
status = false;
m_Manager.SetLiveStatus(m_Hostname, status);
}
else if (tokens[1] == "1")
{
status = true;
m_Manager.SetLiveStatus(m_Hostname, status);
}
}
}
}
}
ServerManager.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace FastEyeClient
{
public class ServerManager
{
private Client m_Client;
private Dictionary<string, Server> m_Servers;
private object m_Locker;
public ServerManager(Client client)
{
m_Client = client;
m_Servers = new Dictionary<string, Server>();
m_Locker = new object();
}
public void AddServer(string hostname, int port)
{
try
{
IPAddress[] IPs = Dns.GetHostAddresses(hostname);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.BeginConnect(IPs, port, new AsyncCallback(ConnectCallback), socket);
}
catch (Exception)
{
bool isConnected = false;
string message = "Could not connect to server.";
m_Client.OnConnect(isConnected, message);
}
}
private void ConnectCallback(IAsyncResult ar)
{
bool isConnected;
string message;
try
{
Socket socket = (Socket)ar.AsyncState;
socket.EndConnect(ar);
IPEndPoint endPoint = (IPEndPoint)socket.RemoteEndPoint;
IPAddress ipAddress = endPoint.Address;
IPHostEntry hostEntry = Dns.GetHostEntry(ipAddress);
string hostname = hostEntry.HostName;
lock (m_Servers)
{
if (m_Servers.ContainsKey(hostname))
{
isConnected = false;
message = "Client is already connected to server";
}
else
{
m_Servers.Add(hostname, new Server(this, socket));
isConnected = true;
message = "Successfully connected.";
}
}
m_Client.OnConnect(isConnected, message);
}
catch (Exception)
{
isConnected = false;
message = "Could not connect to server.";
m_Client.OnConnect(isConnected, message);
}
}
public void SetLiveStatus(string hostname, bool newStatus)
{
string message;
lock (m_Locker)
{
if (m_Servers.ContainsKey(hostname))
{
if (m_Servers[hostname].IsLive == newStatus)
{
message = "Server is already set to this status.";
}
else
{
m_Servers[hostname].IsLive = newStatus;
message = "Successfully set new status.";
}
}
else
{
message = "Server not found.";
}
}
m_Client.OnSetLiveStatus(hostname, message);
}
}
}