Не могу реально сбросить сокет 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());
    }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.