Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java &引用;现有连接被远程主机强制关闭;接收时在UDP服务器中_Java_C#_Android_Udp_Datagram - Fatal编程技术网

Java &引用;现有连接被远程主机强制关闭;接收时在UDP服务器中

Java &引用;现有连接被远程主机强制关闭;接收时在UDP服务器中,java,c#,android,udp,datagram,Java,C#,Android,Udp,Datagram,因此,在与线程斗争之后,我成功地在客户机和服务器之间建立了一个流。我的客户端是一个Java Android Studio应用程序,服务器是一个C#控制台 我希望能够启动流并在客户端单击按钮时停止它。然后随时重新启动,停止,重新启动,停止。。等等 我很喜欢start,但有时在第一次停止后,有时在第一次重新启动时,有时在第二次重新启动时,会弹出一个现有连接被远程主机强制关闭 在PacketReceived=serverSocket.Receive(ref-client)上 我不知道为什么,我正在努力

因此,在与线程斗争之后,我成功地在客户机和服务器之间建立了一个流。我的客户端是一个Java Android Studio应用程序,服务器是一个C#控制台

我希望能够启动流并在客户端单击按钮时停止它。然后随时重新启动,停止,重新启动,停止。。等等

我很喜欢start,但有时在第一次停止后,有时在第一次重新启动时,有时在第二次重新启动时,会弹出
一个现有连接被远程主机强制关闭

PacketReceived=serverSocket.Receive(ref-client)上

我不知道为什么,我正在努力调试它,但没有效率。我的逻辑或语法有什么问题

C#服务器代码:

class UdpServer
{
    static void Main(string[] args)
    {
        // variables declaration block
        byte[] PacketReceived = new byte[1024];
        var MyToken = new CancellationTokenSource(); //create token for the thread cancel
        UdpClient serverSocket = new UdpClient(15000);
        string PacketMessage = "";

        int i = 0;
        while (true) // this while for keeping the server "listening"
        {
            Console.WriteLine("Waiting for a UDP client...");                                   // display stuff
            IPEndPoint client = new IPEndPoint(IPAddress.Any, 0);                               // prepare
            PacketReceived = serverSocket.Receive(ref client);                                  // receive packet
            PacketMessage = Encoding.ASCII.GetString(PacketReceived, 0, PacketReceived.Length); // get string from packet
            Console.WriteLine("Response from " + client.Address);                               // display stuff
            Console.WriteLine("Message " + i++ + ": " + PacketMessage + "\n");                  // display received string

            if (PacketMessage == "Start")
            {
                MyToken = new CancellationTokenSource(); // for the restart, need a new token
                Task.Run(() => Start(ref serverSocket, ref client), MyToken.Token); //start method on another thread
            }

            if (PacketMessage == "Stop")
            {
                MyToken.Cancel();
            }
        }
    }

    static public void Start(ref UdpClient serverSocket, ref IPEndPoint client)
    {
        int i = 0;
        byte[] dataToSend;
        while (true)
        {
            try
            {
                dataToSend = Encoding.ASCII.GetBytes(i.ToString());
                serverSocket.Send(dataToSend, dataToSend.Length, client);
                i++;
            }
            catch (Exception e)
            { }
        }
    }
}
Java客户端代码:

public class MainActivity extends AppCompatActivity {

    String message;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button StrtBtn = (Button) findViewById(R.id.StartButton);
        Button StpBtn = (Button) findViewById(R.id.StopButton);

        // Start Button Click
        StrtBtn.setOnClickListener(
                new Button.OnClickListener() {
                    public void onClick(View v) {
                        message = "Start";
                        SendUdpMsg();
                    }
                }
        );

        // Stop Button Click
        StpBtn.setOnClickListener(
                new Button.OnClickListener() {
                    public void onClick(View v) {
                        message = "Stop";

                    }
                }
        );
    }

    public void SendUdpMsg()
    {
        Thread networkThread = new Thread() {

            // No local Host 127.0.0.1 in Android
            String host = "192.168.200.3"; // Server's IP
            int port = 15000;
            DatagramSocket dsocket = null;

            public void run() {
                try {
                    // Get the Internet address of the specified host
                    InetAddress address = InetAddress.getByName(host);

                    // wrap a packet
                    DatagramPacket packetToSend = new DatagramPacket(
                            message.getBytes(),
                            message.length(),
                            address, port);

                    // Create a datagram socket, send the packet through it.
                    dsocket = new DatagramSocket();
                    dsocket.send(packetToSend);

                    // Here, I am receiving the response
                    byte[] buffer = new byte[65535]; // prepare
                    DatagramPacket packetReceived = new DatagramPacket(buffer, buffer.length); // prepare

                    while (true)
                    {
                        if(message == "Start")
                        {
                            dsocket.receive(packetReceived); // receive packet
                            byte[] buff = packetReceived.getData(); // convert packet to byte[]
                            final String Response = new String(buffer, 0, packetReceived.getLength());

                            runOnUiThread(new Runnable()
                            {
                                @Override
                                public void run()
                                {
                                    // this is executed on the main (UI) thread
                                    final TextView TextOne = (TextView)findViewById(R.id.StatusText);
                                    TextOne.setText(Response);
                                }
                            });
                        }
                        else
                        {
                            // wrap a packet to send the Stop
                            packetToSend = new DatagramPacket(
                                    message.getBytes(),
                                    message.length(),
                                    address, port);

                            // Create a datagram socket, send the packet through it.
                            dsocket = new DatagramSocket();
                            dsocket.send(packetToSend);
                            break; // break the whole thread
                        }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        networkThread.start();
    }
}

如果没有完整的代码示例(特别是要测试的真实客户端),很难诊断这样的错误。但是,您的代码中至少有两个明显的问题,如果出现错误,这两个问题中的任何一个都可能导致类似的错误:

  • 您通过引用
    Start()
    方法传递
    serverSocket
    client
    。不需要这样做,通过引用传递
    客户端
    会引入在错误时间修改
    客户端
    变量的可能性,导致尝试发送到
    任何
    ,或导致非法引用(如果在x64体系结构上运行)。这是最基本的问题,即在没有某种同步的情况下在线程之间共享变量(至少使用
    volatile
    )会带来它自己的问题集合(并且在客户端代码中存在相同的线程安全问题,因为使用
    message
    字段作为线程之间的信号的方式)
  • 您从未使用取消令牌停止线程。将令牌传递给
    Task.Run()
    方法只允许
    Task
    类正确处理可能发生的任何取消异常。但是,在适当的时候抛出该异常取决于您自己的代码。您永远不会这样做,这意味着在从客户端发送多条消息之后,您将遇到多个线程试图发送到客户端
  • 我赌的是上面的第二个。您的客户端似乎将端口选择权留给主机,因此每次发送“Start”方法时,客户端端口都可能发生更改。关闭以前使用的套接字后,该端口无效,如果远程套接字尝试发送到该端口,则会导致远程套接字出错。当然,您的服务器(远程套接字)将尝试发送到该端口,从而在套接字上导致错误,该错误可由
    Receive()
    方法引发(而不是您可能期望的
    send()
    方法)


    顺便说一句,无论如何,您应该避免将线程池用于长时间运行的任务。至少,如果要使用
    Task.Run()
    启动线程,请通过传递适当的值向.NET指示任务是长期运行的: