Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.85/47: Рейтинг темы: голосов - 47, средняя оценка - 4.85
0 / 0 / 0
Регистрация: 22.05.2013
Сообщений: 8

Как работает метод Socket.BeginAccept

04.10.2014, 12:17. Показов 8885. Ответов 3
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Пожалуйста объясните "на пальцах" как работают некоторые функции в этом коде. Вопросы указаны в комментариях.
Описанный ниже код принадлежит серверу, к которому обращаются клиенты с просьбой выслать им текущее время.
Основная цель для меня научиться делать многопоточные серверы с помощью асинхронного обратного вызова.
Не обидьте школьника, помогите советом.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
namespace Multi_Server
{
    class Program
    {
        private static Socket _serverSocket;  
        private static readonly List<Socket> _clientSockets = new List<Socket>(); 
//1) для чего нужен этот список сокетов??
      
        private const int _BUFFER_SIZE = 2048; 
        private const int _PORT = 100; 
        private static readonly byte[] _buffer = new byte[_BUFFER_SIZE]; 
 
        static void Main()
        {
            Console.Title = "Server";
            SetupServer();
            Console.ReadLine(); 
            CloseAllSockets();
        }
 
        private static void SetupServer() 
        {
            Console.WriteLine("Setting up server...");
            _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _serverSocket.Bind(new IPEndPoint(IPAddress.Any, _PORT));
            _serverSocket.Listen(5);
            _serverSocket.BeginAccept(AcceptCallback, null); 
//2) AcceptCallback, это насколько я понял функция которая будет вызвана когда кто либо постучится в наш порт. А что здесь есть NULL??
           
 Console.WriteLine("Server setup complete");
        }
 
 
        /// Close all connected client (we do not need to shutdown the server socket as its connections
        /// are already closed with the clients)
   
        private static void CloseAllSockets()
        {
            foreach (Socket socket in _clientSockets)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
 
            _serverSocket.Close();
        }
 
        private static void AcceptCallback(IAsyncResult AR)
 //3) Это та самая функция которая вызывается через Socket.BeginAccept (?). Какую роль здесь играет IAsyncResult? 
        {
            Socket socket; 
//4) Это открывают отдельный сокет для свежеподключившегося клиента?
            try
            {
                socket = _serverSocket.EndAccept(AR);
//5) Что происходит в этой строке? (Та что сверху)
         
   }
            catch (ObjectDisposedException) // I cannot seem to avoid this (on exit when properly closing sockets)
            {
                return;
            }
 
           _clientSockets.Add(socket);
           socket.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, socket);
//6 ReceiveCallback, это функция которая будет вызвана после завершения BeginReceive, а какие данные будет содержать socket?
 
           Console.WriteLine("Client connected, waiting for request...");
 
           _serverSocket.BeginAccept(AcceptCallback, null);
//7 зачем здесь снова вызывается BeginAccept если обмен данными еще не закончен?
        }
 
        private static void ReceiveCallback(IAsyncResult AR)
        {
 
            Socket current = (Socket)AR.AsyncState;
//8) Что делает эта строка? (та что сверху)
     
       int received;
 
            try
            {
                received = current.EndReceive(AR);
            }
            catch (SocketException)
            {
                Console.WriteLine("Client forcefully disconnected");
                current.Close(); // Dont shutdown because the socket may be disposed and its disconnected anyway
                _clientSockets.Remove(current);
                return;
            }
 
            byte[] recBuf = new byte[received];
            Array.Copy(_buffer, recBuf, received);
            string text = Encoding.ASCII.GetString(recBuf);
            Console.WriteLine("Received Text: " + text);
 
            if (text.ToLower() == "get time") // Client requested time
            {
                Console.WriteLine("Text is a get time request");
                byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
                current.Send(data);
                Console.WriteLine("Time sent to client");
            }
            else if (text.ToLower() == "exit") // Client wants to exit gracefully
            {
                // Always Shutdown before closing
                current.Shutdown(SocketShutdown.Both);
                current.Close();
                _clientSockets.Remove(current);
                Console.WriteLine("Client disconnected");
                return;
            }
            else
            {
                Console.WriteLine("Text is an invalid request");
                byte[] data = Encoding.ASCII.GetBytes("Invalid request");
                current.Send(data);
                Console.WriteLine("Warning Sent");
            }
 
            current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, ReceiveCallback, current);
        }
    }
}
Пока это все вопросы. Пожалуйста помогите разобраться. Надеюсь ваши ответы помогут мне постичь истину)
Если можно, объясните структуру и алгоритм работы метода socket.BeginAccept() своими словами или на простом примере, а не цитатами из msdn с корявым переводом.

Код взят отсюда
Кликните здесь для просмотра всего текста
https://www.youtube.com/watch?v=xgLRe7QV6QI
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
04.10.2014, 12:17
Ответы с готовыми решениями:

Socket AcceptAsync или BeginAccept?
что лучше использовать? и в целом в чем разница? я использовал пока только AcceptAsync

Как остановить BeginAccept (Сокет)?
Пишу серверную часть, использую асинхронные методы (Begin), как теперь остановить поток в котором выполняется метод BeginAccept(Accept)....

Вызов BeginAccept() при вызове Close()
Всем привет. Подскажите, ребята: почему при вызове метода Close() сокет вызывает метод BeginAccept()? Я считаю, что это нужно для вызова...

3
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
04.10.2014, 16:04
Лучший ответ Сообщение было отмечено DrTorqux как решение

