Существует ли способ вновь открыть сокет?

Так как Строки Java основаны на массивах символов, и Java автоматически проверяет границы массива, переполнение буфера только возможно в необычных сценариях:

  1. при вызове собственного кода через JNI
  2. В самой JVM (обычно писавшимся в C++)
  3. , интерпретатор или JIT-компилятор не работают правильно (байт-код Java передал под мандат граничные проверки)
7
задан dugres 11 September 2009 в 13:00
поделиться

4 ответа

No, this is a limitation of the underlying C sockets (and the TCP/IP protocol, for that matter). My question to you is: why are you shutting them down when you can architect your application to use them?

The problem with many short-term sockets is that shutting them down puts them in a state where they cannot be used for a while (basically, twice the packet lifetime, to ensure any packets in the network either arrive and are discarded, or get discarded by the network itself). Basically what happens is that, in the 4-tuple that needs to be unique (source ip, source port, destination ip, destination port), the first one and last two tend to always be the same so, when you run out of source ports, you're hosed.

We've struck this problem in software before where it only became evident when we ran on faster machines (since we could use many more sessions).

Why dont you just open up the socket and continue to use it? It looks like your protocol is a simple request/response one, which should be easily do-able with that approach.

Something like:

sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.connect((adr, prt)
for i in range(nb):
    sck.send('question %i'%i)
    answer=sck.recv(4096)
    print 'answer %i : %s' % (%i, answer)
sck.close()

Update:

One possibility (and we've done this before) if you're running out of connection due to this continual open/close, is to detect the problem and throttle it. Consider the following code (the stuff I've added is more pseudo-code than Python since I haven't touched Python for quite a while):

for i in range(nb):
    sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sck.connect((adr, prt)

    while sck.error() == NO_SOCKETS_AVAIL:
        sleep 250 milliseconds
        sck.connect((adr, prt)

    sck.send('question %i'%i)
    sck.shutdown(SHUT_WR)
    answer=sck.recv(4096)
    print 'answer %i : %s' % (%i, answer)
    sck.close()

Basically, it lets you run at full speed while there are plenty of resources but slows down when you strike your problem area. This is actually what we did to our product to "fix" the problem of failing when resources got low. We would have re-architected it except for the fact it was a legacy product approaching end of life and we were basically in the fix-at-minimal-cost mode for service.

17
ответ дан 6 December 2019 в 08:44
поделиться

Я не уверен, каковы будут дополнительные накладные расходы, но вы можете полностью закрыть и снова открыть сокет. Вам необходимо установить SO_REUSEADDR и привязать к конкретному порту, который вы можете использовать повторно.

sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
3
ответ дан 6 December 2019 в 08:44
поделиться

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

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

1
ответ дан 6 December 2019 в 08:44
поделиться

Вы не можете повторно использовать сокет, но это не помогло бы, если бы вы могли, поскольку у вас заканчиваются порты, не розетки. Каждый порт будет оставаться в состоянии TIME_WAIT в течение удвоенного максимального срока службы сегмента после того, как вы инициируете завершение работы. Было бы лучше не требовать так много портов за такой короткий период, но если вам нужно использовать большое количество, вы можете увеличить диапазон эфемерных портов .

Номера портов 16-битные и поэтому их всего 65536 штук. Если вы работаете в Windows или Mac OS X, то по умолчанию временные порты выбираются из диапазона от 49152 до 65535. Это официальный диапазон , обозначенный IANA , но в Linux и Solaris (часто используется для высокого трафика. серверы) диапазон по умолчанию начинается с 32768, что позволяет использовать больше портов. Возможно, вы захотите внести аналогичное изменение в свою систему, если это еще не сделано и вам нужно больше временных портов.

Также можно уменьшить максимальный срок службы сегмента в вашей системе, сократив время, в течение которого каждый сокет находится в состоянии TIME_WAIT , или использовать SO_REUSEADDR или SO_LINGER в некоторых случаях для повторного использования портов до истечения времени. Однако это может, по крайней мере, теоретически привести к тому, что старые соединения будут смешаны с новыми соединениями, которые используют тот же номер порта, если некоторые пакеты от старых соединений приходят медленно, поэтому, как правило, это не очень хорошая идея.

0
ответ дан 6 December 2019 в 08:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: