Java - Странная висящая розетка? - PullRequest
5 голосов
/ 16 декабря 2009

У меня клиент-серверное приложение с java-сервером. Он работает в значительной степени идеально, за исключением того, что после длительного периода времени, гнездо продолжает висеть. Этот сокет - лишь один из многих, остальные, кажется, все еще в порядке, но как только он попадет в сокет, сервер просто не пройдет линию отправки. Вот соответствующие части кода:

Socket socket; // A normal socket
out  = new PrintWriter(socket.getOutputStream(), true); // The outstream
out.println(msg + "\0"); // This command is used to send stuff, msg is a String

Никаких исключений не выдается, строковое приложение просто не проходит через строку:

out.println(msg + "\0");

Я знаю, что String хороша, вызывайте 4 или 5 других сокетов, прежде чем этот сможет отправить ее просто отлично. Также обратите внимание, что, насколько я знаю, этот сокет может отправлять сотни сообщений просто отлично, прежде чем он внезапно зависнет. Кто-нибудь знает, какую ошибку я должен искать?

Ответы [ 2 ]

5 голосов
/ 16 декабря 2009

Есть много вещей, которые могут вызвать это, но похоже, что вы, вероятно, испытываете обратное давление на уровне TCP.

Обычно, когда вы отправляете данные в сокет, они просто буферизируются, и отправляющий вызов (в вашем случае println() и flush()) может вернуться до того, как данные действительно будут отправлены в сеть. Может случиться так, что все ваши предыдущие записи в этом сокете были просто помещены в локальный SO_SNDBUF , и вы просто заполнили его.

(1) Можете ли вы отследить это, используя tcpdump или Wireshark, и найти точное соединение, которое зависает (я знаю, что это становится трудно со многими соединениями)? Изучение размера окна TCP во время зависания вашей программы расскажет вам больше о том, блокируете ли вы в самой Java или на сетевом уровне.

(2) Сбросьте стопку и разместите ее здесь. Сокеты Java имеют внутреннюю блокировку, предотвращающую одновременную запись в них двух потоков. Вы уверены, что только один поток обращается к этому сокету в тот момент, когда вы пытаетесь написать?

Вы определенно хотите попробовать сделать

$ jstack <PID>

когда он заморожен, чтобы точно увидеть, где он висит, и если поток записи пытается получить какие-либо блокировки.

3 голосов
/ 16 декабря 2009

Объект Socket OutputStream будет блокировать запись при тех же условиях, что и основной вызов send(): когда локальные буферы сокета заполнены. То, что он остается заблокированным, означает, что выходной буфер не может быть очищен, что, в свою очередь, указывает на то, что буфер чтения на другом конце соединения заполнен, и что приложение, обрабатывающее другой конец соединения, не считывает данные, которые уже поступили .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...