Из синхронного сокета в асинхронный
От: nbit http://cyber-dream.ru
Дата: 28.10.11 05:35
Оценка:
В MSDN есть замечательный пример получения кода html страницы, но к сожалению в этом примере производится блокирование до тех пор, пока не будет принята вся страница. Если не сложно помогите пожалуйста переделать его под асинхронные сокеты, буду премного благодарен за помощь.


using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;

public class GetSocket
{
    private static Socket ConnectSocket(string server, int port)
    {
        Socket s = null;
        IPHostEntry hostEntry = null;

        // Get host related information.
        hostEntry = Dns.GetHostEntry(server);

        // Loop through the AddressList to obtain the supported AddressFamily. This is to avoid
        // an exception that occurs when the host IP Address is not compatible with the address family
        // (typical in the IPv6 case).
        foreach(IPAddress address in hostEntry.AddressList)
        {
            IPEndPoint ipe = new IPEndPoint(address, port);
            Socket tempSocket = 
                new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            tempSocket.Connect(ipe);

            if(tempSocket.Connected)
            {
                s = tempSocket;
                break;
            }
            else
            {
                continue;
            }
        }
        return s;
    }

    // This method requests the home page content for the specified server.
    private static string SocketSendReceive(string server, int port) 
    {
        string request = "GET / HTTP/1.1\r\nHost: " + server + 
            "\r\nConnection: Close\r\n\r\n";
        Byte[] bytesSent = Encoding.ASCII.GetBytes(request);
        Byte[] bytesReceived = new Byte[256];

        // Create a socket connection with the specified server and port.
        Socket s = ConnectSocket(server, port);

        if (s == null)
            return ("Connection failed");

        // Send request to the server.
        s.Send(bytesSent, bytesSent.Length, 0);  

        // Receive the server home page content.
        int bytes = 0;
        string page = "Default HTML page on " + server + ":\r\n";

        // The following will block until te page is transmitted.
        do {
            bytes = s.Receive(bytesReceived, bytesReceived.Length, 0);
            page = page + Encoding.ASCII.GetString(bytesReceived, 0, bytes);
        }
        while (bytes > 0);

        return page;
    }

    public static void Main(string[] args) 
    {
        string host;
        int port = 80;

        if (args.Length == 0)
            // If no server name is passed as argument to this program, 
            // use the current host name as the default.
            host = Dns.GetHostName();
        else
            host = args[0];

        string result = SocketSendReceive(host, port); 
        Console.WriteLine(result);
    }
}
Re: Из синхронного сокета в асинхронный
От: Murom Россия  
Дата: 28.10.11 06:09
Оценка: -1
Здравствуйте, nbit, Вы писали:

N>В MSDN есть замечательный пример получения кода html страницы, но к сожалению в этом примере производится блокирование до тех пор, пока не будет принята вся страница. Если не сложно помогите пожалуйста переделать его под асинхронные сокеты, буду премного благодарен за помощь.


Всю работу с синхронным сокетом в отдельный поток, и асинхронное взаимодействие с потоком сокета.
- Eugeny
Re[2]: Из синхронного сокета в асинхронный
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 28.10.11 06:28
Оценка:
Здравствуйте, Murom, Вы писали:

N>>В MSDN есть замечательный пример получения кода html страницы, но к сожалению в этом примере производится блокирование до тех пор, пока не будет принята вся страница. Если не сложно помогите пожалуйста переделать его под асинхронные сокеты, буду премного благодарен за помощь.


M>Всю работу с синхронным сокетом в отдельный поток, и асинхронное взаимодействие с потоком сокета.


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

Простой пример (только с сервером, а не с клиентом): если мы для каждого входного соединения будем создавать новый поток, то на каждое новое подключение будет тратиться как минимум 1Мб памяти, при этом обработка данных также будет производиться в новом потоке. Но одновременно в сотне потоков обрабатывать данные очень не эффективно при наличии 4-х физических процессоров. Используя же асинхронный API класса TcpListener количеством активных потоков будет управлять порт ввода-вывода, который обеспечит максимальную эффективность обработки в зависимости от количества и загрузки текущих аппаратных ресурсов.

