Мрежово програмиране: да поддържате сокети или не?

В момента превеждам API от C# на Java, който има мрежов компонент.

Версията на C# изглежда поддържа входните и изходните потоци и сокета отворени за продължителността на използваните класове.

Дали това е правилно?

Като се има предвид, че приложението изпраща команди и получава събития въз основа на потребителски вход, по-разумно ли е да се отваря нов поток от сокет за всяко "съобщение"?

Поддържам ServerSocket за прослушване на хвърлящи събития от сървъра, но не съм толкова сигурен, че поддържането на Socket и изходен поток за изходящи комуникации е толкова добра идея.

Не съм свикнал с програмирането на Socket. Както при много разработчици, аз обикновено работя на приложния слой, когато трябва да работя в мрежа, а не на сокетния слой и минаха 5 или 6 години, откакто се занимавах с тези неща в университета.

Наздраве за помощта. Предполагам, че това е по-скоро молба за съвет, отколкото за окончателен отговор.


person Omar Kooheji    schedule 06.02.2009    source източник
comment
Знам, че този въпрос е отпреди 2,5 години, но бих казал това (тъй като мисля, че си струва да се каже): пулове за свързване. Това е, което искате да използвате (или да внедрите, ако приложението ви няма достъп до вече създадено).   -  person luis.espinal    schedule 19.08.2011


Отговори (7)


Има компромис между разходите за поддържане на връзките отворени и разходите за създаване на тези връзки.

Създаването на връзки струва време и честотна лента. Трябва да направите 3-посочно TCP ръкостискане, да стартирате нова сървърна нишка, ...

Поддържането на отворени връзки струва основно памет и връзки. Мрежовите връзки са ресурс, ограничен от операционната система. Ако имате твърде много свързани клиенти, може да изчерпите наличните връзки. Това ще струва памет, тъй като ще имате една отворена нишка за всяка връзка, със свързаното с нея състояние.

Правилният баланс ще бъде различен в зависимост от употребата, която очаквате. Ако имате много клиенти, които се свързват за кратък период от време, вероятно ще бъде по-ефективно да затворите връзките. Ако имате малко клиенти, които се свързват за дълъг период от време, вероятно трябва да държите връзките отворени ...

person Guillaume    schedule 06.02.2009

Ако имате само един сокет на клиента и сървъра, трябва да го държите отворен възможно най-дълго.

person David Grant    schedule 06.02.2009

Ако вашето приложение и сървърът, с който говори, са близо, мрежово, МОЖЕ да е разумно да затворите връзката, но ако са отдалечени, мрежово, вероятно е по-добре да оставите сокета да работи за известно време.

Гийом спомена 3-посочното ръкостискане и това на практика означава, че отварянето на сокет ще отнеме минимум 3 пъти най-краткото време за преминаване на пакета. Това може да се приближи до "половината ping двупосочно пътуване" и може лесно да достигне 60-100 ms за дълги разстояния. Ако завършите с допълнителни 300 ms чакане за всяка команда, това ще повлияе ли на потребителското изживяване?

Лично аз бих оставил сокета отворен, по-лесно е и не отнема време за всеки случай на „трябва да изпратя нещо“, относителната цена е малка (един файлов дескриптор, малко памет за структурите от данни в потребителското пространство и допълнително място за съхранение в ядрото).

person Vatine    schedule 06.02.2009

Зависи колко често очаквате потребителят да въвежда команди. Ако се случва доста рядко, може би бихте могли да затворите гнездата. Ако е често, многократното създаване на сокети може да бъде скъпа операция.

След като казахме това, колко скъпо е от гледна точка на ресурсите на машината да имате отворена връзка за сокет за редки данни? Защо точно смятате, че "поддържането на Socket и изходящ поток за изходящи комуникации не е толкова добра идея" (въпреки че изглежда правилното нещо)? От друга страна, това е различно за файловите потоци, ако очаквате, че други процеси може да искат да използват същия файл. Бързото затваряне на файловия поток в този случай би било правилният начин.

Колко вероятно е да изчерпите многото TCP връзки, които можете да създадете, които други процеси, създаващи изходящи връзки, биха искали да използват? Или очаквате да имате голям брой клиенти, свързващи се към вашия сървър едновременно?

person Mystic    schedule 06.02.2009
comment
Ще ви свършат връзките много преди да ви свършат номерата на портовете. - person paxdiablo; 06.02.2009
comment
един сървър един клиент Така че няма да останете без връзки. портът е посочен, тъй като API е обвивка около TCP базиран протокол. - person Omar Kooheji; 06.02.2009
comment
Моя грешка, предполагам, че съм забравил и мрежовото си програмиране - person Mystic; 06.02.2009

Можете също да разгледате DatagramSocket и DatagramPacket. Предимството е по-ниското натоварване, недостатъкът е натоварването, което осигурява обикновеният Socket.

person Paul    schedule 06.02.2009
comment
Нямам опция за смяна на протокола, свързвам се с приложение на доставчик. - person Omar Kooheji; 06.02.2009
comment
И изисква надеждност да бъде внедрена от разработчика? Не, Господине! - person nanofarad; 15.10.2013

Предлагам ви да разгледате използването на съществуващо решение за съобщения като ActiveMQ или Netty. Това ще се справи с много от проблемите, които може да срещнете със съобщенията.

person Peter Lawrey    schedule 06.02.2009

Идвам малко късно, но не видях някой да го е предложил.

Мисля, че ще бъде разумно да обмислите обединяването на вашите връзки (няма значение дали Socket или TCP), възможността да поддържате няколко връзки отворени и бързо да ги използвате повторно във вашата кодова база би било оптимално в случай на производителност.

Всъщност компилаторът Roslyn широко използва тази техника на много места. https://github.com/dotnet/roslyn/search?l=C%23&q=pooled&type=&utf8=%E2%9C%93

person kuskmen    schedule 10.01.2018