繁体   English   中英

SocketChannel套接字不读取数据

[英]SocketChannel sockets not reading data

这是我的代码。 从TestServer,我试图通过输出流发送数据并从测试客户端接收数据。 我使用SocketChannel,因为我需要客户端同时监听3个端口。 目前,我只想从一个套接字读取。 但是,它似乎没有从服务器接收任何数据。 对于KBThread的运行方法,如果我取消注释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来回传递文本。 这里的thisClient是一个套接字。

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

IO多路复用不应如此工作。

首先,不要从selectedKeys删除-在接受了两个连接之后,就没有任何选择可以选择了,因此,主线程块中的循环以及如果有新连接到达的事件就不再接受它们。 -这是错误的,我对Java迭代器感到困惑,已经很长时间了...

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

另外,如果要使用线程,则不要将接受的客户端连接设置为非阻塞,而只需在专用线程中进行常规读取即可。

编辑0:

我能提供的最佳建议是阅读一些不错的Java NIO教程。 Intenet上有很多,但是您可以从这里开始:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM