[英]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.