TCPClient只能连接一次

时间:2014-09-18 08:54:32

标签: sockets tcp tcpclient

我正在构建一个通过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,它发送了多少连接,我可以看到然后增加和减少OK。

我尝试了“公共字符串Connect_TCP(字符串ip,int端口)”并创建了一个新的dll实例,用于从表单调用连接,但这也不起作用。

任何想法我做错了。

到目前为止,感谢您的回答,但我仍有问题。我阅读了MSDN并制作了一个测试应用程序,我现在可以看到出了什么问题,但我现在对如何修复它一无所知。我将Client声明为Static global,因此我可以通过connect和disconnect按钮获取它。我认为这总是创造新的实例,我永远不会关闭它们。第一次机器告诉我它已经连接到应用程序永远不会重新连接在调试模式下它会在客户端崩溃。连接(ipEndPoint); “InvalidOperationException未处理”后跟“一旦套接字断开连接,您只能异步重新连接,并且只能重新连接到另一个EndPoint。必须在一个线程上调用BeginConnect,该线程在操作完成之前不会退出。”

我想我需要将此客户端放在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");

           }




    }


} 

3 个答案:

答案 0 :(得分:5)

感谢我现在解决的帮助。请参阅上面的完整代码,但下面是使其工作的teh片段。只需添加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());

答案 1 :(得分:3)

断开TCP套接字后,无法重新连接。您必须释放套接字并创建一个新套接字。这不仅限于.NET TCPClient类,这就是所有套接字API的工作方式(WinSock,BSD等)。

此规则的例外是WinSock2特定的DisconnectEx()函数,该函数具有TF_REUSE_SOCKET标记,允许ConnectEx()(和AcceptEx())重用现有SOCKET而不是要求创建新套接字。但这并不适用于您的情况。

在大多数情况下,一旦断开套接字,就必须从头开始创建一个新套接字。

答案 2 :(得分:0)

当连接关闭时,需要设置底层套接字(TCPClient.Client返回套接字)以供重用。使用Socket.Disconnect(true)而不是关闭套接字上的重新连接。检查链接: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.disconnect(v=vs.90).aspx