【发布时间】:2019-11-12 15:12:17
【问题描述】:
所以我正在编写两个 ServerSocket。一个监听 8085 端口上的 HTTP 请求并将字节输入保存到静态 LinkedList 中,另一个监听端口 8086 并在静态 LinkedList 中返回所有结果。
问题是当将数据从 ServerSocket:8085 保存到 LinkedList 时,线程挂起,我不知道为什么。
这是主要的 Listener 类:
import java.net.ServerSocket;
import java.nio.charset.Charset;
import java.util.*;
public class Listener {
public static LinkedList<byte[]> Calls = new LinkedList<>();
public static void main(String[] args) {
Thread callback = new Thread(new ThreadListener());
callback.start();
while (true) {
try (var listener = new ServerSocket(8086)) {
System.out.println("Listening on 8086...");
try (var client = listener.accept()) {
StringBuffer response = new StringBuffer();
response.append("HTTP/1.1 200 OK\r\n\r\n");
Iterator<byte[]> iterator = Calls.iterator();
while (iterator.hasNext()) {
response.append(new String(iterator.next(), Charset.forName("UTF-8")) + "\r\n");
iterator.remove();
}
client.getOutputStream().write(response.toString().getBytes("UTF-8"));
client.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
这是 ThreadListener 类:
import java.io.IOException;
import java.net.ServerSocket;
import java.util.Date;
public class ThreadListener implements Runnable {
@Override
public void run() {
while (true) {
try (var listener = new ServerSocket(8085)) {
System.out.println("Listening on 8085...");
try (var socket = listener.accept()) {
if (!socket.getInetAddress().getHostAddress().equals("127.0.0.1")) {
System.out.println("Not localhost");
} else {
System.out.println("Its us!");
}
Listener.Calls.add(socket.getInputStream().readAllBytes());
System.out.println("Result collected");
Date today = new Date();
String httpResponse = "HTTP/1.1 200 OK\r\n\r\n" + today;
socket.getOutputStream().write(httpResponse.getBytes("UTF-8"));
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
至于我的测试,我尝试调用 127.0.0.1:8085,我得到一个 ERR_CONNECTION_RESET,我在控制台中的所有内容如下:
Listening on 8085...
Listening on 8086...
Its us!
Process finished with exit code -1 (I killed the app after 2 mins)
事实上,“它就是我们!”消息已打印,但“已收集结果!”在 LinkedList.add 之后没有导致我认为 LinkedList.add 是挂起线程的那个。
问候
编辑:没有人打电话给 8085(或 8086),我是在浏览器上手动进行的。我通过创建一个方法来调用而不是直接调用 LinkedList.add 解决了同步问题:
public static synchronized void addElementsToList(byte[] bytes) {
Calls.add(bytes);
}
这确实有效,但调用 8085 套接字每次都会重置连接。
【问题讨论】:
-
除了同步问题,谁在写8085服务器?写在那里的应用程序在完成写入后是否关闭流?如果它是一个程序,也显示它的代码。如果不是,请解释它是如何完成的。请edit问题添加信息,不要使用cmets,除非告诉我们你更新了。
-
更新了@RealSkeptic
-
您的同步方法有误。不要使用同步的静态方法。它们在类对象上同步,如果您曾经使用过
wait和notify,可能会导致问题。此外,如果您只在写入时同步,而在读取时忽略同步,则同步毫无意义。您的迭代器在运行时会更改Calls。这很糟糕。您应该改用阻塞队列。
标签: java multithreading serversocket