[Help] Socket closes even though it should stay open?

Discussion in 'Plugin Development' started by BlurredVision, Feb 8, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    BlurredVision

    Hey all!
    I'm currently working on a successor (or so I hope) to Minecraft MobileAdmin. However, I've run into an issue. So, when the plugin is enabled it runs the WaitForAccept() void which can be shown here:
    Code:
    public void WaitForAccept()
        {
            final DataReader reader = new DataReader();
         
            getServer().getScheduler().runTaskAsynchronously(this, new Runnable()
            {
                @Override
                public void run()
                {
                    try
                    {
                        if (Accepted.equals(false))
                        {
                            cs = ss.accept();
                            Accepted = true;
                            Log("A client connected with IP: " + cs.getRemoteSocketAddress().toString() + ". Asking for authentication.", "info");
                        }
                        else
                        {
                         
                        }
                     
                        String RemotePasswordPlainText = reader.Read(br, cs);
                        String RemotePasswordHash = DigestUtils.sha512Hex(RemotePasswordPlainText);
                     
                        if (RemotePasswordHash.equals(PasswordHash))
                        {
                            Log("Client connected with correct password.", "info");
                         
                            EnableOrDisableListener("enable");
                            ListenForData();
                         
                            //Make sure that the client socket hasen't closed... this should solve a lot of problems... I hope
                            while (true)
                            {
                                if (cs.isClosed())
                                {
                                    Accepted = false;
                                    EnableOrDisableListener("disable");
                                    run();
                                    break;
                                }
                                else
                                {
     
                                }
                            }
                        }
                        else
                        {
                            Log("Client connected with bad password hash: " + RemotePasswordHash, "warning");
                            RemotePasswordPlainText = null;
                            RemotePasswordHash = null;
                         
                            run();
                        }
                     
                    }
                    catch (IOException e)
                    {
                        Log("A severe error occured while a client was connecting or the client disconnected without entering the proper password.", "warning");
                     
                        cs = null;
                        Accepted = false;
                             
                        run();
                    }
                }
             
            });
        }
    ("ss" is a ServerSocket and "cs" is just a Socket. All the other functions are irrelevant.)


    When a client connects (I'm currently connecting via a C# client because I don't want to work on the Android app at the moment.) everything works fine. It will then ask for authentication. So, I need to send a password via TCP which I'm doing in here:
    Code:
    NetworkStream ns = client.GetStream();
    StreamWriter sw = new StreamWriter(ns);
    sw.WriteLine(textBox1.Text);
    sw.Flush();
    ("client" is just a TcpClient.)

    However, right after I send either the correct or incorrect password, I get an error afterwards saying the socket is closed. In this case, I sent a bad password:

    Code:
    17:06:18 [WARNING] [MonitorMe] Client connected with bad password hash: d6a51082
    b3f8313aa21aa29833dd79a6771f3b7eaab3e76b1de094d8e6e943977b8f546f5b9c24cc2cb2dc5f
    fe44851784182a9ebab16c74cb197423ca8f6c95
    17:06:18 [SEVERE] [MonitorMe] A severe error occured while a client was connecti
    ng.
    17:06:18 [SEVERE] java.net.SocketException: Socket is closed
    17:06:18 [SEVERE]      at java.net.Socket.getInputStream(Unknown Source)
    17:06:18 [SEVERE]      at com.github.ss111.DataReader.Read(DataReader.java:11)
    17:06:18 [SEVERE]      at com.github.ss111.MonitorMeCore$1.run(MonitorMeCore.ja
    va:142)
    17:06:18 [SEVERE]      at com.github.ss111.MonitorMeCore$1.run(MonitorMeCore.ja
    va:174)
    17:06:18 [SEVERE]      at org.bukkit.craftbukkit.v1_4_R1.scheduler.CraftTask.ru
    n(CraftTask.java:53)
    17:06:18 [SEVERE]      at org.bukkit.craftbukkit.v1_4_R1.scheduler.CraftAsyncTa
    sk.run(CraftAsyncTask.java:53)
    17:06:18 [SEVERE]      at java.util.concurrent.ThreadPoolExecutor.runWorker(Unk
    nown Source)
    17:06:18 [SEVERE]      at java.util.concurrent.ThreadPoolExecutor$Worker.run(Un
    known Source)
    17:06:18 [SEVERE]      at java.lang.Thread.run(Unknown Source)

    Here is my DataReader class which you will probably need to see:
    Code:
    package com.github.ss111;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.Socket;
     
    public class DataReader
    {
        public String Read(BufferedReader reader, Socket clientSocket) throws IOException
        {
            reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            String data = reader.readLine();
            reader.close();
            reader = null;
            return data;
        }
    }
    
    If anybody can spot my error, that would be great. If not, oh well, because this kind of isn't the place to be asking about networking :p
    If you need to see any more source, it's on GitHub at https://github.com/SS111/MonitorMe
    Thanks a ton.

    EDIT: On a side note, I'm starting to realize that if I use UDP packets instead of TCP, this would be a lot easier. If they sent a prefixed packet with the right password, add them to a HashMap and every time one of my events is fired, loop through the HashMap and send a prefixed packet with my data to each person in the HashMap. Would that be a better approach?
     
  2. Offline

    Technius

    If it's some sort of admin plugin, I suggest using TCP for security.

    I think you should try writing the client in Java first(on your computer).

    I have a successful example of a plugin similar to what you're writing right now, and you can go check it out. I plan on releasing the source code soon.

    Edit:

    Your server socket should have its own thread, and new threads should be created for each client socket. I recommend putting the server thread and the client thread in separate classes. The server socket thread should look like this:

    Code:
    ServerSocket ss = //Your server socket
    while(running)//You may want to set running to false when you're plugin is disabled
    {
        Socket cs = null;
        try{
            cs = ss.accept();
        }
        catch(IOException ioe){
            //You can put error code in here if you want
        }
        if(cs == null)continue; //Failed to accept socket
        ClientThread ct = new ClientThread(cs); //Your own class
        //ClientThread should be a subclass of Thread
        ct.start();
    }
    
     
Thread Status:
Not open for further replies.

Share This Page