简体   繁体   English

ServerSocket 和客户端之间发送消息

[英]Sending message between ServerSocket and client

I need to send a message from the ServerSocket to the client when the key is writable, I think that the message is being sent in the right way but when I try to read it on the client I get this error:当密钥可写时,我需要从 ServerSocket 向客户端发送一条消息,我认为消息以正确的方式发送,但是当我尝试在客户端上读取它时,我收到此错误:

java.io.StreamCorruptedException: invalid stream header: 48656C6C
        at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:866)
        at java.io.ObjectInputStream.<init>(ObjectInputStream.java:358)
        at MyTcpClient.main(MyTcpClient.java:22)

How can I read the message correctly in the client?如何在客户端中正确读取消息? These are my files:这些是我的文件:

MyAsyncProcessor.java MyAsyncProcessor.java

import java.io.IOException;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyAsyncProcessor {

    HashMap<Integer, MyTask> hashMap = new HashMap<>();

    ExecutorService pool;

    public MyAsyncProcessor() {
    }

    public static void main(String[] args) throws IOException {
        new MyAsyncProcessor().process();
    }

    public void process() throws IOException {
        pool = Executors.newFixedThreadPool(2);
        InetAddress host = InetAddress.getByName("localhost");
        Selector selector = Selector.open();
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.bind(new InetSocketAddress(host, 9876));
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        SelectionKey key;
        System.out.println("AsyncProcessor ready");
        while (true) {
            if (selector.select() > 0) {
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> i = selectedKeys.iterator();
                while (i.hasNext()) {
                    key = i.next();
                    if (!key.isValid()) {
                        key.cancel();
                        continue;
                    }
                    if (key.isAcceptable()) {
                        SocketChannel socketChannel = serverSocketChannel.accept();
                        socketChannel.configureBlocking(false);
                        System.out.println("Channel hashCode: " + socketChannel.hashCode());
                        MyTask task = new MyTask(selector, socketChannel);
                        hashMap.put(socketChannel.hashCode(), task);
                        pool.execute(task);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                    }
                    if (key.isReadable()) {
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        MyTask task = hashMap.get(socketChannel.hashCode());
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        try {
                            socketChannel.read(byteBuffer);
                            String result = new String(byteBuffer.array()).trim();
                            String[] words = result.split(" ");
                            task.timeToRead = Integer.parseInt(words[words.length - 2]) * 1000;
                            task.timeToWrite = Integer.parseInt(words[words.length - 1]) * 1000;
                            System.out.println(Thread.currentThread().getName() + " reads for " + task.timeToRead + " mills");
                            try {
                                Thread.sleep(task.timeToRead);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println(Thread.currentThread().getName() + " ended reading");
                        } catch (Exception e) {
                            e.printStackTrace();
                            return;
                        }
                        socketChannel.register(selector, SelectionKey.OP_WRITE);
                    }
                    if (key.isWritable()) {
                        SocketChannel socketChannel = (SocketChannel) key.channel();
                        MyTask task = hashMap.get(socketChannel.hashCode());
                        task.readyToWrite();
                        hashMap.remove(socketChannel.hashCode());
                        System.out.println(Thread.currentThread().getName() + " writes for " + task.timeToWrite + " mills");
                        try {
                            Thread.sleep(task.timeToWrite);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + " ended writing");
                        CharsetEncoder enc = StandardCharsets.US_ASCII.newEncoder();
                        String response = "Hello!\n";
                        socketChannel.write(enc.encode(CharBuffer.wrap(response)));
                        key.cancel();
                    }
                    i.remove();
                }
            }
        }
    }
}

MyTcpClient.java MyTcpClient.java

import java.io.*;
import java.net.Socket;
import java.util.Random;

public class MyTcpClient {

    public static void main(String[] args) {

        Random rand = new Random();
        int secondsToRead = rand.nextInt(5);
        int secondsToWrite = secondsToRead + 1;
        String message = "Seconds for the task to be read and written: " + secondsToRead + " " + secondsToWrite;
        System.out.println(message);
        Socket socket;
        ObjectInputStream ois;
        try {
            socket = new Socket("127.0.0.1", 9876);
            PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
            printWriter.println(message);
            System.out.println("Sending message");

            ois = new ObjectInputStream(socket.getInputStream());
            String response = (String) ois.readObject();
            System.out.println("Response: " + response);
            ois.close();
        } catch (IOException e) {
            System.out.println("Error in Socket");
            e.printStackTrace();
            System.exit(-1);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }


    }
}

Thank you in advance先感谢您

Here on the server you are sending raw (text) data在服务器上,您正在发送原始(文本)数据

                    socketChannel.write(enc.encode(CharBuffer.wrap(response)));

And here on the client you are trying to read this as an Object在客户端上,您试图将其读作 Object

        ois = new ObjectInputStream(socket.getInputStream());
        String response = (String) ois.readObject();
        System.out.println("Response: " + response);

For your ObjectInputStream to work, you need to be using an ObjectOutputStream on the other side.要使 ObjectInputStream 正常工作,您需要在另一侧使用 ObjectOutputStream。 I would recommend against using the Object streams, as these are Java-only and can fail if the two sides are using different versions of the serialized object. Instead, just use raw streams.我建议不要使用 Object 流,因为它们仅适用于 Java,如果双方使用序列化 object 的不同版本,则可能会失败。相反,只需使用原始流。

Better yet, use WebSockets - WebSockets handle a lot of the plumbing that sockets come with in a more elegant way.更好的是,使用WebSockets - WebSockets 以更优雅的方式处理 sockets 附带的许多管道。 You can definitely find an implementation of WebSockets for Java on GitHub您绝对可以在 GitHub 上找到 Java 的 WebSockets 实现

I have solved it by using on the client to receive:我已经通过在客户端上使用来接收来解决它:

ByteBuffer readBuffer = ByteBuffer.allocate(1024);
        server.read(readBuffer);
        String result = new String(readBuffer.array()).trim();

In the server to send:在服务器发送:

CharsetEncoder enc = StandardCharsets.US_ASCII.newEncoder();
                String response = "Task completed in " + (this.timeToWrite+this.timeToRead) + " mills \n";

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

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