ServerSocket проверява за физически прекъсване на мрежата
Някой може ли да попадне на периодична проверка на клиентската връзка за наличност. Стресова ситуация - захранващият кабел е изваден иSocket.Connectedвръщаtrue. Това е проблем или нормална работа на ServerSocket.
←→Digitman ( 2002-07-04 17:53 ) [1]
Това е нормална работа. Но не ServerSocket, а самият TCP / IP протокол. Прекъсването на TCP/IP връзката е логическа концепция, а не физическа, и в общия случай представлява факта, че приемникът получава (и, като правило, изпраща от предавателя) TCP пакет с RST флаг (нулиране, нулиране). Ако „захранващият кабел е изваден“ поне от едната страна, не може да се говори за някакво логично взаимодействие между отдалечени партньори.
←→ChernoVVV ( 2002-07-04 18:18 ) [2]
Тогава защоClientSocketследи прекъснатата връзка, аServerSocketмълчи?
←→Digitman ( 2002-07-04 18:26 ) [3]
От това, което взе, за ClientSocket? С какво принципно се различава от т.нар. единичен протокол, използван от ServerSocket?
Моля да посочите аргументи в полза на подобно твърдение.
←→ChernoVVV ( 2002-07-04 18:55 ) [4]
Аргументът "OnError -> OnDisconnect" работи в 99,99% от случаите, поне за мен, може би е просто проблем :)
←→Digitman ( 2002-07-05 08:06 ) [5]
Проведете съзнателно "чист" експеримент: оставете вашия ClientSocket да осъществи успешна връзка със сървъра и от този момент нататък "мълчи", без да изпълнява повече методи (чието изпълнение може да доведе до OnError() със същата диагностика, последвано от OnDisconnect). А сега - "издърпайте конеца" от машината, на която се намира сървърът.
←→ChernoVVV ( 2002-07-05 08:47 ) [6]
Клиентът периодично проверява [9sec] за(Active=true)и(ClientSocket.Socket.Connected)и(ClientSocket.Socket.RemoteAddress<>"")- това чист експеримент ли е? Ако от страната на сървъра проверя същото за ServerSocket, винаги ще е вярно, независимо от връзката.
←→Digitman ( 2002-07-05 10:43 ) [7]
Не, това не е чист експеримент.
Най-малкото защото в контекста на метода GetRemoteAddress() се извиква функцията WinsockAPI:
CheckSocketResult(getpeername(FSocket, SockAddrIn, Size), "getpeername");
←→ChernoVVV ( 2002-07-05 11:53 ) [8]
Защо тогава от страната на сървъра подобенGetRemoteAddress()не хвърля изключение?
←→Digitman ( 2002-07-05 12:05 ) [9]
Аха! Хванахте ли изключението?) Всъщност това е отговорът на вашия въпрос от страна на клиента: клиентът е "мълчалив" - той няма да получи никакви известия, че "дантелата" на сървъра е "откъсната".
Но за да отговорите на аналогичен въпрос от страна на сървъра, трябва да знаете режима на инициализация на ServerSocket (блокиране на нишки / неблокиране), програмната среда на създадения сървърен обект на класа TServerSocket и конкретното място в кода, където се извикват методите / свойствата на обекта на класа TClientServerWinSocket, който е установил връзка с "счупения" клиент
Донесете кода - ние ще го анализираме
←→ChernoVVV ( 2002-07-05 12:42 ) [10]
Инициализация ->ServerSocket.ServerType := stNonBlocking;OnConnect(Server) ->User(TUser(TObject+Socket)).Socket(TCustomWinSocket) := Socket(OnConnect(Socket));(добавяне в списък) Проверкавръзки -> (User[i].Socket=nil)or(not User[i].Socket.Connected)or(User[i].Socket.RemoteAddress) след това User[i].Free(del in list);
←→Digitman ( 2002-07-05 16:10 ) [11]
1. Е, къде е вашият манипулатор OnClientError()? Как ще прихванете изключителни ситуации при достъп до вече несъществуващ физически транспортен канал с клиент?
3. Всичко, което прави свойството TCustomWinSocket.Connected, е да връща стойността на частното поле TCustomWinSocket.FConnected. Което от своя страна става True, когато се установи успешна връзка с партньор, и се нулира на False, когато се извика методът TCustomWinSocket.Disconnect().
TCustomWinSocket.Disconnect() се извиква автоматично: - в деструктора на обекта TCustomWinSocket (извикахте ли го, деструктор?); - преди извикване на манипулатора OnDisconnect() (когато връзката е правилно затворена по инициатива на партньора); - когато класът TCustomWinSocket хвърля изключение, свързано с повреда на една от API функциите на сокета (свързани, наред с други неща, с достъп за четене/запис до проблемния транспортен канал)
Има ли съмнения по този въпрос? Можете да проверите цялата тази логика (и трябваше да го направите отдавна!) в модула scktcomp.pas.
Добре ? По-нататък? Или ви убедих в неправилността на вашата версия за проверка на активността на връзката?