所以我正在写两个ServerSockets。一个在端口8085上侦听HTTP请求并将字节输入保存到静态LinkedList中,另一个在端口8086上侦听并在静态LinkedList中返回所有结果。
问题是,将数据从ServerSocket:8085保存到LinkedList时,线程挂起,我不确定为什么。
这是侦听器的主要类:
int main()
{
long int id;
float grade,age;
char name[40],city[40],country[40],line[100]="3888914775 Itzel_Gardean 21 26 Iran Tehran";
int read_items = sscanf(line,"%ld %s %f %f %s %s",&id,name,&age,&grade,country,city);
printf("readed line is: %ld %s %f %f %s %s. sscanf() read %d items\n",id,name,grade,age,country,city,read_items);
}
这是ThreadListener类:
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();
}
}
}
}
对于我的测试,我尝试调用127.0.0.1:8085,并且收到ERR_CONNECTION_RESET,控制台中的所有内容如下:
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();
}
}
}
}
“这就是我们!”消息已打印,但“结果已收集!”紧接着LinkedList.add失败之后,我才假设LinkedList.add是挂线程的线程。
致谢
编辑:没有人打电话给8085(或8086),我正在浏览器中手动进行操作。我通过创建一种调用方法而不是直接调用LinkedList.add来解决了Syncronization问题:
Listening on 8085...
Listening on 8086...
Its us!
Process finished with exit code -1 (I killed the app after 2 mins)
这确实有效,但是每次调用8085套接字都会重置连接。
答案 0 :(得分:1)
LinkedList
不是synchornized
,as highlighted in the documentation。
您可以手动处理同步,使用同步列表或并发列表。也许还有其他方法,但就目前而言,只需保持简单即可。
public static LinkedList<byte[]> Calls = Collections.synchronizedList(new LinkedList<>());
// or
public static LinkedList<byte[]> Calls = new CopyOnWriteArrayList<>();
答案 1 :(得分:1)
您使用浏览器创建请求的测试机制在这里也可能无济于事,例如InputStream.readAllBytes()
阻塞,直到读取完所有剩余字节并检测到流的末尾或引发异常为止。此方法不会关闭输入流。
来自the documentation。具体来说,浏览器会保持连接打开状态,因为它期待某些响应。您的服务器正在尝试从连接读取所有内容,直到连接关闭。捕获22(又名死锁)。
尝试使用localhost:8085
与telnet
建立连接,并从客户端关闭连接。
telnet 127.0.0.1 8085
^D
其中^D
实际上是[CTRL]和[D]键(例如:注销)