Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.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 插座通道插座不读取数据_Java_Sockets_Nio - Fatal编程技术网

Java 插座通道插座不读取数据

Java 插座通道插座不读取数据,java,sockets,nio,Java,Sockets,Nio,这是我的密码。从TestServer,我试图通过outputstream发送数据,并从测试客户端接收数据。我使用的是SocketChannel,因为我需要客户端同时监听3个端口。目前,我只想从一个插座读取数据。但是,它似乎没有从服务器接收任何数据。对于KBThread的run方法,如果我取消对nodata println的注释,它将反复执行 TestServer.java import java.awt.event.KeyEvent; import java.awt.event.KeyListe

这是我的密码。从TestServer,我试图通过outputstream发送数据,并从测试客户端接收数据。我使用的是SocketChannel,因为我需要客户端同时监听3个端口。目前,我只想从一个插座读取数据。但是,它似乎没有从服务器接收任何数据。对于KBThread的run方法,如果我取消对nodata println的注释,它将反复执行

TestServer.java

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;


public class TestServer extends JPanel implements KeyListener, MouseListener, MouseMotionListener {

    private final int MAX_CLIENTS = 8;

    JPanel listenerPanel = new JPanel();
    JFrame listenerFrame = new JFrame();

    static DataOutputStream kbOut;
    static DataOutputStream mOut;
    static Socket dataSocket;

    public TestServer() {
        this.setFocusable(true);
        listenerPanel.addKeyListener(this);
        listenerPanel.addMouseMotionListener(this);

        listenerFrame.add(listenerPanel);
        listenerFrame.setSize(1376,808); // 10 more x, 40 more y.
        listenerFrame.setVisible(true);
        listenerFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        listenerPanel.requestFocusInWindow();

    }

    public static void main(String[] args) {

        new TestServer().startServer();
    }

    public void startServer() {

        final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(MAX_CLIENTS);

        Runnable serverTask = () -> {
            try {
                ServerSocket serverSocket = new ServerSocket(1111);
                System.out.println("Waiting for clients.");
                while (true) {
                    Socket clientSocket = serverSocket.accept();
                    clientProcessingPool.submit(new ClientTask(clientSocket));
                }
            } catch (IOException ex) {
                System.err.println("Error with client socket.");
            }
        };

        Thread serverThread = new Thread(serverTask);
        serverThread.start();
    }

    private class ClientTask implements Runnable {
        private final Socket clientSocket;

        private ClientTask(Socket clientSocket) {
            this.clientSocket = clientSocket;
        }

        @Override
        public void run() {

            try {
                String clientIP = clientSocket.getInetAddress().getHostAddress();
                System.out.println("Client connected from " + clientIP);

                Socket kbSocket = new Socket(clientIP, 1112);
                System.out.println("Keyboard socket connected to " + clientIP);
                kbOut = new DataOutputStream(kbSocket.getOutputStream());

                Socket mSocket = new Socket(clientIP, 1113);
                System.out.println("Mouse socket connected to " + clientIP);
                mOut = new DataOutputStream(mSocket.getOutputStream());

                //new TestServer().startKBServer(clientIP);
                //new TestServer().startMServer(clientIP);

                try {
                    clientSocket.close();
                } catch (IOException ex) {
                }
            } catch (IOException ex) {
                Logger.getLogger(TestServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public void startKBServer(String clientAddress) {

        Runnable kbTask = () -> {
            try {
                Socket kbSocket = new Socket(clientAddress, 1112);
                System.out.println("Keyboard socket connected to " + clientAddress);
                new KBTask(kbSocket);

            } catch (IOException ex) {
                System.out.println("Error Calling Back " + clientAddress);
            }
        };

        Thread kbThread = new Thread(kbTask);
        kbThread.start();
    }

    private class KBTask implements Runnable {
        private final Socket kbSocket;

        private KBTask(Socket kbSocket) {
            this.kbSocket = kbSocket;
        }

        @Override
        public void run() {
            try {
                kbOut = new DataOutputStream(kbSocket.getOutputStream());
            } catch (IOException ex) {
                Logger.getLogger(TestServer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    @Override
    public void keyPressed(KeyEvent ke) {
        try {
            int key = ke.getKeyCode();

            System.out.println("Key Pressed: " + key);

            kbOut.writeInt(key);
            kbOut.flush();

        } catch (IOException ex) {
            System.out.println("Error writing key data to server");
        }
    }

    @Override
    public void keyReleased(KeyEvent ke) {
        try {
            int key = ke.getKeyCode();

            System.out.println("Key Pressed: " + -key);

            kbOut.writeInt(-key);
            kbOut.flush();

        } catch (IOException ex) {
            System.out.println("Error writing -key data to server");
        }
    }

        @Override
    public void mouseMoved(MouseEvent me) {
        try {
            int mouseX = me.getX();
            int mouseY = me.getY();

            if (mOut != null) {
                mOut.writeInt(mouseX);
                mOut.writeInt(mouseY);
                mOut.flush();
                System.out.println("Mouse Moved To: " + mouseX + "," + mouseY);
            }


        } catch (IOException | NullPointerException ex) {
            System.out.println("Error writing mouse data to server");
        }
    }

    @Override
    public void mouseClicked(MouseEvent me) {

    }

    @Override
    public void mousePressed(MouseEvent me) {

    }

    @Override
    public void mouseReleased(MouseEvent me) {

    }

    @Override
    public void mouseEntered(MouseEvent me) {

    }

    @Override
    public void mouseExited(MouseEvent me) {

    }

    @Override
    public void mouseDragged(MouseEvent me) {

    }

    @Override
    public void keyTyped(KeyEvent ke) {

    }
}
TestClient.java

import java.awt.AWTException;
import java.awt.Robot;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class TestClient {

    private final static String SERVER_IP = "192.168.0.50";

    JPanel clientPanel = new JPanel();
    JFrame clientFrame = new JFrame();

    public void setupGUI() {

        clientFrame.add(clientPanel);
        clientFrame.setSize(200,200);
        clientFrame.setVisible(true);
        clientFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        clientPanel.requestFocusInWindow();
    }

    public static void main(String[] args) {

        try {
            new TestClient().setupGUI();

            Robot keyRobot = new Robot();

            Socket firstSocket = new Socket(SERVER_IP, 1111);
            System.out.println("Connected to Commander. Address sent. Waiting for callback.");
            firstSocket.close();

            Selector selector = Selector.open();

            int ports[] = new int[] { 1112, 1113 };

            for (int port : ports) {
                ServerSocketChannel serverChannel = ServerSocketChannel.open();
                serverChannel.configureBlocking(false);
                serverChannel.socket().bind(new InetSocketAddress(port));
                serverChannel.register(selector, SelectionKey.OP_ACCEPT);
            }

            while (true) {
                // After the 2 accept methods fire, it stops here and program doesnt continue.
                selector.select();
                Set setKeys = selector.selectedKeys();
                Iterator selectedKeys = setKeys.iterator();


                while (selectedKeys.hasNext()) {
                    SelectionKey selectedKey = (SelectionKey) selectedKeys.next();
                    if (selectedKey.isAcceptable()) {
                        SocketChannel socketChannel = ((ServerSocketChannel) selectedKey.channel()).accept();
                        socketChannel.configureBlocking(false);

                        switch (socketChannel.socket().getLocalPort()) {
                            case 1112:
                                System.out.println("Keyboard socket open.");
                                Runnable kbr = new KBThread(socketChannel.socket());
                                new Thread(kbr).start();
                                break;

                            case 1113:
                                System.out.println("Mouse socket open.");
                                break;
                        }
                    }
                    selectedKeys.remove();
                }


            }

            } catch (ConnectException ece) {
            System.out.println("Failed to connect to server: " + SERVER_IP);
        } catch (IOException | AWTException eio) {
            Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, eio);
        }
    }

    private static class KBThread implements Runnable {
        private final Socket kbSocket;
        private int dataID = 0;

        private KBThread(Socket kbSocket) {
            this.kbSocket = kbSocket;
        }

        @Override
        public void run() {

            try {
                DataInputStream kbDis = new DataInputStream(kbSocket.getInputStream());
                while (true) {
                    try {


                        if (kbDis.available() > 0) {
                            dataID = kbDis.readInt();
                            System.out.println(dataID);
                        }
                        //else System.out.println("noData");
                    } catch (IOException ex) {
                        Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            } catch (IOException ex) {
                Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

没有足够的评论代表,因此发布作为答案。我不是专家,但我相信您必须在套接字输出流上使用PrintWriter来来回传递文本。这里这个客户端是一个套接字

writer = new PrintWriter(thisClient.getOutputStream());
System.out.println("Transmitting");
writer.println(msg);
writer.flush();

这不是IO多路复用的工作原理

首先,不要从
selectedKeys
中删除-在您接受两个连接后,没有什么可选择的,因此主线程中的循环将阻塞,如果新连接到达,您将不再接受它们。-这是错误的,我对Java迭代器感到困惑,已经很久了

然后,一旦连接被接受并标记为非阻塞,使用
OP_READ
将其添加到同一选择器中。检查循环中的可读事件,从套接字读取。这不需要线程

或者,如果您想使用线程,不要将接受的客户端连接设置为非阻塞,只需在专用线程中定期读取它

编辑0: 我能提供的最好的建议是浏览一些好的JavaNIO教程。互联网上有很多,但您可以从这里开始:


当我使用常规IO而不是NIO时,我使用了dataoutputstreams。那会有区别吗?我想是的。。这是我几个月前开发的。。它是一个基本的聊天/服务器客户端。希望这一切顺利。。我不确定这是否行得通。我需要多个客户端连接,每个客户端连接到多个端口,这就是我使用NIO的原因。dataoutputstreams在套接字上使用常规IO时工作完全正常,但是套接字在accept上阻塞,因此我需要使用NIO。这是否适用于连接到服务器的多个客户端?我需要一个客户端,它将在随机时间连接,以连接到服务器。此客户端向服务器提供其IP地址。然后,客户端打开3个服务器套接字,服务器连接到这3个套接字。然后,服务器在每个套接字上发送数据,客户端从每个套接字读取数据,这样就可以工作了。不过,您不需要连接回客户端-一旦客户端建立TCP连接,它将是一个双向字节流。另外,一般来说,客户端可能位于NAT防火墙后面,服务器将无法连接回它们。我尝试将OP_READ添加到选择器中,我得到了非法的参数异常,尽管我可能没有在正确的位置添加它们。你能再解释一下你的建议吗?这是有道理的,我只是不知道具体如何实施。此应用程序将仅在本地网络上运行,因此不需要考虑防火墙。我可能不需要线程,这似乎是唯一的方法。我也曾为套接字通道设置isReadable,但它不起作用。另一个问题是,客户端将继续在isAcceptable中运行代码,并尝试再次设置configureBlocking并命中空指针。我可以通过更改一些内容使其发送数据。我必须保留selectedKeys.remove,以便它首先停止运行accept方法。然而,在我的switch语句中,我会按照您的建议将选择器添加回OP_READ,现在它可以工作了。现在我只需要弄清楚如何将bytebuffer解码成int。