До сих пор не приходилось использовать 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());
}
}