【问题标题】:Bind sending socket绑定发送套接字
【发布时间】:2017-01-18 20:56:12
【问题描述】:

我有一个带有两个按钮的表单,首先是开始监听套接字,并显示带有地址的消息框,从该地址发送消息。第二个按钮用于将消息发送到我按下收听按钮时收听的地址。我正在尝试绑定发送的套接字。例如,我想从端口 50000 发送它。我正在使用Bind 方法,但它只在第一次工作,而不是异常成为,该地址通常只能使用一次,我需要再次重新打开我的表单。我怎么解决这个问题 ?这是我的发送代码:

    private void button2_Click(object sender, EventArgs e)
    {
        string local_host = System.Net.Dns.GetHostName();
        string local_ip_address = Dns.GetHostByName(local_host).AddressList[0].ToString();
        IPEndPoint send_point = new IPEndPoint(IPAddress.Parse(local_ip_address), 50000);

        Socket send_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPEndPoint connected_point = new IPEndPoint(IPAddress.Parse(textBoxIPListen.Text), 
                                                    Convert.ToInt32(textBoxPortListen.Text));
        try
        {
            send_socket.Bind(send_point);
            send_socket.Connect(connected_point);
            byte[] data = Encoding.Unicode.GetBytes("TestTest");
            send_socket.Send(data);
            send_socket.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

【问题讨论】:

    标签: c# winforms sockets


    【解决方案1】:

    而不是在 Try 部分调用 send_socket.Close() 我宁愿在 finally 块中调用它,以确保即使引发异常也会关闭套接字。否则,如果出现任何问题,您可能会保持套接字打开。

        try
        {
            send_socket.Bind(send_point);
            send_socket.Connect(connected_point);
            byte[] data = Encoding.Unicode.GetBytes("TestTest");
            send_socket.Send(data);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
        finally
        {
            send_socket.Close();
        }
    

    【讨论】:

    • 感谢您的建议!你说得对,反正最好关闭它。但不幸的是,我无论如何只能第一次发送我的消息,而不是异常变成反正:/
    【解决方案2】:

    Bind()Listen() 结合使用以将socket 绑定到指定的连接。基本上你可以Bind() socket 只监听特定的端口和地址,但要连接到另一个远程,你应该使用简单的Connect() 方法。

    正如文档中所说:https://msdn.microsoft.com/en-us/library/system.net.sockets.socket.bind(v=vs.110).aspx

    您必须先调用 Bind,然后才能调用 Listen 方法。除非您需要使用特定的本地端点,否则您无需在使用 Connect 方法之前调用 Bind。

    在你的情况下是什么意思?这意味着您正在尝试将来自(假设)127.0.0.1:5000 的数据包绑定到 127.0.0.1:4990。您当然可以这样做,但您必须记住,只要您想“重新绑定”,就必须从本地端点取消绑定此套接字。

    如果这是您的预期行为,那么我可以在关闭它后建议Dispose() 套接字。这将解除本地端点与套接字的绑定。示例:

    send_socket.Close();
    using ( send_socket ){ }
    

    编辑:

    如果它只在第一次工作我会推荐using套接字:

        try
        {
            using(send_socket) {
                send_socket.Bind(send_point);
                send_socket.Connect(connected_point);
                byte[] data = Encoding.Unicode.GetBytes("TestTest");
                send_socket.Send(data);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    

    或者您可以通过设置send_socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress, true); 选项将成员字段Socket send_socket 作为Form 类的成员来保持您的套接字实例绑定。

    【讨论】:

    • Dziekuje!但问题是老板希望我从指定地址发送消息。如果我只使用连接方法,它可以完美发送,但是系统会自动选择端口,这不是我老板想要的:/当我在连接之前使用绑定时,它是有效的,我可以使用我自己的地址,但是它只在第一次工作,然后成为例外。
    • 我尝试使用(send_socket),但不幸的是它没有帮助:/仍然有同样的例外。我会尝试第二个建议。所以完整的代码如下:try { send_socket.Bind(send_point); send_socket.Connect(connected_point); byte[] data = Encoding.Unicode.GetBytes("TestTest"); send_socket.Send(data); }
    • 奇怪,但第二个建议也没有帮助。我试着把它放在任何地方,但没有用。
    猜你喜欢
    • 2014-10-31
    • 1970-01-01
    • 2015-07-20
    • 2017-12-14
    • 2012-11-29
    • 2019-03-10
    • 2010-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多