Решение

Цитата Сообщение от DrTorqux Посмотреть сообщение
1) для чего нужен этот список сокетов??
Для хранения подключенных клиентов. Обратите внимание на то, как он используется в методах AcceptCallback и ReceiveCallback.
Держать этот список не обязательно, но полезно, если нужно знать, сколько и каких клиентов подключено к серверу в данный момент. Например, чтобы всем разом отправить сообщение.

Цитата Сообщение от DrTorqux Посмотреть сообщение
2) AcceptCallback, это насколько я понял функция которая будет вызвана когда кто либо постучится в наш порт. А что здесь есть NULL??
Null здесь — это любой объект, который вы хотите передать в метод AcceptCallback, когда произойдет подсоединение.
В методе AcceptCallback вы на вход получаете ссылку на IAsyncResult. В этом инетрфейсе определено свойство AsyncState — это и будет ссылка на объект, который вы передали при вызове BeginAccept.

Цитата Сообщение от DrTorqux Посмотреть сообщение
3) Это та самая функция которая вызывается через Socket.BeginAccept (?). Какую роль здесь играет IAsyncResult?
Она самая.
IAsyncResult здесь играет роль контекста асинхронной операции. По переданной ссылке вы можете получить дескриптор ожидания завершения асинхронной операции, информацию о том, выполняется ли метод AcceptCallback синхронно (в том же потоке, откуда вызывался BeginConnect) или асинхронно (в другом потоке). Ну и ссылку на передаваемый объект, как в предыдущем вопросе.

Цитата Сообщение от DrTorqux Посмотреть сообщение
4) Это открывают отдельный сокет для свежеподключившегося клиента?
Да.

Цитата Сообщение от DrTorqux Посмотреть сообщение
5) Что происходит в этой строке? (Та что сверху)
Открывается отдельный сокет для свежеподключившегося клиента
Точнее, возвращается ссылка на подключившегося клиента.

Цитата Сообщение от DrTorqux Посмотреть сообщение
6 ReceiveCallback, это функция которая будет вызвана после завершения BeginReceive, а какие данные будет содержать socket?
О каком сокете идет речь? Если о том, который передается последним аргументом в метод, то это передача "любого объекта" в асинхронную операцию, как было сделано с Null в BeginAccept.
Обратите внимание на первую строчку метода ReceiveCallback:
C#
1
Socket current = (Socket)AR.AsyncState;
Вот здесь и происходит извлечение переданного последним аргументом сокета в метод BeginReceive.
То есть socket из метода AcceptCallback и current из метода ReceiveCallback — ссылки на один и тот же объект.

Цитата Сообщение от DrTorqux Посмотреть сообщение
7 зачем здесь снова вызывается BeginAccept если обмен данными еще не закончен?
Ну так это же код обработчика AcceptCallback, то есть подключения клиента. Клиент подключился, мы начали получать от него данные через BeginReceive, а дальше-то что? Если просто завершить метод, то новый клиент уже не сможет подключиться, так как сервер уж не принимает подключений. Значит надо после подключения клиента начать слушать подключение нового клиента, что этот метод и делает.

Цитата Сообщение от DrTorqux Посмотреть сообщение
8) Что делает эта строка? (та что сверху)
Ответ в ответах на вопросы 2 и 6.
2
0 / 0 / 0
Регистрация: 22.05.2013
Сообщений: 8
04.10.2014, 19:35  [ТС]
Спасибо большое за ваши ответы! Вы мне очень помогли.
Так же мне помогло вот это видео. Рекомендую тем кто столкнулся с такими же вопросами. Там хоть и на английском, но всё разжевано донельзя.
Кликните здесь для просмотра всего текста
https://www.youtube.com/watch?v=cG5q4XdYIUI

Еще раз спасибо kolorotur. Сейчас практикуюсь, не подскажите как отслеживать активно ли подключение с клиентом? Просто если во время работы теряется соединение с клиентом, то и сервер падает. Позже скину код созданного сервера. Может посоветуете что нибудь путное.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
04.10.2014, 20:29
Цитата Сообщение от DrTorqux Посмотреть сообщение
не подскажите как отслеживать активно ли подключение с клиентом?
Если данные приходят-уходят нормально, то соединение активно.
Если клиент отключился удаленно в штатном режиме, то в методе ReceiveCallback вызов current.EndReceive(AR) вернет 0 (значение received будет равно нулю).
Если соединение оборвалось, то любой метод, начинающийся на End (EndReceive, EndAccept, EndSend) выбросит исключение.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
04.10.2014, 20:29
Помогаю со студенческими работами здесь

Чем отличается метод передачи данных TcpClient() от Socket
Здравствуйте! Подскажите, пожалуйста! Очень интересно :)

Не работает метод ReceiveAsync класса Socket
Добрый день. Устанавливаю соединение на прослушивание вот таким образом: /// &lt;summary&gt; /// Слушаем...

Как проверить работает ли php socket
Добрый день, можно ли проверить работает ли php fpm через сокет? Имею ввиду как то подключившись к сокету например выполнить phpinfo ().

Метод получает другой метод, как аргумент. Как это работает?
Добрый день, ребят. Есть такая программа: package javaapplication13; class Block{ int a, b, c; int volume; ...

Невозможно создать Socket: Socket sock = new Socket(someHostString,somePortInt);
Народ! Помогите пожалуйста. Вся красота губится на exception что выскакивает в момент создания сокета: Socket sock = new...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru