TCPClient只会连接一次。

3

我正在开发一个通过TCP与机器通信的应用程序。我的问题是,虽然我可以成功连接并正常通信,但一旦断开连接再尝试重新连接时,只会出现错误。

我在代码表单中的代码如下:

   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"));
        }
    }

这段代码涉及到 Codenet dll 中的连接和断开连接功能。

     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();
    }

我得到的错误是:
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

即使IP地址不同,它也不会执行tcpclnt.Connect(ip,Port)操作。似乎仍有一些内容处于打开状态,但是由于机器已经断开连接,我不知道是什么。我知道这一点,因为我在其中发送了UDP,以发送出多少个连接,并且我可以看到它们增加和减少。
我尝试过“public string Connect_TCP(string ip, int Port)”并在调用表单之前创建了一个新的dll实例,但那也没有起作用。
有任何想法我做错了什么。
感谢到目前为止的答案,但仍然存在问题。我阅读了MSDN并制作了一个测试应用程序,现在我可以看到问题所在,但目前还无法修复它。我将Client声明为静态全局变量,以便我可以从connect和disconnect按钮获取它。我认为这总是创建新实例,并且我永远不会关闭它们。第一次循环时,机器告诉我已经断开连接,但应用程序从未重新连接。在调试模式下,它会在client.Connect(ipEndPoint)处崩溃;随后出现“InvalidOperationException was unhandled”,然后是“一旦套接字已断开连接,则只能以异步方式重新连接,并且仅限于不同的EndPoint。必须在完成操作之前保持线程上调用BeginConnect。”
我想我需要将此Client放入btn_connect_click并从内部获取指针,然后如何操作呢?
完整的代码是:
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");

           }




    }


} 

你得到的错误信息是什么?确切地说是什么?逐字逐句的吗?不是改述、拼写错误、压缩、精简等等。 - user207421
错误.....在 System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port) 在 comms_engine.Codenet.Connect_TCP(String ip, Int32 Port) 位于 C:\a\code\g_com_test_1\comms_engine\Codenet.cs 的第 37 行 在 comms_test.CommTester.btn_connect_Click(Object sender, EventArgs e) 位于 C:\a\code\g_com_test_1\dll_test\ethernet.cs 的第 98 行 - user3884423
1
@user3884423 在你的问题中出现了错误!它在这里是不可读的,可能会对未来的读者不可见! - zoska
并且要按照要求包括 message。不要使用“...”或扭曲的译文,只需复制并粘贴实际的消息即可。 - user207421
3个回答

5

感谢您的帮助,我现在已经解决了这个问题。请参考以下完整代码片段,只需在连接按钮中添加client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);即可使其正常工作。我的测试显示,它可以连接和断开连接,并允许重新连接或连接到另一台机器。在您的帮助下,我花了两天时间才解决了这个问题。

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());

5
一旦你断开一个TCP socket,它就无法重新连接。你必须释放该socket并创建一个新的socket。这不仅限于.NET TCPClient类,这是所有socket API工作的一般规则(WinSock,BSD等)。
唯一例外的是WinSock2特定的DisconnectEx()函数,它有一个TF_REUSE_SOCKET标志,允许ConnectEx()(和AcceptEx())重用现有的SOCKET而不需要创建新的socket。但这在你的情况下不适用。
在大多数情况下,一旦你断开一个socket,你必须从头开始创建一个新的socket。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接