Не могу реально сбросить сокет TCP клиента. Как?
От: Dimonira  
Дата: 04.05.12 05:18
Оценка:
До сих пор не приходилось использовать TCP явно, использовал UDP и сам разруливал обмен между хостом и железякой.
Теперь решил сделать по уму: в железяку вставил поддержку протокола TCP (адаптированный OpenTCP), запустил в режиме сервера, а на хосте запустил клиента (текст прикладываю).
Первый коннект, обмен и дисконнект проходят нормально. А при попытке второго и дальше коннекта вылезает ошибка повторного использования сокета, мол не положено два сокета с одинаковыми IP и портом (железяки). Значит на хосте Shutdown() и Close() сокета "выключают" его только в программе, а не в системе? Как же быть? Пробовал и так, и сяк — ничего не выходит. При этом железяка, как я понял из отладочных сообщений, ведёт себя корректно — после дисконнекта переходит в прослушку. Если программу клиента завершить, а потом снова запустить, то коннект и прочее проходят нормально. Искал в интернете, находил обсуждения этой же проблемы, но решения так и не нашёл.
Что посоветуете?

Клиент TCP (за основу пример отсюда).
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

public class AsyncTcpClient : Form
{
    private TextBox newText;
    private TextBox conStatus;
    private ListBox results;
    private Label label1;
    private Label label2;
    private Button sendit;
    private Button connect;
    private Button discon;
    private byte[] data = new byte[10240];
    private Socket client;

