gpt4 book ai didi

c# - SocketException 一个现有的连接被远程主机强行关闭

转载 作者:行者123 更新时间:2023-11-30 17:04:11 24 4
gpt4 key购买 nike

我决定看看网络消息传递等,我的第一个调用端口是 UDP。

我遇到的问题是当我尝试发送消息时。我正在尝试在特定端口上访问 IP,但应用程序错误并出现错误

“SocketException 一个现有的连接被远程主机强行关闭”。

这是代码。

    User ME = new User();
UdpClient MyUDPClient;

private void Form1_Load(object sender, EventArgs e)
{
ME.Username = Environment.UserName;
}

private void StartUDP_Click(object sender, EventArgs e)
{
CreateUDPClient();
}

private void CreateUDPClient()
{
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
int Port = int.Parse(txt_Port.Text);
ME.UserIP = new IPEndPoint(ip, Port);
break;
}
}

MyUDPClient = new UdpClient(ME.UserIP);
UDPListening();
}


public void UDPListening()
{
MyUDPClient.BeginReceive(ReceiveMessage, new object());
}

private void ReceiveMessage(IAsyncResult IAR)
{
byte[] B = MyUDPClient.EndReceive(IAR, ref ME.UserIP);
ProcessMSG(Encoding.ASCII.GetString(B));
UDPListening();
}

delegate void MessageDelegate(String MSG);

public void ProcessMSG(String M)
{
if (this.lbl_Messages.InvokeRequired)
{
MessageDelegate Del = new MessageDelegate(ProcessMSG);
this.Invoke(Del, M);
}
else
{
lbl_Messages.Text = M;
}
}



//Send Data to Another version of this program elsewhere.

private void btn_SendtoTarget_Click(object sender, EventArgs e)
{
IPEndPoint TargetIP = new IPEndPoint(IPAddress.Parse(txt_Send2IP.Text),int.Parse(txt_Send2Port.Text));
byte[] Message = Encoding.ASCII.GetBytes("TEST TEST TEST");

MyUDPClient.Send(Message, Message.Length, TargetIP);
}


}

谢谢您的帮助。

不确定这是否有帮助,但...

应用程序在设置为监听的机器上运行,位于 192.168.0.25:5555

发送正在尝试发送到机器 192.168.0.50:10001



通过进一步阅读,我认为我的具体问题是创建 UDPclient 对象。它被创建,然后在 ip 192.168.0.25:5555 上监听。当我尝试发送消息时,我尝试使用相同的 UDPClient 但发送到新 IP。我觉得这不是正确的程序,因此它试图关闭以前的程序???我相信有人可以证实这一点。所以这向我建议,要拥有有效的 UDP 网络(UP 和 Down),我需要有一个 UDPclient 接收和第二个 UDP 才能发送(这对于我想要命中的每个目标地址都是动态的)。再一次,这都是猜测工作,如果我有这个,我希望有人可以提供一些指示。

最佳答案

上面的几个问题。

  • 不要使用 ME在 C# 中,它是 this . Me是VB。如果使用 C#,上面的代码将无法编译,因为您遗漏了 User()。您定义为 ME 的类.我不知道你为什么认为你需要它,因为它似乎只有 UserIPUserName . IP 是 Socket 的一部分,所以如果你需要它,你应该使用它:IPAddress ip = IPAddress.Parse(socket.RemoteEndPoint);UserName可以成为全局字符串变量 - 不必是类的一部分。
    也许我很挑剔,但我没有看到在 User() 中需要在哪里拥有这些变量中的任何一个。像这样的对象,只是把事情搞砸了,对我来说,试图破译代码。
  • 始终定义您的 Socket ,连接到它,然后执行您的.Send() .您错过了单击按钮的前两个步骤 - 您只需执行 .Send() . UdpClient不是 Socket ,我认为最好将其作为 Socket并稍后定义您的连接类型。我想你可能是对的,你正在尝试做你的 .Send()使用 UdpClient你定义为你的听众。不要为您的发送和收听使用相同的对象!通常你会,但每个事件都有 2 个不同的地址和端口。
  • 不要使用 foreach在您的 CreateUDPClient()获取您的IPAddress的功能分配给您的IPEndPoint .你已经知道你的IP了。直接赋值。这是浪费处理时间。
    IPAddress ip = IPAddress.Parse("192.168.0.25");
    IPEndPoint endPoint = new IPEndPoint(ip, port);

  • 如果你只有主机名,你会这样做:
        string hostName = "MyComputerName";
    int port = 5555; // or int.Parse(txt_Port.Text); ???
    IPHostEntry hostEntry = Dns.GetHostAddresses(hostName);
    IPEndPoint endPoint = new IPEndPoint(hostEntry[0], port);

    不要使用 Dns.GetHostEntry() -- 如果该名称没有反向查找 (PTR) 记录,它将失败。使用 Dns.GetHostAddresses() .而且我不知道为什么您认为您需要循环,除非您具有与您提供的相同主机名的 IPv6 地址。如果没有,请使用 [0] - 如果不使用 IPv6,它应该是您将使用的第一个也是唯一一个返回的 IP。但同样,由于您已经拥有 IP,只需将其插入 - 无需进行查找。它可以帮助您消除 Dns.GetHostName() , 也一样 - 只需使用 192.168.0.25 .

    供您引用,MSDN 在这里有一个同步套接字发送/接收的过程:
    https://msdn.microsoft.com/en-us/library/kb5kfec7(v=vs.110).aspx

    和异步套接字在这里发送/接收:
    http://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx

    由于我鄙视仅链接的答案,而您似乎正在使用 Send() 混合这两种方法和 EndReceive() ,分别到上面的链接,我将努力简洁地描述其内容并帮助修复您的代码:

    基本上他们说使用 StateObject类,而不是全局变量 MyUDPClient你有:
    public class StateObject
    {
    public byte[] buffer = new byte[1024];
    public Socket workSocket;
    public StringBuilder sb = new StringBuilder();
    }

    您将创建一个套接字并将其添加到其中。缓冲区用作告诉 Receive() 的一种方式或 EndReceive()您想一次从响应中读回的 block 的大小,以及 sb将作为响应的占位符。

    看起来你在这里有很多事情要做:a SendtoTarget_Click从表格和您的听众中进行一次性测试。您的 SendtoTarget按钮进行同步发送,您的 StartUDP_Click()进行异步接收。

    你会改变你的 SendtoTarget_Click()事件是这样的(之前从未定义过您的套接字,并且您必须在发送之前连接到它):
    private void btn_SendtoTarget_Click(object sender, EventArgs e)
    {
    IPEndPoint TargetIP = new IPEndPoint(IPAddress.Parse(txt_Send2IP.Text),int.Parse(txt_Send2Port.Text));
    byte[] Message = Encoding.ASCII.GetBytes("TEST TEST TEST");

    // Create a UDP socket.
    Socket sender = new Socket(AddressFamily.InterNetwork,
    SocketType.Stream, ProtocolType.Udp);

    try
    {
    // Connect to the remote endpoint.
    sender.Connect(TargetIP);

    // Send message -- already contains the endpoint so no need to
    // specify again
    sender.Send(Message, 0, Message.Length, SocketFlags.None);

    sender.Close();
    }
    catch (Exception)
    {
    // do something here...
    }
    }

    对于您的听众,您可以这样做:
    private void CreateUDPClient()
    {
    IPEndPoint TargetIP = new IPEndPoint(IPAddress.Parse("192.168.0.25"), 5555);

    // Create a UDP socket.
    Socket receiver = new Socket(AddressFamily.InterNetwork,
    SocketType.Stream, ProtocolType.Udp);

    try {

    // Create the state object.
    StateObject state = new StateObject();
    state.workSocket = receiver;

    // Begin receiving the data from the remote device.
    receiver.BeginReceive(state.buffer, 0, 256, 0,
    new AsyncCallback(ReceiveMessage), state);

    } catch (Exception e) {
    Console.WriteLine(e.ToString());
    }
    }

    你的函数叫做 ReceiveMessage() , 做这个:
    private void ReceiveMessage(IAsyncResult IAR)
    {
    string response = String.Empty;
    try {

    // Retrieve the state object and the client socket
    // from the asynchronous state object.
    StateObject state = (StateObject) IAR.AsyncState;
    Socket client = state.workSocket;

    // Read data from the remote device.
    int bytesRead = client.EndReceive(IAR);

    if (bytesRead > 0) {
    // There might be more data, so store the data received so far.
    state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

    // Get the rest of the data.
    client.BeginReceive(state.buffer, 0, 256, 0,
    new AsyncCallback(ReceiveCallback), state);
    } else {
    // All the data has arrived; put it in response.
    if (state.sb.Length > 1) {
    response = state.sb.ToString();
    }
    // Signal that all bytes have been received.
    client.Close();
    }
    ProcessMSG(response);
    CreateUDPClient(); // personally, I would re-create than calling BeginReceive directly

    } catch (Exception e) {
    Console.WriteLine(e.ToString());
    }
    }

    我已尽我所能以一种可行的方式将您的代码与 MSDN 集成。您也许可以将该套接字分配给 StateObject并调用 BeginReceive()再说一遍 - 不确定。但不要重复使用 UdpClient那样的对象。使用 StateObject像 MSDN 上的类,仅将其用作您的听众。

    关于c# - SocketException 一个现有的连接被远程主机强行关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17790612/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com