Reputation: 594
I am building an app that communicates to a machine via TCP. The issue I have is that I can connect and all is well but once I disconnect and then try and reconnect all I get is error
The code I have in the form is
private void btn_connect_Click(object sender, EventArgs e)
{
try
{
Log(LogMsgType.Normal, String.Format("Connected on {0}\n", DateTime.Now));
string ip = (txt_ipadd_1.Text + "." + txt_ipadd_2.Text + "." + txt_ipadd_3.Text + "." + txt_ipadd_4.Text);
Log(LogMsgType.Normal, String.Format("Connecting to IP address " + ip + " Port # " + txt_port.Text +"\n"));
string con = Codenet.Connect_TCP(ip, Convert.ToInt32(txt_port.Text)); //connect to this one
Log(LogMsgType.Normal, String.Format(con + "\n"));
toolStripStatusLabel1.Text = "Connected";
btn_connect.Visible = false;
btn_disconnect.Visible = true;
ip = "";
}
catch (Exception d)
{
Log(LogMsgType.Error, String.Format("Error..... " + d.StackTrace +"\n"));
}
}
Which goes over to code from the Codenet dll which does the connection and disconnection
public static string Connect_TCP(string ip, int Port)
{
tcpclnt.Connect(ip, Port);
connection_type = "TCP";
return "Connected OK ";
}
public static void DisConnect_TCP()
{
tcpclnt.GetStream().Close();
tcpclnt.Close();
}
The error I get is:
Error..... at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port) at
comms_engine.Codenet.Connect_TCP(String ip, Int32 Port) in C:\a\code\g_com_test_1\comms_engine\Codenet.cs:line 37 at
comms_test.CommTester.btn_connect_Click(Object sender, EventArgs e) in C:\a\code\g_com_test_1\dll_test\ethernet.cs:line 98
It will not perform the tcpclnt.Connect(ip, Port) even if the ip is different. It seems that something is still open but what I do not know as the machine has disconnected. I know that as I have UDP in it sending out how many connections it has and I can see then increase and decrease OK.
I tried "public string Connect_TCP(string ip, int Port)" and making a NEW instance of the dll befor calling the connect from the form but that did not work either.
Thanks for answers so far but still I have an issue. I read the MSDN and made a test app and I can now see what is wrong but am clueless on how to fix it at the moment. I am declaring the Client as Static global so I can get it from the connect and disconnect button. I think thta this always creates new instances and I never close them. First time round the machine tells me it has diconnected bu t the app never reconnects In debug mode it falls over at client.Connect(ipEndPoint); with "InvalidOperationException was unhandled" followed by "Once the socket has been disconnected, you can only reconnect again asynchronously, and only to a different EndPoint. BeginConnect must be called on a thread that won't exit until the operation has been completed."
I guess I need to put this Client inside the btn_connect_click and get a pointer to it from inside the disconnect but how?
The full code is
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.IO.Ports;
using System.Diagnostics;
using System.Threading;
namespace TCP_Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
static Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private void btn_connect_Click(object sender, EventArgs e)
{
string ip = (txt_ipadd_1.Text + "." + txt_ipadd_2.Text + "." + txt_ipadd_3.Text + "." + txt_ipadd_4.Text);
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = IPAddress.Parse(ip);
IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, Convert.ToInt32(txt_port.Text));
// Connect the socket to the remote end point.
client.Connect(ipEndPoint);
rchTxtBx_output.AppendText("connected to " + ipEndPoint + "\n\r");
}
private void btn_disconnect_Click(object sender, EventArgs e)
{
client.Shutdown(SocketShutdown.Both);
client.Disconnect(true);
if (client.Connected)
rchTxtBx_output.AppendText("We're still connnected \n\r");
else
rchTxtBx_output.AppendText("We're disconnected \n\r");
}
}
}
Upvotes: 3
Views: 4910
Reputation: 594
Thanks for the help I have now solved it. See above for full code but below is teh snippet that makes it work. Just add client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); inside the connect button. My testing now shows it connects and disconnects and allows reconnect or connect to anothe machine. Only took me two man days to work that out with your help.
static Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private void btn_connect_Click(object sender, EventArgs e)
{
if (client.Connected)
{
client.Shutdown(SocketShutdown.Both);
client.Disconnect(true);
client.Close();
}
else
{
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
string ip = (txt_ipadd_1.Text + "." + txt_ipadd_2.Text + "." + txt_ipadd_3.Text + "." + txt_ipadd_4.Text);
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
Upvotes: 5
Reputation: 1377
When the connection is closed, underlying socket(TCPClient.Client returns socket) needs to be set for reuse . Use the Socket.Disconnect(true) instead of close to reconnect on the socket. Check the link: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.disconnect(v=vs.90).aspx
Upvotes: 1
Reputation: 596332
Once you disconnect a TCP socket, it cannot be reconnected. You have to release the socket and create a new one. This is not just limited to the .NET TCPClient
class, this is how all socket APIs work in general (WinSock, BSD, etc).
The exception to this rule is the WinSock2-specific DisconnectEx()
function, which has a TF_REUSE_SOCKET
flag that allows ConnectEx()
(and AcceptEx()
) to re-use an existing SOCKET
instead of requiring a new socket to be created. But that does not apply in your situation.
In the majority of cases, once you disconnect a socket, you have to create a new socket from scratch.
Upvotes: 5