Примеры асинхронной работы: TcpClient.BeginConnect и Socket.BeginReceive
Re[3]: Из синхронного сокета в асинхронный
От: nbit http://cyber-dream.ru
Дата: 28.10.11 08:30
Оценка: :)
Здравствуйте, SergeyT., Вы писали:

ST>Синхронная работа с сокетом в новом потоке — это совсем не тоже самое, что и использование асинхронного API этого сокета. Разница заключается в эффективности и потреблении ресурсов. При использовании нативных асинхронных операций будут использованы соответствующие механизмы ОС, типа портов завершения или других механизмов асинхронного взаимодействия уровня ОС, что *значительно* более эффективно, по сравнению с ручным созданием потока и работы из него.


ST>Простой пример (только с сервером, а не с клиентом): если мы для каждого входного соединения будем создавать новый поток, то на каждое новое подключение будет тратиться как минимум 1Мб памяти, при этом обработка данных также будет производиться в новом потоке. Но одновременно в сотне потоков обрабатывать данные очень не эффективно при наличии 4-х физических процессоров. Используя же асинхронный API класса TcpListener количеством активных потоков будет управлять порт ввода-вывода, который обеспечит максимальную эффективность обработки в зависимости от количества и загрузки текущих аппаратных ресурсов.


ST>Примеры асинхронной работы: TcpClient.BeginConnect и Socket.BeginReceive


Для меня очень важна производительность, поэтому я и выбрал асинхронные сокеты, хоть для меня их и очень трудно понять. Подскажите а какие есть варианты реализаций асинхронных сокетов? Потому что например классы, которые Вы указали для примера, вообще не используются в примере от MSDN Socket Performance Technology Sample см. также описание на русском
Re[4]: Из синхронного сокета в асинхронный
От: nbit http://cyber-dream.ru
Дата: 28.10.11 08:35
Оценка:
Здравствуйте, nbit, Вы писали:

N> Потому что например классы,


Простите поправка, "методы TcpClient.BeginConnect и Socket.BeginReceive..."
Re[3]: Из синхронного сокета в асинхронный
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.10.11 18:04
Оценка:
Здравствуйте, SergeyT., Вы писали:

ST>Простой пример (только с сервером, а не с клиентом): если мы для каждого входного соединения будем создавать новый поток, то на каждое новое подключение будет тратиться как минимум 1Мб памяти


Не памяти, а адресного пространства. И размер стека можно задать другой, если гарантированно 1М не понадобится.

ST>Но одновременно в сотне потоков обрабатывать данные очень не эффективно при наличии 4-х физических процессоров.


Это пофигу. Все равно в блокирующих вызовах основное время тратится на ожидание и активных потоков будет примерно столько же, сколько при использовании IO completion ports.
... << RSDN@Home 1.2.0 alpha 5 rev. 1537 on Windows 7 6.1.7601.65536>>
AVK Blog
Re[4]: Из синхронного сокета в асинхронный
От: enCobalt  
Дата: 30.10.11 20:28
Оценка:
Здравствуйте, nbit, Вы писали:

N>Для меня очень важна производительность, поэтому я и выбрал асинхронные сокеты, хоть для меня их и очень трудно понять. Подскажите а какие есть варианты реализаций асинхронных сокетов? Потому что например классы, которые Вы указали для примера, вообще не используются в примере от MSDN Socket Performance Technology Sample см. также описание на русском


Похоже пример изначально написан под плюсы..

Строго говоря, пример использует асинхронные операции сокета, только другим боком, через
bool ReceiveAsync(System.Net.Sockets.SocketAsyncEventArgs e) и систему эвентов, но только для сервера.
Я бы так делать не стал. А клиент в примере обычный.

Я не смотрел глубоко в код, на предмет чистоты использования эвентов, но на всякий случай в двух
словах: у сборщика мусора есть небольшая проблема с эвентами. Майкрософт осторожно предупреждает, что "Therefore, event handlers can keep objects alive longer than expected."

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

А если задача простая и не ресурсоемкая, а тебе расово не подходит асинк*, то лучше используй ThreadPool вместо Thread.
Хочу инвайт на хабру :)
Re[5]: Из синхронного сокета в асинхронный
От: nbit http://cyber-dream.ru
Дата: 30.10.11 23:48
Оценка:
Здравствуйте, enCobalt, Вы писали:

C>Здравствуйте, nbit, Вы писали:


N>>Для меня очень важна производительность, поэтому я и выбрал асинхронные сокеты, хоть для меня их и очень трудно понять. Подскажите а какие есть варианты реализаций асинхронных сокетов? Потому что например классы, которые Вы указали для примера, вообще не используются в примере от MSDN Socket Performance Technology Sample см. также описание на русском


C>Похоже пример изначально написан под плюсы..


C>Строго говоря, пример использует асинхронные операции сокета, только другим боком, через

C>bool ReceiveAsync(System.Net.Sockets.SocketAsyncEventArgs e) и систему эвентов, но только для сервера.
C>Я бы так делать не стал. А клиент в примере обычный.

C>Я не смотрел глубоко в код, на предмет чистоты использования эвентов, но на всякий случай в двух

C>словах: у сборщика мусора есть небольшая проблема с эвентами. Майкрософт осторожно предупреждает, что "Therefore, event handlers can keep objects alive longer than expected."

C>В случае, если у тебя идет перекачка длинных данных в конкурентных потоках, и нужно нужно что-то посерьезнее для разделения толщины канала — копай поисковики по ключевому слову "chunking". Грубо говоря — это управляемая фрагментация передачи.


C>А если задача простая и не ресурсоемкая, а тебе расово не подходит асинк*, то лучше используй ThreadPool вместо Thread.


В общем на другом ресурсе мне помогли с примером. Код, немного измененный если интересно тут выложу, а сам пример можете скачать здесь.

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace AsyncSocketExample
{
    /*
     * ВНИМАНИЕ: ПЕРЕД ПРОВЕРКОЙ РАБОТЫ ПРОГРАММЫ, УБЕДИТЕСЬ, ЧТО ФАЙРФОЛ ЕЁ НЕ БЛОКИРУЕТ!
     */

    public partial class Form1 : Form
    {
        private delegate void MyDelegate(object args);

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(textBox1.Text))
            {
                MessageBox.Show("Необходимо указать url!", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            int port = 80; // по умолчанию порт 80
            Uri u = new Uri(textBox1.Text);

            // создаем сокет
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            // инициализируем обработчик асихронных операций
            SocketAsyncEventArgs se = new SocketAsyncEventArgs();
            // подключаем обработчики событий асинхронных запросов
            se.Completed += new EventHandler<SocketAsyncEventArgs>(OnSend);

            // цепляем точку доступа
            IPHostEntry hostEntry = Dns.GetHostEntry(u.Host);
            se.RemoteEndPoint = new IPEndPoint(hostEntry.AddressList[0], port);

            //se.UserToken = s;
            // создаем асихронное подключение
            s.ConnectAsync(se);
        }

        // обработчик асинхронных операций
        private void OnSend(object sender, SocketAsyncEventArgs e)
        {
            Socket s = (Socket)sender; // в sender будет передаваться экземпляр сокета, вызвавшего это событие

            // выводим информацию о текущей операции и результатах её выполнения
            if (e.SocketError == SocketError.Success)
            {
                SetLabel(String.Format("Операция {0} успешно выполнена!", e.LastOperation));
            }
            else
            {
                SetLabel(String.Format("Ошибка {1} при выполнении операции {0}...", e.LastOperation, e.SocketError));
            }
            // --

            // делаем что-нибудь, в зависимости от типа выполненной операции
            switch (e.LastOperation)
            {
                case SocketAsyncOperation.Connect:
                    // если соединение установлено
                    if (e.SocketError == SocketError.Success)
                    { // отправляем запрос
                        SendRequest(s, e);
                    }
                    break;

                case SocketAsyncOperation.Send:
                    // если запрос отправлен без ошибок
                    if (e.SocketError == SocketError.Success)
                    { // получаем ответ от удаленного сервера
                        SocketAsyncEventArgs er = new SocketAsyncEventArgs();
                        er.Completed += new EventHandler<SocketAsyncEventArgs>(OnReceive);
                        byte[] buffer = new byte[4096];// размер пакета 4 кб
                        er.SetBuffer(buffer, 0, buffer.Length);
                        // аннулируем предыдущий результат, если был
                        SetRequestResult(null);
                        // получаем пачку ответа
                        s.ReceiveAsync(er);
                    }
                    break;
            }
        }

        private void OnReceive(object sender, SocketAsyncEventArgs e)
        {
            Socket s = (Socket)sender; // в sender будет передаваться экземпляр сокета, вызвавшего это событие

            // выводим информацию о текущей операции и результатах её выполнения
            if (e.SocketError == SocketError.Success)
            {
                SetLabel(String.Format("Операция {0} успешно выполнена! Получено {1} байт.", e.LastOperation, e.BytesTransferred));

                // передаем результат в TextBox
                SetRequestResult(Encoding.UTF8.GetString(e.Buffer));

                // слудующая пачка данных, если есть
                if (e.BytesTransferred > 0)
                {
                    // нужно обнулить буфер, иначе куски данных могут попасть в следующий ответ
                    byte[] buffer = new byte[4096];
                    e.SetBuffer(buffer, 0, buffer.Length);
                    s.ReceiveAsync(e);
                }
                else
                {
                    // нет данных, отключаемся
                    s.Close();
                }
            }
            else
            {
                SetLabel(String.Format("Ошибка {1} при выполнении операции {0}...", e.LastOperation, e.SocketError));
            }
            // --
        }

        // метод отправляет запрос
        private void SendRequest(Socket s, SocketAsyncEventArgs e)
        {
            // формируем HTTP-запрос
            Uri u = new Uri(textBox1.Text);
            string request = "GET /blogs/infosecurity/70330/ HTTP/1.1\r\nHost: " + u.Host + "\r\nConnection: Close\r\n\r\n";
            Byte[] buffer = Encoding.ASCII.GetBytes(request);
            e.SetBuffer(buffer, 0, buffer.Length);
            // отправляем асинхронный запрос
            s.SendAsync(e);
        }

        // изменение label-а, находящегося в основном потоке
        private void SetLabel(object args)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MyDelegate(SetLabel), args);
                return;
            }
            label2.Text = args.ToString();
        }

        // изменение TextBox, содержащего результат запроса
        private void SetRequestResult(object args)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MyDelegate(SetRequestResult), args);
                return;
            }
            if (args == null)
            {
                textBox2.Text = ""; // сбрасываем
            }
            else
            {
                textBox2.Text += args.ToString();// добавляем кусок данных
            }
        }
    }
}


В общем то пример работает, но "тяжелые" (может быть и обычные, но пока не замечал такого еще) html страницы, где много информации, он не до конца скачивает, например вот эту. Сервер преждевременно возвращает в переменную e.BytesTransferred метода OnReceive значение 0, означающие по справке мсдна, что подключение было закрыто на удаленном конце. Почему так происходит непонятно. Уважаемые форумчане, если есть предположения поделитесь пожалуйста опытом.
Re[6]: Из синхронного сокета в асинхронный
От: Hacker_Delphi Россия  
Дата: 31.10.11 00:18
Оценка:
Здравствуйте, nbit, Вы писали:

N>Почему так происходит непонятно. Уважаемые форумчане, если есть предположения поделитесь пожалуйста опытом.

В общем, увидел только Connection:Close и сразу напрягся. КМНИП когда я писал свой http недосервер (так надо было) в примерно 2000 году, рекомендацией было использование KeepAlive хедера и закрытие этих самых коннекшеннов только по необходимости.
... << RSDN@Home 1.2.0 alpha 5 rev. 1538>>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
Re[4]: Из синхронного сокета в асинхронный
От: Jolly Roger  
Дата: 31.10.11 02:19
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, SergeyT., Вы писали:


ST>>Простой пример (только с сервером, а не с клиентом): если мы для каждого входного соединения будем создавать новый поток, то на каждое новое подключение будет тратиться как минимум 1Мб памяти


AVK>Не памяти, а адресного пространства. И размер стека можно задать другой, если гарантированно 1М не понадобится.


+1

ST>>Но одновременно в сотне потоков обрабатывать данные очень не эффективно при наличии 4-х физических процессоров.


AVK>Это пофигу. Все равно в блокирующих вызовах основное время тратится на ожидание и активных потоков будет примерно столько же, сколько при использовании IO completion ports.


Только потоков будет намного больше, их содержание требует ненужного расхода ресурсов, а на переключение контекстов уходит процессорное время. И всё бы ничего, если бы эти потоки активировались более-менее равномерно, но в реальности то все "спят", то сразу целой куче "вдруг" потребовался процессор. С этими неприятностями, собственно, и призван бороться IOCP.
"Нормальные герои всегда идут в обход!"
Re[7]: Из синхронного сокета в асинхронный
От: nbit http://cyber-dream.ru
Дата: 31.10.11 06:11
Оценка:
Здравствуйте, Hacker_Delphi, Вы писали:

H_D>Здравствуйте, nbit, Вы писали:


N>>Почему так происходит непонятно. Уважаемые форумчане, если есть предположения поделитесь пожалуйста опытом.

H_D>В общем, увидел только Connection:Close и сразу напрягся. КМНИП когда я писал свой http недосервер (так надо было) в примерно 2000 году, рекомендацией было использование KeepAlive хедера и закрытие этих самых коннекшеннов только по необходимости.

Прбовал с KeepAlive — то же самое почти. (один раз из пяти все таки до конца скачал)
Re[7]: Из синхронного сокета в асинхронный
От: nbit http://cyber-dream.ru
Дата: 31.10.11 08:25
Оценка:
+ пример мсдна из первого поста на блокируемом сокете спокойно справляется с задачей и хидеры там такие же.
Re[5]: Из синхронного сокета в асинхронный
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 31.10.11 08:39
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Только потоков будет намного больше, их содержание требует ненужного расхода ресурсов


Верно.

JR>а на переключение контекстов уходит процессорное время


Спящие потоки переключать не нужно.

JR>. И всё бы ничего, если бы эти потоки активировались более-менее равномерно, но в реальности то все "спят", то сразу целой куче "вдруг" потребовался процессор С этими неприятностями, собственно, и призван бороться IOCP.


Каким образом?
... << RSDN@Home 1.2.0 alpha 5 rev. 1537 on Windows 7 6.1.7601.65536>>
AVK Blog
Re[6]: Из синхронного сокета в асинхронный
От: Jolly Roger  
Дата: 31.10.11 09:56
Оценка:
Здравствуйте, AndrewVK, Вы писали:

JR>>а на переключение контекстов уходит процессорное время


AVK>Спящие потоки переключать не нужно.


JR>>. И всё бы ничего, если бы эти потоки активировались более-менее равномерно, но в реальности то все "спят", то сразу целой куче "вдруг" потребовался процессор


AVK>Каким образом?


Признаться, я в некотором затруднении Это напрямую следует из логики его работы Но Вы ведь наверняка читали, например, Рихтера. Или Соломона-Руссиновича, у которых оно расписано более детально. Потому уточните, пожалуйста, вопрос.
"Нормальные герои всегда идут в обход!"
Re[7]: Из синхронного сокета в асинхронный
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 31.10.11 10:05
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Признаться, я в некотором затруднении Это напрямую следует из логики его работы