    private void InitializeComponent()
    {
            this.label1 = new System.Windows.Forms.Label();
            this.newText = new System.Windows.Forms.TextBox();
            this.results = new System.Windows.Forms.ListBox();
            this.label2 = new System.Windows.Forms.Label();
            this.conStatus = new System.Windows.Forms.TextBox();
            this.sendit = new System.Windows.Forms.Button();
            this.connect = new System.Windows.Forms.Button();
            this.discon = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(12, 41);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(83, 13);
            this.label1.TabIndex = 0;
            this.label1.Text = "Enter text string:";
            // 
            // newText
            // 
            this.newText.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.newText.Location = new System.Drawing.Point(12, 57);
            this.newText.Name = "newText";
            this.newText.Size = new System.Drawing.Size(339, 20);
            this.newText.TabIndex = 1;
            // 
            // results
            // 
            this.results.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.results.Location = new System.Drawing.Point(12, 85);
            this.results.Name = "results";
            this.results.Size = new System.Drawing.Size(410, 238);
            this.results.TabIndex = 2;
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(180, 19);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(40, 13);
            this.label2.TabIndex = 3;
            this.label2.Text = "Status:";
            // 
            // conStatus
            // 
            this.conStatus.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.conStatus.Location = new System.Drawing.Point(226, 16);
            this.conStatus.Name = "conStatus";
            this.conStatus.Size = new System.Drawing.Size(196, 20);
            this.conStatus.TabIndex = 4;
            this.conStatus.Text = "Disconnected";
            // 
            // sendit
            // 
            this.sendit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.sendit.Location = new System.Drawing.Point(357, 53);
            this.sendit.Name = "sendit";
            this.sendit.Size = new System.Drawing.Size(65, 26);
            this.sendit.TabIndex = 5;
            this.sendit.Text = "Send";
            this.sendit.Click += new System.EventHandler(this.ButtonSendOnClick);
            // 
            // connect
            // 
            this.connect.Location = new System.Drawing.Point(12, 12);
            this.connect.Name = "connect";
            this.connect.Size = new System.Drawing.Size(78, 26);
            this.connect.TabIndex = 6;
            this.connect.Text = "Connect";
            this.connect.Click += new System.EventHandler(this.ButtonConnectOnClick);
            // 
            // discon
            // 
            this.discon.Location = new System.Drawing.Point(96, 12);
            this.discon.Name = "discon";
            this.discon.Size = new System.Drawing.Size(78, 26);
            this.discon.TabIndex = 7;
            this.discon.Text = "Disconnect";
            this.discon.Click += new System.EventHandler(this.ButtonDisconOnClick);
            // 
            // AsyncTcpClient
            // 
            this.ClientSize = new System.Drawing.Size(434, 334);
            this.Controls.Add(this.newText);
            this.Controls.Add(this.results);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.conStatus);
            this.Controls.Add(this.sendit);
            this.Controls.Add(this.connect);
            this.Controls.Add(this.discon);
            this.Controls.Add(this.label1);
            this.MaximumSize = new System.Drawing.Size(700, 372);
            this.MinimumSize = new System.Drawing.Size(450, 372);
            this.Name = "AsyncTcpClient";
            this.Text = "Asynchronous TCP client";
            this.ResumeLayout(false);
            this.PerformLayout();

    }

    public AsyncTcpClient()
    {
        this.InitializeComponent();
    }

    bool IsSocketNullOrDisposed(Socket socket)
    {
        if (socket != null) { try { int temp = socket.Available; return false; } catch (ObjectDisposedException) { } }
        return true;
    }

    void ButtonConnectOnClick(object obj, EventArgs ea)
    {
        try
        {
            if (!IsSocketNullOrDisposed(client))
                ButtonDisconOnClick(null, null);
            conStatus.Text = "Connecting...";
            Socket newclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //newclient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            newclient.Bind(new IPEndPoint(IPAddress.Parse("10.10.1.130"), 54328));
            IPEndPoint iep = new IPEndPoint(IPAddress.Parse("10.10.1.110"), 54329);
            newclient.BeginConnect(iep, new AsyncCallback(Connected), newclient);
        }
        catch (SocketException e)
        {
            results.Items.Add(e.Message);
        }
    }

    void Connected(IAsyncResult iar)
    {
        client = (Socket)iar.AsyncState;
        try
        {
            client.EndConnect(iar);
            string str = client.Connected ? "Connected to: " + client.RemoteEndPoint.ToString() : "Not connected";
            if (conStatus.InvokeRequired)
                conStatus.Invoke((Action<string>)delegate(string Title) { conStatus.Text = Title; }, new object[] { str });
            else
                conStatus.Text = str;
            //if (client.Connected)
            //    client.BeginReceive(data, 0, data.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), client);
        }
        catch (SocketException e)
        {
            string str = "Error connecting";
            if (conStatus.InvokeRequired)
                conStatus.Invoke((Action<string>)delegate(string Title) { conStatus.Text = Title; }, new object[] { str });
            else
                conStatus.Text = str;
            if (results.InvokeRequired)
                results.Invoke((Action<object>)delegate(object item) { results.Items.Add(item); }, new object[] { e.Message });
            else
                results.Items.Add(e.Message);
        }
    }

    void ButtonDisconOnClick(object obj, EventArgs ea)
    {
        try
        {
            //if (client.Connected)
            client.Shutdown(SocketShutdown.Both);
            client.Close();
            conStatus.Text = "Disconnected";
        }
        catch (SocketException e)
        {
            results.Items.Add(e.Message);
        }
    }

    void ButtonSendOnClick(object obj, EventArgs ea)
    {
        try
        {
            byte[] message = Encoding.ASCII.GetBytes(newText.Text);
            //newText.Clear();
            if (client.Connected)
                client.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(SendCallback), client);
        }
        catch (SocketException e)
        {
            results.Items.Add(e.Message);
        }
    }

    void SendCallback(IAsyncResult iar)
    {
        try
        {
            Socket remote = (Socket)iar.AsyncState;
            int sent = remote.EndSend(iar);
            remote.BeginReceive(data, 0, data.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), remote);
        }
        catch (SocketException e)
        {
            if (results.InvokeRequired)
                results.Invoke((Action<object>)delegate(object item) { results.Items.Add(item); }, new object[] { e.Message });
            else
                results.Items.Add(e.Message);
        }
    }

    void ReceiveCallback(IAsyncResult iar)
    {
        try
        {
            Socket remote = (Socket)iar.AsyncState;
            if (remote.Connected)
            {
                int recv = remote.EndReceive(iar);
                if (recv != 0)
                {
                    string stringData = Encoding.ASCII.GetString(data, 0, recv);
                    if (results.InvokeRequired)
                        results.Invoke((Action<object>)delegate(object item) { results.Items.Add(item); }, new object[] { stringData });
                    else
                        results.Items.Add(stringData);
                }
                //remote.BeginReceive(data, 0, data.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), remote);
            }
        }
        catch (SocketException e)
        {
            if (results.InvokeRequired)
                results.Invoke((Action<object>)delegate(object item) { results.Items.Add(item); }, new object[] { e.Message });
            else
                results.Items.Add(e.Message);
        }
    }

    public static void Main()
    {
        Application.Run(new AsyncTcpClient());
    }
}
Re: Не могу реально сбросить сокет TCP клиента. Как?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 04.05.12 05:38
Оценка:
Здравствуйте, Dimonira, Вы писали:

D>Первый коннект, обмен и дисконнект проходят нормально. А при попытке второго и дальше коннекта вылезает ошибка повторного использования сокета, мол не положено два сокета с одинаковыми IP и портом (железяки).


google:CLOSE_WAIT
google:SO_REUSEADDR
The God is real, unless declared integer.
Отредактировано 26.02.2015 9:07 netch80 (форматирование) . Предыдущая версия .
Re[2]: Не могу реально сбросить сокет TCP клиента. Как?
От: Dimonira  
Дата: 04.05.12 06:37
Оценка:
Здравствуйте, netch80, Вы писали:

N>google://CLOSE_WAIT

N>google://SO_REUSEADDR

Я же написал: поиск проводил, решения НЕ НАШЁЛ.
Никакие Disconnect(true) (аналог си-шной DisconnectEx с её TF_REUSE_SOCKET), уменьшение TcpTimedWaitDelay (может перезагружаться надо, хотя изначально было 30с, но и через это время ничего не реюзится), Close() сокета и приравнивание его к null, и т.д. — не помогли.
Поскольку после закрытия клиента и повторного его запуска всё начинает работать, делаю вывод, что в системе копаться нет нужды. Что-то надо сделать в самой программе...
Re[3]: Не могу реально сбросить сокет TCP клиента. Как?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 04.05.12 06:49
Оценка:
Здравствуйте, Dimonira, Вы писали:

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


N>>google://CLOSE_WAIT

N>>google://SO_REUSEADDR

D>Я же написал: поиск проводил, решения НЕ НАШЁЛ.


Этого недостаточно, надо указывать, какие именно методы не сработали. А то мало ли что искалось.

D>Никакие Disconnect(true) (аналог си-шной DisconnectEx с её TF_REUSE_SOCKET), уменьшение TcpTimedWaitDelay (может перезагружаться надо, хотя изначально было 30с, но и через это время ничего не реюзится), Close() сокета и приравнивание его к null, и т.д. — не помогли.


У Вас какая-то странная среда исполнения. Что именно это и какая версия? Судя по тексту, там где-то посреди дотнет, но что под ним, какая версия и т.д. — может существенно влиять.
Может, надо перенести обсуждение в дотнетовский форум, если это специфичная грабля рантайма.

D>Поскольку после закрытия клиента и повторного его запуска всё начинает работать, делаю вывод, что в системе копаться нет нужды. Что-то надо сделать в самой программе...


Для начала попробуйте отследить, что видно именно в сетевом стеке.
Например, по netstat -a (если это винда традиционного стиля) — есть соединение или нет? Занят порт или нет?
The God is real, unless declared integer.
Re: Не могу реально сбросить сокет TCP клиента. Как?
От: Michael Chelnokov Украина  
Дата: 04.05.12 06:58
Оценка:
Здравствуйте, Dimonira, Вы писали:

D> newclient.Bind(new IPEndPoint(IPAddress.Parse("10.10.1.130"), 54328));


Вот это убери и все заработает
Re[4]: Не могу реально сбросить сокет TCP клиента. Как?
От: Dimonira  
Дата: 04.05.12 07:24
Оценка:
Оказалось, что всё-таки TcpTimedWaitDelay рулит. И, похоже, новое значение вступает в силу после перезапуска системы. Изначально TcpTimedWaitDelay равно 30 секунд, я исправил на 5. Без перезагрузки оказалось, что через 30 секунд после дисконнекта, повторный коннект прошёл таки!
Но вылезло ещё кое-что. Если после коннекта нет обмена, то сервер (моя железка) сама разрывает соединение по таймауту (я поставил 2 минуты). При этом в клиенте возникает исключение "Удалённый хост принудительно разорвал существующее подключение", а при попытке коннекта — исключение "Сделан запрос на подключение для уже подключённого сокета". Что странно, ведь система знает, что коннект разорван. Хотя смысл слова "подключённого" может уже и другой в этой ситуации. Однако после принудительного вызова дисконнекта у клиента, повторный коннект сработал!
Но всё-таки хотелось бы программно "убивать" сокет, чтобы можно было в любой момент без большой задержки реализовывать короткую "сессию" типа коннект-обмен-дисконект. Потому как другой вариант — гонять туфту по сети ради поддержания коннекта, не выглядит привлекательным.
Re[2]: Не могу реально сбросить сокет TCP клиента. Как?
От: Dimonira  
Дата: 04.05.12 07:24
Оценка:
Здравствуйте, Michael Chelnokov, Вы писали:

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


D>> newclient.Bind(new IPEndPoint(IPAddress.Parse("10.10.1.130"), 54328));


MC>Вот это убери и все заработает


Пробовал — не заработало.
Но я вроде начал осознавать ситуацию (см. ответ выше).
Re[5]: Не могу реально сбросить сокет TCP клиента. Как?
От: Dimonira  
Дата: 04.05.12 07:54
Оценка:
Да, ещё забыл добавить. Клиента я изменил так: сам сокет перестал убивать (Close) по дисконнекту, а делаю только Shutdown (именно после этого сервер разрывает коннект и переходит в прослушку) и Disconnect. Потом при повторном коннекте вызываю только BeginConnect. Держать проинициализированный сокет на всём времени жизни приложения не проблема. Я бы даже сказал, что ещё и лучше — чтобы другие не повадились его открывать.
Но всё-таки как реально "убить" бывший коннект так, чтобы можно было сразу делать новый? Поскольку "убивание" самого сокета ничего в этом смысле не даёт, то получается, что надо ждать истечения TcpTimedWaitDelay. Не знаю хорошо ли это время сокращать до секунды (минимум, что можно сделать), но даже этого много для моего приложения (будет несколько соединений с сервером и т.д.). По идее можно сделать коннект и проверять его состояние перед очередным обменом (свойство Connected сокета) и в случае разрыва хостом снова дисконнектиться/коннектиться. Но может оказаться, что TcpTimedWaitDelay начала истекать только что и придётся ждать, что не очень хорошо.

На всякий случай прикладываю текст клиента:

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

public class AsyncTcpClient : Form
{
    private TextBox newText;
    private TextBox conStatus;
    private ListBox results;
    private Label label1;
    private Label label2;
    private Button sendit;
    private Button connect;
    private Button discon;
    private byte[] data = new byte[10240];
    private Socket client;

    private void InitializeComponent()
    {
            this.label1 = new System.Windows.Forms.Label();
            this.newText = new System.Windows.Forms.TextBox();
            this.results = new System.Windows.Forms.ListBox();
            this.label2 = new System.Windows.Forms.Label();
            this.conStatus = new System.Windows.Forms.TextBox();
            this.sendit = new System.Windows.Forms.Button();
            this.connect = new System.Windows.Forms.Button();
            this.discon = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(12, 41);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(83, 13);
            this.label1.TabIndex = 0;
            this.label1.Text = "Enter text string:";
            // 
            // newText
            // 
            this.newText.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.newText.Location = new System.Drawing.Point(12, 57);
            this.newText.Name = "newText";
            this.newText.Size = new System.Drawing.Size(339, 20);
            this.newText.TabIndex = 1;
            // 
            // results
            // 
            this.results.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.results.Location = new System.Drawing.Point(12, 85);
            this.results.Name = "results";
            this.results.Size = new System.Drawing.Size(410, 238);
            this.results.TabIndex = 2;
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(180, 19);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(40, 13);
            this.label2.TabIndex = 3;
            this.label2.Text = "Status:";
            // 
            // conStatus
            // 
            this.conStatus.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.conStatus.Location = new System.Drawing.Point(226, 16);
            this.conStatus.Name = "conStatus";
            this.conStatus.Size = new System.Drawing.Size(196, 20);
            this.conStatus.TabIndex = 4;
            this.conStatus.Text = "Disconnected";
            // 
            // sendit
            // 
            this.sendit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.sendit.Location = new System.Drawing.Point(357, 53);
            this.sendit.Name = "sendit";
            this.sendit.Size = new System.Drawing.Size(65, 26);
            this.sendit.TabIndex = 5;
            this.sendit.Text = "Send";
            this.sendit.Click += new System.EventHandler(this.ButtonSendOnClick);
            // 
            // connect
            // 
            this.connect.Location = new System.Drawing.Point(12, 12);
            this.connect.Name = "connect";
            this.connect.Size = new System.Drawing.Size(78, 26);
            this.connect.TabIndex = 6;
            this.connect.Text = "Connect";
            this.connect.Click += new System.EventHandler(this.ButtonConnectOnClick);
            // 
            // discon
            // 
            this.discon.Location = new System.Drawing.Point(96, 12);
            this.discon.Name = "discon";
            this.discon.Size = new System.Drawing.Size(78, 26);
            this.discon.TabIndex = 7;
            this.discon.Text = "Disconnect";
            this.discon.Click += new System.EventHandler(this.ButtonDisconOnClick);
            // 
            // AsyncTcpClient
            // 
            this.ClientSize = new System.Drawing.Size(434, 334);
            this.Controls.Add(this.newText);
            this.Controls.Add(this.results);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.conStatus);
            this.Controls.Add(this.sendit);
            this.Controls.Add(this.connect);
            this.Controls.Add(this.discon);
            this.Controls.Add(this.label1);
            this.MaximumSize = new System.Drawing.Size(700, 372);
            this.MinimumSize = new System.Drawing.Size(450, 372);
            this.Name = "AsyncTcpClient";
            this.Text = "Asynchronous TCP client";
            this.ResumeLayout(false);
            this.PerformLayout();

    }

    public AsyncTcpClient()
    {
        this.InitializeComponent();
    }

    bool IsSocketNullOrDisposed(Socket socket)
    {
        if (socket != null) { try { int temp = socket.Available; return false; } catch (ObjectDisposedException) { } }
        return true;
    }

    void ButtonConnectOnClick(object obj, EventArgs ea)
    {
        try
        {
            if (IsSocketNullOrDisposed(client))
            {
                conStatus.Text = "Socket initialization...";
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                client.Bind(new IPEndPoint(IPAddress.Parse("10.10.1.130"), 54328));
            }
            if (!client.Connected)
            {
                conStatus.Text = "Connecting...";
                IPEndPoint iep = new IPEndPoint(IPAddress.Parse("10.10.1.110"), 54329);
                client.BeginConnect(iep, new AsyncCallback(Connected), client);
            }
        }
        catch (SocketException e)
        {
            results.Items.Add(e.Message);
        }
    }

    void Connected(IAsyncResult iar)
    {
        Socket remote = (Socket)iar.AsyncState;
        try
        {
            remote.EndConnect(iar);
            string str = remote.Connected ? "Connected to: " + remote.RemoteEndPoint.ToString() : "Not connected";
            if (conStatus.InvokeRequired)
                conStatus.Invoke((Action<string>)delegate(string Title) { conStatus.Text = Title; }, new object[] { str });
            else
                conStatus.Text = str;
            //if (remote.Connected)
            //    remote.BeginReceive(data, 0, data.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), remote);
        }
        catch (SocketException e)
        {
            string str = "Error connecting";
            if (conStatus.InvokeRequired)
                conStatus.Invoke((Action<string>)delegate(string Title) { conStatus.Text = Title; }, new object[] { str });
            else
                conStatus.Text = str;
            if (results.InvokeRequired)
                results.Invoke((Action<object>)delegate(object item) { results.Items.Add(item); }, new object[] { e.Message });
            else
                results.Items.Add(e.Message);
        }
    }

    void ButtonDisconOnClick(object obj, EventArgs ea)
    {
        try
        {
            //if (client.Connected)
            client.Shutdown(SocketShutdown.Both);
            client.Disconnect(true);
            //client.Close();
            conStatus.Text = "Disconnected";
        }
        catch (SocketException e)
        {
            results.Items.Add(e.Message);
        }
    }

    void ButtonSendOnClick(object obj, EventArgs ea)
    {
        try
        {
            byte[] message = Encoding.ASCII.GetBytes(newText.Text);
            //newText.Clear();
            if (client.Connected)
                client.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(SendCallback), client);
        }
        catch (SocketException e)
        {
            results.Items.Add(e.Message);
        }
    }

    void SendCallback(IAsyncResult iar)
    {
        try
        {
            Socket remote = (Socket)iar.AsyncState;
            int sent = remote.EndSend(iar);
            remote.BeginReceive(data, 0, data.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), remote);
        }
        catch (SocketException e)
        {
            if (results.InvokeRequired)
                results.Invoke((Action<object>)delegate(object item) { results.Items.Add(item); }, new object[] { e.Message });
            else
                results.Items.Add(e.Message);
        }
    }

    void ReceiveCallback(IAsyncResult iar)
    {
        try
        {
            Socket remote = (Socket)iar.AsyncState;
            if (remote.Connected)
            {
                int recv = remote.EndReceive(iar);
                if (recv != 0)
                {
                    string stringData = Encoding.ASCII.GetString(data, 0, recv);
                    if (results.InvokeRequired)
                        results.Invoke((Action<object>)delegate(object item) { results.Items.Add(item); }, new object[] { stringData });
                    else
                        results.Items.Add(stringData);
                }
                //remote.BeginReceive(data, 0, data.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), remote);
            }
        }
        catch (SocketException e)
        {
            if (results.InvokeRequired)
                results.Invoke((Action<object>)delegate(object item) { results.Items.Add(item); }, new object[] { e.Message });
            else
                results.Items.Add(e.Message);
        }
    }

    public static void Main()
    {
        Application.Run(new AsyncTcpClient());
    }
}
Re[6]: Не могу реально сбросить сокет TCP клиента. Как?
От: Dimonira  
Дата: 04.05.12 08:01
Оценка:
Выяснилось, что свойство Connected сокета клиента не сбрасывается автоматически после разрыва соединения со стороны хоста. Это происходит только после попытки что-то сделать с сокетом — вылетает исключение "Удаленный хост принудительно разорвал существующее подключение". Только после этого становится Connected = flase. Так что придётся отлавливать...
Re[7]: Не могу реально сбросить сокет TCP клиента. Как?
От: Аноним  
Дата: 05.05.12 13:35
Оценка:
кривой клиент. после успешного close сокета не будет.
если вылазит ошибка повторное использование сокета,
после того как ты его якобы убил и заново подключаешься
значит ты его не убил да еще и заново в тот же сокет лезешь, нигде не обнуляешь
юзаный сокет. может это и к лучшему, что сечас обнаружил, а то бы плодил
сокеты с каждым подключением.
Re[3]: Не могу реально сбросить сокет TCP клиента. Как?
От: Michael Chelnokov Украина  
Дата: 07.05.12 19:32
Оценка:
Здравствуйте, Dimonira, Вы писали:

D>Пробовал — не заработало.


Ну все равно убери bind, он только мешает установить подключение повторно.
А не заработало — значит ты сокет все-таки не закрываешь.
Re[8]: Не могу реально сбросить сокет TCP клиента. Как?
От: Dimonira  
Дата: 10.05.12 11:29
Оценка:
Здравствуйте, Аноним, Вы писали:

А>кривой клиент. после успешного close сокета не будет.

А>если вылазит ошибка повторное использование сокета,
А>после того как ты его якобы убил и заново подключаешься
А>значит ты его не убил да еще и заново в тот же сокет лезешь, нигде не обнуляешь
А>юзаный сокет. может это и к лучшему, что сечас обнаружил, а то бы плодил
А>сокеты с каждым подключением.
Я сокет убивал точно. А вот Винды его убивают "якобы".
Но я уже сделал без убивания сокета — только коннект убивается, точнее если коннект порвался, то он восстанавливается перед обменом.
Так что сокет живёт на всём протяжении жизни приложения.
Re[4]: Не могу реально сбросить сокет TCP клиента. Как?
От: Dimonira  
Дата: 10.05.12 11:30
Оценка:
Здравствуйте, Michael Chelnokov, Вы писали:

MC>Ну все равно убери bind, он только мешает установить подключение повторно.

