Асинхронный сервер, объяснить работу Callback методов - C#
Формулировка задачи:
Прив. ЕОК, есть один код. Взят он с МСДН и является примером асинхронного сервера. Но на том же МСДН не очень ОК пояснили каждое действие.
Вопросы я написал в виде комментариев, так же присутствуют несколько комментариев самого автора. Я-то читал, что функции Callback запускают выполнение чего-то в отдельном потоке, а потом возвращают результат в основной поток. Но я не могу понять, где, в данном коде, начало какой-то операции, и когда мы получаем результат, и что делается в основном потоке, во время обработки асинхронной операции в другом потоке?
Объясните, пожалуйста, кто как может, можно даже с картинками :3 Спасибо!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.NetworkInformation;
using System.Net;
using System.Threading;
using System.Net.Sockets;
namespace ConsoleApplication3
{
class Program
{
class ThreadedServer
{
private Socket _serverSocket;
private int _port;
private bool count = false;
public ThreadedServer(int port) { _port = port; }
public void Start()
{
SetupServerSocket();
for (int i = 0; i < 10; i++) // зачем нам 10 раз запускать BeginAccept?
_serverSocket.BeginAccept(new
AsyncCallback(AcceptCallback), _serverSocket); // что в этой строке делает BeginAccept?
}
private class ConnectionInfo
{
public Socket Socket;
public byte[] Buffer;
}
private List<ConnectionInfo> _connections = new List<ConnectionInfo>();
private void SetupServerSocket()
{
// Получаем информацию о локальном компьютере
IPEndPoint myEndpoint = new IPEndPoint(IPAddress.Any, _port);
// Создаем сокет, привязываем его к адресу
// и начинаем прослушивание
_serverSocket = new Socket(
myEndpoint.Address.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(myEndpoint);
_serverSocket.Listen((int)
SocketOptionName.MaxConnections);
}
private void AcceptCallback(IAsyncResult result) // что это за дивный IAsyncResult result, и когда вызывается этот метод (AcceptCallback)?
{
ConnectionInfo connection = new ConnectionInfo();
try
{
// Завершение операции Accept
//если это завершение, то когда эта операция началась?
Console.WriteLine("Подключился чел");
count = true;
Socket s = (Socket)result.AsyncState;
connection.Socket = s.EndAccept(result);
connection.Buffer = new byte[256];
byte[] b = new byte[1];
lock (_connections) _connections.Add(connection);
b = BitConverter.GetBytes(count);
foreach (ConnectionInfo conn in
_connections)
{
if (connection != conn)
{
conn.Socket.Send(b,
b.Length, SocketFlags.None);
}
}
count = false;
// Начало операции Receive и новой операции Accept
connection.Socket.BeginReceive(connection.Buffer,
0, connection.Buffer.Length, SocketFlags.None,
new AsyncCallback(ReceiveCallback),
connection); //что делает BeginReceive ?
_serverSocket.BeginAccept(new AsyncCallback(
AcceptCallback), result.AsyncState); //для чего эти строки? мы же писали аналогичное в функции Start
}
catch (SocketException exc)
{
CloseConnection(connection);
Console.WriteLine("Socket exception: " +
exc.SocketErrorCode);
}
catch (Exception exc)
{
CloseConnection(connection);
Console.WriteLine("Exception: " + exc);
}
}
private void ReceiveCallback(IAsyncResult result) // что за IAsyncResult result ?
{
ConnectionInfo connection =
(ConnectionInfo)result.AsyncState;
try
{
int bytesRead =
connection.Socket.EndReceive(result);
if (0 != bytesRead)
{
lock (_connections)
{
float x, y, z, x_rot, y_rot, z_rot, w_rot;
x = BitConverter.ToSingle(connection.Buffer, 0);
y = BitConverter.ToSingle(connection.Buffer, 4);
z = BitConverter.ToSingle(connection.Buffer, 8);
x_rot = BitConverter.ToSingle(connection.Buffer, 12);
y_rot = BitConverter.ToSingle(connection.Buffer, 16);
z_rot = BitConverter.ToSingle(connection.Buffer, 20);
w_rot = BitConverter.ToSingle(connection.Buffer, 24);
Console.WriteLine("Position: {0},{1},{2}", x, y, z);
Console.WriteLine("Rotation: {0},{1},{2},{3}", x_rot, y_rot, z_rot, w_rot);
foreach (ConnectionInfo conn in
_connections)
{
if (connection != conn)
{
conn.Socket.Send(connection.Buffer,
bytesRead, SocketFlags.None);
}
}
}
connection.Socket.BeginReceive(
connection.Buffer, 0,
connection.Buffer.Length, SocketFlags.None,
new AsyncCallback(ReceiveCallback),
connection); // что делают эти строки?
}
else CloseConnection(connection);
}
catch (SocketException exc)
{
CloseConnection(connection);
Console.WriteLine("Socket exception: " +
exc.SocketErrorCode);
}
catch (Exception exc)
{
CloseConnection(connection);
Console.WriteLine("Exception: " + exc);
}
}
private void CloseConnection(ConnectionInfo ci)
{
ci.Socket.Close();
lock (_connections) _connections.Remove(ci);
}
}
static void Main(string[] args)
{
ThreadedServer ts = new ThreadedServer(9390);
ts.Start();
Console.ReadLine();
}
}
}Решение задачи: «Асинхронный сервер, объяснить работу Callback методов»
textual
Листинг программы
_serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), _serverSocket);