HttpUrlConnection зависает на SYN_SENTJAVA

Программисты JAVA общаются здесь
Anonymous
HttpUrlConnection зависает на SYN_SENT

Сообщение Anonymous »

Рассмотрим следующие клиентские и серверные компоненты:

Код: Выделить всё

import java.io.InputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

public class client {
public static void main(String[] args) throws IOException {
while (true) {
URL url = new URL("http://localhost:8000");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int statusCode = connection.getResponseCode();
System.out.println("Status Code: " + statusCode);
connection.disconnect();
}
}
}

Код: Выделить всё

import java.io.OutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8000);
while (true) {
Socket clientSocket = serverSocket.accept();
OutputStream outputStream = clientSocket.getOutputStream();
outputStream.write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes());
outputStream.flush();
clientSocket.close();
}
}
}
При запуске клиента во время работы сервера вы вскоре увидите, что клиент начинает зависать на SYN_SENT на уровне TCP (всего около 30 секунд) :

Код: Выделить всё

$ watch -n 0.1 "ss -on state syn-sent '( dport = :8000 )'"
Every 0.1s: ss -on state syn-sent '( dport = :8000 )'               myhost: Tue Jul 16 04:08:52 2024

Netid Recv-Q Send-Q      Local Address:Port        Peer Address:Port           Process
tcp   0      1           [::ffff:127.0.0.1]:60418  [::ffff:127.0.0.1]:8000     timer:(on,3.731ms,2)

Код: Выделить всё

$ pkill -3 java
# Stack trace of client's main thread while hanging outputted in Java terminal...
"main"  #1 prio=5 os_prio=0 cpu=2429.68ms elapsed=40.96s tid=0x000079e6c40266c0 nid=0x18a1c6 runnable  [0x000079e6cb9fd000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.Net.connect0(java.base@17.0.11/Native Method)
at sun.nio.ch.Net.connect(java.base@17.0.11/Net.java:579)
at sun.nio.ch.Net.connect(java.base@17.0.11/Net.java:568)
at sun.nio.ch.NioSocketImpl.connect(java.base@17.0.11/NioSocketImpl.java:593)
at java.net.Socket.connect(java.base@17.0.11/Socket.java:633)
at java.net.Socket.connect(java.base@17.0.11/Socket.java:583)
at sun.net.NetworkClient.doConnect(java.base@17.0.11/NetworkClient.java:183)
at sun.net.www.http.HttpClient.openServer(java.base@17.0.11/HttpClient.java:533)
at sun.net.www.http.HttpClient.openServer(java.base@17.0.11/HttpClient.java:638)
at sun.net.www.http.HttpClient.(java.base@17.0.11/HttpClient.java:281)
at sun.net.www.http.HttpClient.New(java.base@17.0.11/HttpClient.java:386)
at sun.net.www.http.HttpClient.New(java.base@17.0.11/HttpClient.java:422)
at sun.net.www.protocol.http.HttpURLConnection.setNewClient(java.base@17.0.11/HttpURLConnection.java:831)
at sun.net.www.protocol.http.HttpURLConnection.setNewClient(java.base@17.0.11/HttpURLConnection.java:819)
at sun.net.www.protocol.http.HttpURLConnection.writeRequests(java.base@17.0.11/HttpURLConnection.java:759)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(java.base@17.0.11/HttpURLConnection.java:1708)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(java.base@17.0.11/HttpURLConnection.java:1611)
at java.net.HttpURLConnection.getResponseCode(java.base@17.0.11/HttpURLConnection.java:529)
at client.main(client.java:13)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@17.0.11/Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@17.0.11/NativeMethodAccessorImpl.java:77)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@17.0.11/DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(java.base@17.0.11/Method.java:568)
at com.sun.tools.javac.launcher.Main.execute(jdk.compiler@17.0.11/Main.java:419)
at com.sun.tools.javac.launcher.Main.run(jdk.compiler@17.0.11/Main.java:192)
at com.sun.tools.javac.launcher.Main.main(jdk.compiler@17.0.11/Main.java:132)
Я создаю Java-приложение (когда я столкнулся с этой проблемой, я пытался использовать интервал опроса 10 мс - мне показалось, что 30 мс работает), где мне нужно быстро отправить HTTP подобные запросы в течение определенного периода времени (я не могу использовать веб-сокеты). Итак, мой вопрос: почему происходит это зависание и как я могу это исправить?
Моей лучшей попыткой исправить это до сих пор было увеличение количества доступных файловых дескрипторов с обеих сторон (

Код: Выделить всё

uname -n unlimitied
), но безрезультатно.
Сейчас проверяю больше... Я также могу воспроизвести то же самое с Python:

Код: Выделить всё

import requests

while True:
response = requests.get("http://localhost:8000")
print(f"Status Code: {response.status_code}")
Затем python -m http.server для сервера, и вы получите зависание SYN_SENT. Итак, похоже, что проблема может быть глубже, чем я первоначально предполагал, но мне любопытно и я готов услышать любое потенциальное решение.


Подробнее здесь: https://stackoverflow.com/questions/787 ... n-syn-sent

Вернуться в «JAVA»