MC>А не заработало — значит ты сокет все-таки не закрываешь.

Мне bind нужен для выбора конкретного сетевого адаптера.
Re[5]: Не могу реально сбросить сокет TCP клиента. Как?
От: Michael Chelnokov Украина  
Дата: 10.05.12 11:49
Оценка:
Здравствуйте, Dimonira, Вы писали:

D>Мне bind нужен для выбора конкретного сетевого адаптера.


Тогда вызывай bind, но указывай порт 0.
Re[6]: Не могу реально сбросить сокет TCP клиента. Как?
От: Dimonira  
Дата: 12.05.12 07:19
Оценка:
Здравствуйте, Michael Chelnokov, Вы писали:

MC>Тогда вызывай bind, но указывай порт 0.


Удалённый девайс (сервер) ждёт подключения с конкретного порта.
Re: Не могу реально сбросить сокет TCP клиента. Как?
От: ofercinn Россия http:/o-fercinn.livejournal.com
Дата: 17.05.13 11:20
Оценка:
Мне помогло выставить для сокета: LingerState = new LingerOption(false, 0) (именно false)
Закрываю так:
if (Socket.Connected)
{
Socket.Shutdown(SocketShutdown.Both);
}
Socket.Close();
Socket = null;
Re[7]: Не могу реально сбросить сокет TCP клиента. Как?
От: Mr.Delphist  
Дата: 17.05.13 12:18
Оценка:
Здравствуйте, Dimonira, Вы писали:

D>Здравствуйте, Michael Chelnokov, Вы писали:


MC>>Тогда вызывай bind, но указывай порт 0.


D>Удалённый девайс (сервер) ждёт подключения с конкретного порта.


Т.е. при подключении сервак смотрит IP/port подключившейся стороны и ежели чего не совпало — дропает коннект? Я правильно понимаю?
Re: Не могу реально сбросить сокет TCP клиента. Как?
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 20.05.13 09:12
Оценка:
Здравствуйте, Dimonira, Вы писали:

D>До сих пор не приходилось использовать TCP явно, использовал UDP и сам разруливал обмен между хостом и железякой.

Сессия на той стороне рвётся? Что в ваершарке видно? Для начал попробуй только один connect/disconnect поделать.
Sic luceat lux!
Re[9]: Не могу реально сбросить сокет TCP клиента. Как?
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 20.05.13 14:36
Оценка:
Здравствуйте, Dimonira, Вы писали:

D>Здравствуйте, Аноним, Вы писали:


А>>кривой клиент. после успешного close сокета не будет.

А>>если вылазит ошибка повторное использование сокета,
А>>после того как ты его якобы убил и заново подключаешься
А>>значит ты его не убил да еще и заново в тот же сокет лезешь, нигде не обнуляешь
А>>юзаный сокет. может это и к лучшему, что сечас обнаружил, а то бы плодил
А>>сокеты с каждым подключением.
D>Я сокет убивал точно. А вот Винды его убивают "якобы".
D>Но я уже сделал без убивания сокета — только коннект убивается, точнее если коннект порвался, то он восстанавливается перед обменом.
D>Так что сокет живёт на всём протяжении жизни приложения.
Ты уверен, что правильно понял как это всё работает?
Sic luceat lux!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.