Сама по себе идея IOCP никаким образом не спасает от описанного тобой. Спасает наличие очереди сообщений внутри реализации IOCP, но ровно такую же очередь совсем несложно организовать и на обычном блокирующем API.
Фишка IOCP не в очереди, а в возможности увязать активацию потока на железное прерывание, чего никакими способами в пользовательском приложении не достичь.
В практическом же плане, безусловно, в Windows при малейшей возможности нужно именно IOCP использовать. А для серверной части еще и http.sys.
... << RSDN@Home 1.2.0 alpha 5 rev. 1537 on Windows 7 6.1.7601.65536>>
AVK Blog
Re[8]: Из синхронного сокета в асинхронный
От: Jolly Roger  
Дата: 31.10.11 10:32
Оценка: 3 (1) +1
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, Jolly Roger, Вы писали:


JR>>Признаться, я в некотором затруднении Это напрямую следует из логики его работы


AVK>Сама по себе идея IOCP никаким образом не спасает от описанного тобой. Спасает наличие очереди сообщений внутри реализации IOCP, но ровно такую же очередь совсем несложно организовать и на обычном блокирующем API.

AVK>Фишка IOCP не в очереди, а в возможности увязать активацию потока на железное прерывание, чего никакими способами в пользовательском приложении не достичь.

Простите, а это Вы на какие мои утверждения возражаете? Или Вы сам с собой спорите?

Ну раз пошло такое дело, хотелось-бы поподробнее про привязку кжелезным прерываниям, потому как ононе очень вписывается в мои представления.

Гланое преимущество от порта заключается в том, что он позволяет оптимизировать использование процессорного времени. При наличие заданий он, с одной стороны, не двёт ядрам простаивать, поддерживая число активных потоков не менее числа ядрер, а с другой, при дефолтной настройке, по возможности не активирует излишнее число потоков (больше числа ядер), избегая тем самым излишних переключений их контекстов. Порт умеет отслеживать активность подключенных к нему потоков, и если такой поток "засыпает" на, например, IO-операции, порт может тут-же активировать следующий поток из своего пула, не давая процесссору простаивать. И вот это, действительно, никак иначе в третьем кольце не получишь. Другой момент — первым активируется всегда поток, последним вызвавший GetQueuedCompletionStatus, что позволяет снизить вероятность его усыпления — при наличии заданий в очереди поток сразу его получает, не проходя через стадии усыпления-пробуждения.
"Нормальные герои всегда идут в обход!"
Re[9]: Из синхронного сокета в асинхронный
От: nbit http://cyber-dream.ru
Дата: 31.10.11 11:09
Оценка:
Добавлю комментарий в тему от

Мощь порта завершения ввода-вывода заключается в регулировании степени конкурентности — параметр NumberOfConcurrentThreads функции CreateIoCompletionPort, и в возможности привязки к операции ввода-вывода — уже упомянутому в комментариях сокету или файлу или вообще любому описателю, представляющему собой объект ввода-вывода.

Суть параметра NumberOfConcurrentThreads заключается в том, что через его значение вы сообщаете, какое максимальное количество активных потоков может принимать сообщения от порта завершения ввода-вывода. Если ваш пул содержит 10 потоков, ожидающих на вызове GetQueuedCompletionStatus, а значение NumberOfConcurrentThreads равно 2, то только 2 из них получат управление. Если же один из них "заснёт" в процессе обработки сообщения, например, на файловой операции, а в порту будет содержаться очередное сообщение, то порт разбудить новый поток и предоставит ему возможность обработать данные. В этом главное отличие порта от мьютексов.

Привязка объекта ввода-вывода в сочетании с регулированием степени конкуренции, предоставляют мощнейший механизм реализации сессий на серверной стороне.

взято отсюда.
А вообще я выбрал данную реализацию сокетов изза разницы в используемых подходах, детали и причины введения нового метода можно посмотреть здесь. Если вкратце, то ConnectAsync более производителен и не требует лишних синхронизаций, работает под сильверлайтом (в отличии от первого), но сложнее в написании и поддержке, поэтому socket.BeginConnect() был отброшен т.к. для меня очень важна производительность. + пример производительности сокетов от MSDN как раз реализован на этом подходе Socket Performance Technology Sample
Парни может хватит воевать? Подскажите лучше как выснить почему коннект преждевременно рвется, ведь на блокируемом сокете все нормально.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.