Ko te hoahoanga taketake o te Ipurangi i kii he mokowā wāhitau riterite kei roto i ia kōpuku he wāhitau IP o te ao me te ahurei, ka taea te korero tika ki etahi atu pona. Inaianei he rereke te hoahoanga o te Ipurangi - tetahi waahanga o nga wahitau IP o te ao me te maha o nga waahi me nga wahitau motuhake kei muri i nga taputapu NAT.I roto i tenei hoahoanga, ko nga taputapu anake i roto i te waahi waahi o te ao ka ngawari te korero ki tetahi i runga i te whatunga na te mea he wahitau IP ahurei to ratou, huri noa i te ao. Ka taea e te node i runga i te whatunga tūmataiti te hono ki etahi atu node i runga i te whatunga kotahi, ka taea hoki te hono atu ki etahi atu pona rongonui i roto i te waahi waahi o te ao. Ko te nuinga o tenei tauwhitinga i tutuki na te tikanga whakamaori wahitau whatunga. Ko nga taputapu NAT, penei i nga pouara Wi-Fi, ka waihanga i nga urunga ripanga whakamaori motuhake mo nga hononga putaatu me te whakarereke i nga wahitau IP me nga tau tauranga i roto i nga kete. Ma tenei ka taea nga hononga puta mai i te whatunga tūmataiti ki nga kaihautu i te waahi waahi o te ao. Engari i te wa ano, ko nga taputapu NAT te nuinga ka aukati i nga waka taumai katoa mena ka whakaritea nga ture motuhake mo nga hononga taumai.
He tika tenei hoahoanga o te Ipurangi mo te whakawhitiwhiti korero a te kiritaki-tūmau, ka taea e nga kiritaki te noho ki roto i nga whatunga tūmataiti, me nga kaitoro he wahitau o te ao. Engari he uaua ki te hono tika o nga pona e rua i waenga rerekē whatunga tūmataiti. He mea nui te hono tika i waenga i nga pona e rua mo nga tono hoa-ki-hoa penei i te tuku reo (Skype), te uru mamao ki te rorohiko (TeamViewer), te petipeti ipurangi ranei.
Ko tetahi o nga huarahi tino whai hua mo te whakarite hononga hoa-ki-hoa i waenga i nga taputapu i runga i nga whatunga motuhake rereke ka kiia ko te pupuhi poka. Ka whakamahia tenei tikanga me nga tono i runga i te kawa UDP.
Engari ki te hiahia to tono ki te tuku i nga raraunga, hei tauira, ka whakawhiti koe i nga konae i waenga i nga rorohiko, katahi ka raru te whakamahi i te UDP na te mea ehara te UDP i te kawa tuku taurangi me te kore e tuku i nga paakete kia rite ki te TCP. kawa.
I roto i tenei take, ki te whakarite i te tuku paatete whai mana, me whakatinana he kawa paparanga tono e whakarato ana i nga mahi e tika ana me te mahi i runga i te UDP.
Kei te pirangi au ki te mahara tonu kei reira he tikanga kuia poka TCP mo te whakatuu hononga TCP i waenga i nga pona i roto i nga momo whatunga motuhake, engari na te kore tautoko e te maha o nga taputapu NAT, kaore e kiia ko te huarahi matua ki te hono atu. taua pona.
Mo te toenga o tenei tuhinga, ka aro noa ahau ki te whakatinanatanga o te kawa tuku whakamana. Ko te whakatinanatanga o te tikanga kuki poka UDP ka whakaahuahia i roto i nga tuhinga e whai ake nei.
Nga Whakaritenga Kawa
Ko te tuku putea pono i whakatinanahia na roto i te tikanga urupare pai (te mea e kiia nei he mihi pai)
Ko te hiahia mo te whakawhiti pai o nga raraunga nui, i.e. me karo te kawa i te tukunga o nga paakete kore e tika
Ka taea te whakakore i te tikanga whakapumau tuku (te kaha ki te mahi hei kawa UDP "parakore")
Te kaha ki te whakatinana i te aratau whakahau, me te whakapumautanga o ia karere
Ko te waahanga taketake o te whakawhiti raraunga i runga i te kawa me he karere
Ko enei whakaritenga ka tino rite ki nga whakaritenga Kawa Raraunga Whakapono kua whakaahuatia i roto RFC 908 и RFC 1151, a i whakawhirinaki ahau ki aua paerewa i te wa e whakawhanake ana i tenei kawa.
Kia mohio ai ki enei whakaritenga, me titiro ki te wa whakawhiti raraunga i waenga i nga waahanga whatunga e rua ma te whakamahi i nga tikanga TCP me te UDP. Kia rua nga keehi ka ngaro tetahi kete. Te whakawhiti i nga raraunga tauwhitiwhiti kore i runga i te TCP:
Ka kitea e koe mai i te hoahoa, mena kua ngaro te paatete, ka kitea e TCP te kete kua ngaro, ka ripoata ki te kaituku ma te tono mo te maha o te wahanga ngaro. Te whakawhiti raraunga ma te kawa UDP:
Karekau a UDP e whai i nga mahi rapunga mate. Ko te whakahaere i nga hapa tuku i roto i te kawa UDP te kawenga katoa o te tono.
Ka kitea te hapa i roto i te kawa TCP ma te whakatu hononga ki te node mutunga, te penapena i te ahua o taua hononga, me te tohu i te maha o nga paita ka tukuna ki ia pane pane, me te whakamohio i nga rihīti ma te whakamahi i te nama mihi.
I tua atu, ki te whakapai ake i te mahi (ara te tuku neke atu i te kotahi waahanga me te kore e whiwhi mihi), ka whakamahia e te kawa TCP te matapihi whakawhiti e kiia nei - ko te maha o nga paita o nga raraunga e tumanakohia ana e te kaituku o te wahanga kia whiwhi.
Mo etahi atu korero mo te kawa TCP, tirohia RFC 793, mai i te UDP ki RFC 768kei hea, i roto i te meka, kua tautuhia.
Mai i nga korero o runga ake nei, ka maarama ko te hanga i tetahi kawa tuku karere pono i runga i te UDP (ka kiia i muri nei ko UDP pono), e hiahiatia ana ki te whakatinana i nga tikanga whakawhiti raraunga e rite ana ki te TCP. Ara:
tiakina te ahua hononga
whakamahia te tatau wahanga
whakamahi i nga kohinga whakapumau motuhake
te whakamahi i te tikanga matapihi ngawari ki te whakapiki ake i te puta kawa
Hei taapiri, me hiahia koe:
tohu te timatanga o te karere, ki te toha rauemi mo te hononga
tohu te mutunga o te karere, ki te tuku i te karere kua tae ki te tono whakarunga me te tuku rauemi kawa
tukua te kawa hononga-motuhake ki te whakakore i te tikanga whakau tuku kia mahi hei UDP "parakore".
Pane UDP pono
Kia maumahara ko te UDP raraunga kua whakauruhia ki roto i te IP raraunga. E tika ana te "takai" te paakete UDP Whakapono ki roto i te mahere raraunga UDP. Whakakapinga pane UDP pono:
He tino ngawari te hanganga o te pane UDP Whakapono:
Kara - haki mana mōkihi
Momo Karere - momo karere e whakamahia ana e nga tono whakarunga hei ohauru ki nga karere motuhake
TransmissionId - te tau o te tuku, me te wahitau me te tauranga o te kaiwhiwhi, he tohu motuhake te hononga
PacketNumber - tau packet
Kōwhiringa - kōwhiringa kawa taapiri. Mo te putea tuatahi, ka whakamahia hei tohu i te rahi o te karere
Ko nga haki e whai ake nei:
FirstPacket - te kete tuatahi o te karere
NoAsk - karekau te karere e hiahia kia whakahoehia he tikanga mihi
LastPacket - te kete whakamutunga o te karere
RequestForPacket - mokete whakau, tono ranei mo te kete kua ngaro
Ngā mātāpono whānui o te kawa
I te mea ko te UDP Whakapono e aro ana ki te tuku karere pono i waenga i nga pona e rua, me kaha ki te whakatu hononga ki tera taha. Hei whakarite hononga, ka tukuna e te kaituku he paatete me te haki FirstPacket, ko te whakautu ki te mea ka whakapumautia te hononga. Ko nga putea whakautu katoa, me etahi atu kupu, ko nga putea mihi, ka tautuhi i nga wa katoa te uara o te mara PacketNumber ma te kotahi neke atu i te uara PacketNumber nui rawa atu o nga paatete kua whiwhi angitu. Ko te mara Kōwhiringa mo te pākete tuatahi i tukuna ko te rahi o te karere.
Ka whakamahia he tikanga rite ki te whakamutu i tetahi hononga. Kua whakaritea te haki LastPacket ki te kete whakamutunga o te karere. I roto i te kete whakautu, ka tohuhia te nama o te paatete whakamutunga + 1, ko te tikanga mo te taha tango te tikanga o te tukunga o te karere. Te whakatu hononga me te hoahoa whakamutu:
Ina oti te hononga, ka timata te whakawhiti raraunga. Ka tukuna nga raraunga ki nga poraka o nga paatete. Kei ia poraka, haunga te mea whakamutunga, he maha nga paatete. He rite ki te rahinga matapihi whiwhi/tuku. He iti ake pea nga putea o te paraka raraunga whakamutunga. I muri i te tuku i ia poraka, ka tatari te taha tuku mo te whakapumautanga tuku, he tono ranei kia tukuna ano nga paatete ngaro, ka waiho te matapihi whiwhi/tuku kia tuwhera ki te whiwhi whakautu. I muri i te whakapumautanga o te tuku poraka, ka huri te matapihi whiwhi / tuku ka tukuna te poraka o muri mai.
Ka whiwhi te taha tango i nga paatete. Ka takina ia kete ki te kite mena ka taka ki roto i te matapihi tuku. Ko nga paatete me nga taarua kaore e taka ki te matapihi ka tātarihia. No te mea Mena kua whakatauhia te rahi o te matapihi me te rite mo te kaiwhiwhi me te kaituku, na i te mea ka tukuna he poraka o nga putea kaore he ngaro, ka nekehia te matapihi ki te tango i nga paanui o te poraka o muri o nga raraunga me te whakapumautanga tuku. tukuna. Mena karekau te matapihi e whakakiia i roto i te waa i whakaritea e te kaima mahi, katahi ka timata te haki kaore ano kia tukuna mai nga kete ka tukuna ano nga tono mo te tuku. Hoahoa Whakawhiti Anō:
Nga waahi me nga kawa kawa
He maha nga take kaore e taea te whakatuu hononga. Hei tauira, mena kei te tuimotu te roopu whiwhi. I tenei keehi, i te wa e ngana ana ki te whakatu hononga, ka kati te hononga i te wa mutunga. Ko te whakatinanatanga UDP Whakapono e whakamahi ana i nga taima e rua hei whakarite i nga waahi. Ko te tuatahi, ko te taima mahi, ka whakamahia hei tatari mo te whakautu mai i te kaihautu mamao. Mena ka pupuhi ki te taha o te kaituku, ka tukuna ano te paakete whakamutunga. Mena ka pau te taima ki te kaiwhiwhi, ka mahia he haki mo nga paatete ngaro ka tukuna nga tono mo te tuku ano.
Ko te taima tuarua e hiahiatia ana hei kati i te hononga mena he kore korero i waenga i nga pona. Mo te taha kaituku, ka timata i muri tonu i te paunga o te wa mahi, me te tatari mo te whakautu mai i te pona mamao. Mena karekau he whakautu i roto i te waa kua tohua, ka mutu te hononga ka tukuna nga rauemi. Mo te taha whiwhi, ka timata te matama kati hononga i muri i te paunga o te taima mahi e rua nga wa. He mea tika tenei hei inihua i te ngaro o te kete whakau. Ka pau te taima, ka mutu ano te hononga ka tukuna nga rauemi.
Hoahoa whenua tuku UDP pono
Ka whakatinanahia nga maataapono o te kawa i roto i te miihini ahua mutunga, ko ia kawanatanga te kawenga mo tetahi arorau o te tukatuka putea.
Hoahoa State UDP pono:
Katia - ehara i te mea he whenua, he timatanga me te mutunga mo te miihini. Mo te kawanatanga Katia ka riro mai he poraka mana tuku, ma te whakamahi i te tūmau UDP tukutahi, ka tuku atu i nga paakete ki nga hononga e tika ana, ka timata i te tukatuka kawanatanga.
TuatahiPacketTukua – te ahua tuatahi kei roto te hononga puta i te wa ka tukuna te karere.
I roto i tenei ahua, ka tukuna te putea tuatahi mo nga karere noa. Mo nga karere karekau he whakapumautanga tuku, koinei anake te whenua ka tukuna te katoa o nga korero.
Huringa Tukunga – te ahua whenua mo te tuku i nga paanui karere.
Te whakawhiti ki a ia mai i te kawanatanga TuatahiPacketTukua ka mahia i muri i te tukunga o te kete tuatahi o te karere. I roto i tenei ahuatanga ka tae mai nga mihi me nga tono mo te tuku ano. Ka taea te puta mai i roto i nga keehi e rua - mena ka angitu te tuku o te karere, ma te wa poto ranei.
Peeke Tuatahi Kua riro – te ahua tuatahi mo te kaiwhiwhi o te karere.
Ka tirotirohia te tika o te timatanga o te tuku, ka hangaia nga hanganga e tika ana, ka tukuna he mihi mo te whiwhinga o te kete tuatahi.
Mo te panui kei roto i te paatete kotahi ka tukuna me te kore e whakamahi tohu o te tuku, koinei anake te kawanatanga. I muri i te tukatuka i taua karere, ka kati te hononga.
Huihuinga – te ahua taketake mo te whiwhi putea karere.
Ka tuhia e ia nga paatete ki te rokiroki rangitahi, ka tirohia mo te ngaronga o te paatete, ka tuku mihi mo te tukunga o te poraka o nga paanui me te katoa o te karere, ka tuku tono mo te tuku ano i nga paanui kua ngaro. Mena ka angitu te whiwhinga o te panui katoa, ka uru te hononga ki te kawanatanga oti, ki te kore, ka puta he waahi.
oti – katia te hononga i te mea ka angitu te whiwhinga o te karere katoa.
He mea tika tenei ahua mo te huihuinga o te karere me te keehi i te wa i ngaro ai te whakapumautanga tuku o te karere i te huarahi ki te kaituku. Ka puta tenei ahua ma te waahi, engari ka kiia te hononga kua katia pai.
Hohonu atu ki te waehere. wae mana tuku
Ko tetahi o nga mea matua o te UDP Whakapono ko te poraka mana tuku. Ko te mahi o tenei poraka ko te penapena i nga hononga o naianei me nga huānga awhina, te tohatoha i nga paatete taumai ki nga hononga e tika ana, te whakarato i tetahi atanga mo te tuku paatete ki tetahi hononga, me te whakatinana i te API kawa. Ka whiwhi te poraka mana tuku i nga paatete mai i te paparanga UDP ka tukuna atu ki te miihini kawanatanga mo te tukatuka. Hei tango i nga paatete, ka whakamahia he tūmau UDP tukutahi. Ko etahi mema o te akomanga ReliableUdpConnectionControlBlock:
internal class ReliableUdpConnectionControlBlock : IDisposable
{
// массив байт для указанного ключа. Используется для сборки входящих сообщений
public ConcurrentDictionary<Tuple<EndPoint, Int32>, byte[]> IncomingStreams { get; private set;}
// массив байт для указанного ключа. Используется для отправки исходящих сообщений.
public ConcurrentDictionary<Tuple<EndPoint, Int32>, byte[]> OutcomingStreams { get; private set; }
// connection record для указанного ключа.
private readonly ConcurrentDictionary<Tuple<EndPoint, Int32>, ReliableUdpConnectionRecord> m_listOfHandlers;
// список подписчиков на сообщения.
private readonly List<ReliableUdpSubscribeObject> m_subscribers;
// локальный сокет
private Socket m_socketIn;
// порт для входящих сообщений
private int m_port;
// локальный IP адрес
private IPAddress m_ipAddress;
// локальная конечная точка
public IPEndPoint LocalEndpoint { get; private set; }
// коллекция предварительно инициализированных
// состояний конечного автомата
public StatesCollection States { get; private set; }
// генератор случайных чисел. Используется для создания TransmissionId
private readonly RNGCryptoServiceProvider m_randomCrypto;
//...
}
Te whakatinanatanga o te tūmau UDP tukutahi:
private void Receive()
{
EndPoint connectedClient = new IPEndPoint(IPAddress.Any, 0);
// создаем новый буфер, для каждого socket.BeginReceiveFrom
byte[] buffer = new byte[DefaultMaxPacketSize + ReliableUdpHeader.Length];
// передаем буфер в качестве параметра для асинхронного метода
this.m_socketIn.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref connectedClient, EndReceive, buffer);
}
private void EndReceive(IAsyncResult ar)
{
EndPoint connectedClient = new IPEndPoint(IPAddress.Any, 0);
int bytesRead = this.m_socketIn.EndReceiveFrom(ar, ref connectedClient);
//пакет получен, готовы принимать следующий
Receive();
// т.к. простейший способ решить вопрос с буфером - получить ссылку на него
// из IAsyncResult.AsyncState
byte[] bytes = ((byte[]) ar.AsyncState).Slice(0, bytesRead);
// получаем заголовок пакета
ReliableUdpHeader header;
if (!ReliableUdpStateTools.ReadReliableUdpHeader(bytes, out header))
{
// пришел некорректный пакет - отбрасываем его
return;
}
// конструируем ключ для определения connection record’а для пакета
Tuple<EndPoint, Int32> key = new Tuple<EndPoint, Int32>(connectedClient, header.TransmissionId);
// получаем существующую connection record или создаем новую
ReliableUdpConnectionRecord record = m_listOfHandlers.GetOrAdd(key, new ReliableUdpConnectionRecord(key, this, header.ReliableUdpMessageType));
// запускаем пакет в обработку в конечный автомат
record.State.ReceivePacket(record, header, bytes);
}
Mo ia whakawhitinga karere, ka hangaia he hanganga kei roto nga korero mo te hononga. Ko taua hanganga ka kiia rekoata hononga. Ko etahi mema o te akomanga ReliableUdpConnectionRecord:
internal class ReliableUdpConnectionRecord : IDisposable
{
// массив байт с сообщением
public byte[] IncomingStream { get; set; }
// ссылка на состояние конечного автомата
public ReliableUdpState State { get; set; }
// пара, однозначно определяющая connection record
// в блоке управления передачей
public Tuple<EndPoint, Int32> Key { get; private set;}
// нижняя граница приемного окна
public int WindowLowerBound;
// размер окна передачи
public readonly int WindowSize;
// номер пакета для отправки
public int SndNext;
// количество пакетов для отправки
public int NumberOfPackets;
// номер передачи (именно он и есть вторая часть Tuple)
// для каждого сообщения свой
public readonly Int32 TransmissionId;
// удаленный IP endpoint – собственно получатель сообщения
public readonly IPEndPoint RemoteClient;
// размер пакета, во избежание фрагментации на IP уровне
// не должен превышать MTU – (IP.Header + UDP.Header + RelaibleUDP.Header)
public readonly int BufferSize;
// блок управления передачей
public readonly ReliableUdpConnectionControlBlock Tcb;
// инкапсулирует результаты асинхронной операции для BeginSendMessage/EndSendMessage
public readonly AsyncResultSendMessage AsyncResult;
// не отправлять пакеты подтверждения
public bool IsNoAnswerNeeded;
// последний корректно полученный пакет (всегда устанавливается в наибольший номер)
public int RcvCurrent;
// массив с номерами потерянных пакетов
public int[] LostPackets { get; private set; }
// пришел ли последний пакет. Используется как bool.
public int IsLastPacketReceived = 0;
//...
}
Hohonu atu ki te waehere. āhua
Ka whakatinanahia e nga whenua te miihini kawanatanga o te kawa UDP Whakapono, kei reira te tukatuka matua o nga paatete. Ko te akomanga waitara ReliableUdpState he atanga mo te kawanatanga:
Ko te arorau katoa o te kawa ka whakatinanahia e nga karaehe kua whakaatuhia i runga ake nei, me tetahi akomanga awhina e whakarato ana i nga tikanga tuuturu, penei, hei tauira, te hanga i te pane ReliableUdp mai i te rekoata hononga.
I muri mai, ka whakaarohia e maatau te whakatinanatanga o nga tikanga atanga e whakatau ana i nga algorithms taketake o te kawa.
Tikanga DisposeByTimeout
Ko te tikanga DisposeByTimeout te kawenga mo te tuku rauemi hononga i muri i te waahi me te tohu i te tuku karere angitu/kore. ReliableUdpState.DisposeByTimeout:
Ka whakakorea noa i te kawanatanga oti. Kua oti.DisposeByTimeout:
protected override void DisposeByTimeout(object record)
{
ReliableUdpConnectionRecord connectionRecord = (ReliableUdpConnectionRecord) record;
// сообщаем об успешном получении сообщения
SetAsCompleted(connectionRecord);
}
Tikanga ProcessPackets
Ko te tikanga ProcessPackets te kawenga mo te tukatuka taapiri o tetahi kete, kete ranei. Ka waea tika mai, ma te paatata tatari ranei.
Taea Huihuinga kua whakakorehia te tikanga me te kawenga mo te tirotiro mo nga putea ngaro me te whakawhiti ki te kawanatanga oti, i te mea ka riro mai te kete whakamutunga ka tukuna he haki angitu Huihuinga.ProcessPackets:
public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
if (connectionRecord.IsDone != 0)
return;
if (!ReliableUdpStateTools.CheckForNoPacketLoss(connectionRecord, connectionRecord.IsLastPacketReceived != 0))
{
// есть потерянные пакеты, отсылаем запросы на них
foreach (int seqNum in connectionRecord.LostPackets)
{
if (seqNum != 0)
{
ReliableUdpStateTools.SendAskForLostPacket(connectionRecord, seqNum);
}
}
// устанавливаем таймер во второй раз, для повторной попытки передачи
if (!connectionRecord.TimerSecondTry)
{
connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
connectionRecord.TimerSecondTry = true;
return;
}
// если после двух попыток срабатываний WaitForPacketTimer
// не удалось получить пакеты - запускаем таймер завершения соединения
StartCloseWaitTimer(connectionRecord);
}
else if (connectionRecord.IsLastPacketReceived != 0)
// успешная проверка
{
// высылаем подтверждение о получении блока данных
ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
connectionRecord.State = connectionRecord.Tcb.States.Completed;
connectionRecord.State.ProcessPackets(connectionRecord);
// вместо моментальной реализации ресурсов
// запускаем таймер, на случай, если
// если последний ack не дойдет до отправителя и он запросит его снова.
// по срабатыванию таймера - реализуем ресурсы
// в состоянии Completed метод таймера переопределен
StartCloseWaitTimer(connectionRecord);
}
// это случай, когда ack на блок пакетов был потерян
else
{
if (!connectionRecord.TimerSecondTry)
{
ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
connectionRecord.TimerSecondTry = true;
return;
}
// запускаем таймер завершения соединения
StartCloseWaitTimer(connectionRecord);
}
}
Taea Huringa Tukunga ka karangahia tenei tikanga i runga i te matawā anake, a ko te kawenga mo te tuku ano i te karere whakamutunga, me te whakaahei i te taima kati hononga. SendingCycle.ProcessPackets:
public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
if (connectionRecord.IsDone != 0)
return;
// отправляем повторно последний пакет
// ( в случае восстановления соединения узел-приемник заново отправит запросы, которые до него не дошли)
ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.RetransmissionCreateUdpPayload(connectionRecord, connectionRecord.SndNext - 1));
// включаем таймер CloseWait – для ожидания восстановления соединения или его завершения
StartCloseWaitTimer(connectionRecord);
}
Taea oti ko te tikanga ka mutu te mahi oma me te tuku i te karere ki nga kaiohauru. Kua oti.ProcessPackets:
public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
if (connectionRecord.WaitForPacketsTimer != null)
connectionRecord.WaitForPacketsTimer.Dispose();
// собираем сообщение и передаем его подписчикам
ReliableUdpStateTools.CreateMessageFromMemoryStream(connectionRecord);
}
ReceivePacket Tikanga
Taea Peeke Tuatahi Kua riro Ko te mahi matua o te tikanga ko te whakatau mena kua tae mai te paanui karere tuatahi ki te atanga, me te kohi karere kei roto i te kete kotahi. FirstPacketReceived.ReceivePacket:
public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
if (!header.Flags.HasFlag(ReliableUdpHeaderFlags.FirstPacket))
// отбрасываем пакет
return;
// комбинация двух флагов - FirstPacket и LastPacket - говорит что у нас единственное сообщение
if (header.Flags.HasFlag(ReliableUdpHeaderFlags.FirstPacket) &
header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
{
ReliableUdpStateTools.CreateMessageFromSinglePacket(connectionRecord, header, payload.Slice(ReliableUdpHeader.Length, payload.Length));
if (!header.Flags.HasFlag(ReliableUdpHeaderFlags.NoAsk))
{
// отправляем пакет подтверждение
ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
}
SetAsCompleted(connectionRecord);
return;
}
// by design все packet numbers начинаются с 0;
if (header.PacketNumber != 0)
return;
ReliableUdpStateTools.InitIncomingBytesStorage(connectionRecord, header);
ReliableUdpStateTools.WritePacketData(connectionRecord, header, payload);
// считаем кол-во пакетов, которые должны прийти
connectionRecord.NumberOfPackets = (int)Math.Ceiling((double) ((double) connectionRecord.IncomingStream.Length/(double) connectionRecord.BufferSize));
// записываем номер последнего полученного пакета (0)
connectionRecord.RcvCurrent = header.PacketNumber;
// после сдвинули окно приема на 1
connectionRecord.WindowLowerBound++;
// переключаем состояние
connectionRecord.State = connectionRecord.Tcb.States.Assembling;
// если не требуется механизм подтверждение
// запускаем таймер который высвободит все структуры
if (header.Flags.HasFlag(ReliableUdpHeaderFlags.NoAsk))
{
connectionRecord.CloseWaitTimer = new Timer(DisposeByTimeout, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
}
else
{
ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
connectionRecord.WaitForPacketsTimer = new Timer(CheckByTimer, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
}
}
Taea Huringa Tukunga kua whakakorehia tenei tikanga ki te whakaae ki nga mihi tuku me nga tono tuku ano. SendingCycle.ReceivePacket:
public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
if (connectionRecord.IsDone != 0)
return;
if (!header.Flags.HasFlag(ReliableUdpHeaderFlags.RequestForPacket))
return;
// расчет конечной границы окна
// берется граница окна + 1, для получения подтверждений доставки
int windowHighestBound = Math.Min((connectionRecord.WindowLowerBound + connectionRecord.WindowSize), (connectionRecord.NumberOfPackets));
// проверка на попадание в окно
if (header.PacketNumber < connectionRecord.WindowLowerBound || header.PacketNumber > windowHighestBound)
return;
connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
if (connectionRecord.CloseWaitTimer != null)
connectionRecord.CloseWaitTimer.Change(-1, -1);
// проверить на последний пакет:
if (header.PacketNumber == connectionRecord.NumberOfPackets)
{
// передача завершена
Interlocked.Increment(ref connectionRecord.IsDone);
SetAsCompleted(connectionRecord);
return;
}
// это ответ на первый пакет c подтверждением
if ((header.Flags.HasFlag(ReliableUdpHeaderFlags.FirstPacket) && header.PacketNumber == 1))
{
// без сдвига окна
SendPacket(connectionRecord);
}
// пришло подтверждение о получении блока данных
else if (header.PacketNumber == windowHighestBound)
{
// сдвигаем окно прием/передачи
connectionRecord.WindowLowerBound += connectionRecord.WindowSize;
// обнуляем массив контроля передачи
connectionRecord.WindowControlArray.Nullify();
// отправляем блок пакетов
SendPacket(connectionRecord);
}
// это запрос на повторную передачу – отправляем требуемый пакет
else
ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.RetransmissionCreateUdpPayload(connectionRecord, header.PacketNumber));
}
Taea Huihuinga i roto i te tikanga ReceivePacket, ko te mahi matua o te whakahiato i te karere mai i nga paatete taumai ka puta. Huihuinga.ReceivePacket:
public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
if (connectionRecord.IsDone != 0)
return;
// обработка пакетов с отключенным механизмом подтверждения доставки
if (header.Flags.HasFlag(ReliableUdpHeaderFlags.NoAsk))
{
// сбрасываем таймер
connectionRecord.CloseWaitTimer.Change(connectionRecord.LongTimerPeriod, -1);
// записываем данные
ReliableUdpStateTools.WritePacketData(connectionRecord, header, payload);
// если получили пакет с последним флагом - делаем завершаем
if (header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
{
connectionRecord.State = connectionRecord.Tcb.States.Completed;
connectionRecord.State.ProcessPackets(connectionRecord);
}
return;
}
// расчет конечной границы окна
int windowHighestBound = Math.Min((connectionRecord.WindowLowerBound + connectionRecord.WindowSize - 1), (connectionRecord.NumberOfPackets - 1));
// отбрасываем не попадающие в окно пакеты
if (header.PacketNumber < connectionRecord.WindowLowerBound || header.PacketNumber > (windowHighestBound))
return;
// отбрасываем дубликаты
if (connectionRecord.WindowControlArray.Contains(header.PacketNumber))
return;
// записываем данные
ReliableUdpStateTools.WritePacketData(connectionRecord, header, payload);
// увеличиваем счетчик пакетов
connectionRecord.PacketCounter++;
// записываем в массив управления окном текущий номер пакета
connectionRecord.WindowControlArray[header.PacketNumber - connectionRecord.WindowLowerBound] = header.PacketNumber;
// устанавливаем наибольший пришедший пакет
if (header.PacketNumber > connectionRecord.RcvCurrent)
connectionRecord.RcvCurrent = header.PacketNumber;
// перезапускам таймеры
connectionRecord.TimerSecondTry = false;
connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
if (connectionRecord.CloseWaitTimer != null)
connectionRecord.CloseWaitTimer.Change(-1, -1);
// если пришел последний пакет
if (header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
{
Interlocked.Increment(ref connectionRecord.IsLastPacketReceived);
}
// если нам пришли все пакеты окна, то сбрасываем счетчик
// и высылаем пакет подтверждение
else if (connectionRecord.PacketCounter == connectionRecord.WindowSize)
{
// сбрасываем счетчик.
connectionRecord.PacketCounter = 0;
// сдвинули окно передачи
connectionRecord.WindowLowerBound += connectionRecord.WindowSize;
// обнуление массива управления передачей
connectionRecord.WindowControlArray.Nullify();
ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
}
// если последний пакет уже имеется
if (Thread.VolatileRead(ref connectionRecord.IsLastPacketReceived) != 0)
{
// проверяем пакеты
ProcessPackets(connectionRecord);
}
}
Taea oti Ko te mahi anake o te tikanga ko te tuku mihi ano mo te tukunga angitu o te karere. Kua oti.ReceivePacket:
public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
// повторная отправка последнего пакета в связи с тем,
// что последний ack не дошел до отправителя
if (header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
{
ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
}
}
Tukua Tikanga Pakete
Taea TuatahiPacketTukua ka tukuna e tenei tikanga te putea tuatahi o nga raraunga, ki te kore e hiahiatia e te karere te whakapumautanga tuku, ko te karere katoa. FirstPacketSending.SendPacket:
public override void SendPacket(ReliableUdpConnectionRecord connectionRecord)
{
connectionRecord.PacketCounter = 0;
connectionRecord.SndNext = 0;
connectionRecord.WindowLowerBound = 0;
// если подтверждения не требуется - отправляем все пакеты
// и высвобождаем ресурсы
if (connectionRecord.IsNoAnswerNeeded)
{
// Здесь происходит отправка As Is
do
{
ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, ReliableUdpStateTools. CreateReliableUdpHeader(connectionRecord)));
connectionRecord.SndNext++;
} while (connectionRecord.SndNext < connectionRecord.NumberOfPackets);
SetAsCompleted(connectionRecord);
return;
}
// создаем заголовок пакета и отправляем его
ReliableUdpHeader header = ReliableUdpStateTools.CreateReliableUdpHeader(connectionRecord);
ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, header));
// увеличиваем счетчик
connectionRecord.SndNext++;
// сдвигаем окно
connectionRecord.WindowLowerBound++;
connectionRecord.State = connectionRecord.Tcb.States.SendingCycle;
// Запускаем таймер
connectionRecord.WaitForPacketsTimer = new Timer(CheckByTimer, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
}
Taea Huringa Tukunga i tenei tikanga, ka tukuna he poraka o nga paatete. SendingCycle.SendPacket:
public override void SendPacket(ReliableUdpConnectionRecord connectionRecord)
{
// отправляем блок пакетов
for (connectionRecord.PacketCounter = 0;
connectionRecord.PacketCounter < connectionRecord.WindowSize &&
connectionRecord.SndNext < connectionRecord.NumberOfPackets;
connectionRecord.PacketCounter++)
{
ReliableUdpHeader header = ReliableUdpStateTools.CreateReliableUdpHeader(connectionRecord);
ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, header));
connectionRecord.SndNext++;
}
// на случай большого окна передачи, перезапускаем таймер после отправки
connectionRecord.WaitForPacketsTimer.Change( connectionRecord.ShortTimerPeriod, -1 );
if ( connectionRecord.CloseWaitTimer != null )
{
connectionRecord.CloseWaitTimer.Change( -1, -1 );
}
}
Hohonu atu ki te waehere. Te Waihanga me te Whakapumau Hononga
Inaianei kua kite tatou i nga ahuatanga taketake me nga tikanga e whakamahia ana ki te hapai i nga kawanatanga, me wehewehe etahi tauira mo te mahi a te kawa i roto i nga korero taipitopito. Hoahoa tuku raraunga i raro i nga tikanga noa:
Whakaarohia nga korero mo te hanganga rekoata hononga ki te hono me te tuku i te kete tuatahi. Ko te whakawhitinga i nga wa katoa ka timatahia e te tono e karanga ana i te API karere tuku. I muri mai, ka karangahia te tikanga StartTransmission o te poraka mana tuku, ka timata te tuku raraunga mo te karere hou. Te hanga hononga putaatu:
private void StartTransmission(ReliableUdpMessage reliableUdpMessage, EndPoint endPoint, AsyncResultSendMessage asyncResult)
{
if (m_isListenerStarted == 0)
{
if (this.LocalEndpoint == null)
{
throw new ArgumentNullException( "", "You must use constructor with parameters or start listener before sending message" );
}
// запускаем обработку входящих пакетов
StartListener(LocalEndpoint);
}
// создаем ключ для словаря, на основе EndPoint и ReliableUdpHeader.TransmissionId
byte[] transmissionId = new byte[4];
// создаем случайный номер transmissionId
m_randomCrypto.GetBytes(transmissionId);
Tuple<EndPoint, Int32> key = new Tuple<EndPoint, Int32>(endPoint, BitConverter.ToInt32(transmissionId, 0));
// создаем новую запись для соединения и проверяем,
// существует ли уже такой номер в наших словарях
if (!m_listOfHandlers.TryAdd(key, new ReliableUdpConnectionRecord(key, this, reliableUdpMessage, asyncResult)))
{
// если существует – то повторно генерируем случайный номер
m_randomCrypto.GetBytes(transmissionId);
key = new Tuple<EndPoint, Int32>(endPoint, BitConverter.ToInt32(transmissionId, 0));
if (!m_listOfHandlers.TryAdd(key, new ReliableUdpConnectionRecord(key, this, reliableUdpMessage, asyncResult)))
// если снова не удалось – генерируем исключение
throw new ArgumentException("Pair TransmissionId & EndPoint is already exists in the dictionary");
}
// запустили состояние в обработку
m_listOfHandlers[key].State.SendPacket(m_listOfHandlers[key]);
}
Te tuku i te kete tuatahi (FirstPacketSending state):
public override void SendPacket(ReliableUdpConnectionRecord connectionRecord)
{
connectionRecord.PacketCounter = 0;
connectionRecord.SndNext = 0;
connectionRecord.WindowLowerBound = 0;
// ...
// создаем заголовок пакета и отправляем его
ReliableUdpHeader header = ReliableUdpStateTools.CreateReliableUdpHeader(connectionRecord);
ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, header));
// увеличиваем счетчик
connectionRecord.SndNext++;
// сдвигаем окно
connectionRecord.WindowLowerBound++;
// переходим в состояние SendingCycle
connectionRecord.State = connectionRecord.Tcb.States.SendingCycle;
// Запускаем таймер
connectionRecord.WaitForPacketsTimer = new Timer(CheckByTimer, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
}
I muri i te tuku i te putea tuatahi, ka uru te kaituku ki te kawanatanga Huringa Tukunga – tatari mo te whakapumautanga o te tuku kete.
Ko te taha tango, ma te whakamahi i te tikanga EndReceive, ka whiwhi i te kete kua tukuna, ka hanga he hou rekoata hononga ka tukuna tenei kete, me te pane kua oti te whakamaarama, ki te tikanga ReceivePacket o te kawanatanga mo te tukatuka Peeke Tuatahi Kua riro Te hanga hononga ki te taha whiwhi:
private void EndReceive(IAsyncResult ar)
{
// ...
// пакет получен
// парсим заголовок пакета
ReliableUdpHeader header;
if (!ReliableUdpStateTools.ReadReliableUdpHeader(bytes, out header))
{
// пришел некорректный пакет - отбрасываем его
return;
}
// конструируем ключ для определения connection record’а для пакета
Tuple<EndPoint, Int32> key = new Tuple<EndPoint, Int32>(connectedClient, header.TransmissionId);
// получаем существующую connection record или создаем новую
ReliableUdpConnectionRecord record = m_listOfHandlers.GetOrAdd(key, new ReliableUdpConnectionRecord(key, this, header. ReliableUdpMessageType));
// запускаем пакет в обработку в конечный автомат
record.State.ReceivePacket(record, header, bytes);
}
Te whiwhi i te kete tuatahi me te tuku mihi (FirstPacketReceived state):
public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
if (!header.Flags.HasFlag(ReliableUdpHeaderFlags.FirstPacket))
// отбрасываем пакет
return;
// ...
// by design все packet numbers начинаются с 0;
if (header.PacketNumber != 0)
return;
// инициализируем массив для хранения частей сообщения
ReliableUdpStateTools.InitIncomingBytesStorage(connectionRecord, header);
// записываем данные пакет в массив
ReliableUdpStateTools.WritePacketData(connectionRecord, header, payload);
// считаем кол-во пакетов, которые должны прийти
connectionRecord.NumberOfPackets = (int)Math.Ceiling((double) ((double) connectionRecord.IncomingStream.Length/(double) connectionRecord.BufferSize));
// записываем номер последнего полученного пакета (0)
connectionRecord.RcvCurrent = header.PacketNumber;
// после сдвинули окно приема на 1
connectionRecord.WindowLowerBound++;
// переключаем состояние
connectionRecord.State = connectionRecord.Tcb.States.Assembling;
if (/*если не требуется механизм подтверждение*/)
// ...
else
{
// отправляем подтверждение
ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
connectionRecord.WaitForPacketsTimer = new Timer(CheckByTimer, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
}
}
Hohonu atu ki te waehere. Katia te hononga i te wa mutunga
Ko te whakahaere i te wa poto he waahanga nui o te UDP Whakapono. Whakaarohia he tauira i rahua ai te node takawaenga, ka kore e taea te tuku raraunga ki nga taha e rua. Hoahoa mo te kati i tetahi hononga ma te waahi:
Ka kitea mai i te hoahoa, ka timata te matama mahi a te kaituku i muri tonu i te tuku i tetahi poraka o nga paatete. Ka tupu tenei i roto i te tikanga SendPacket o te kawanatanga Huringa Tukunga. Whakahohe ana i te taima mahi (te ahua o teSendingCycle):
public override void SendPacket(ReliableUdpConnectionRecord connectionRecord)
{
// отправляем блок пакетов
// ...
// перезапускаем таймер после отправки
connectionRecord.WaitForPacketsTimer.Change( connectionRecord.ShortTimerPeriod, -1 );
if ( connectionRecord.CloseWaitTimer != null )
connectionRecord.CloseWaitTimer.Change( -1, -1 );
}
Ka whakatauhia nga taima ka hangaia te hononga. Ko te ShortTimerPeriod taunoa he 5 hēkona. I roto i te tauira, kua whakaritea ki te 1,5 hēkona.
Mo te hononga taumai, ka timata te taima i muri i te whiwhinga o te kete raraunga taumai whakamutunga, ka puta tenei i roto i te tikanga ReceivePacket o te kawanatanga. Huihuinga Whakahohe ana i te taima mahi (Te ahua Huihuinga):
Karekau he kete i tae mai i te hononga taumai i te wa e tatari ana mo te taima mahi. Ka pahemo te taima ka karangahia te tikanga ProcessPackets, i kitea ai nga paatete ngaro ka tukuna ano nga tono tuku mo te wa tuatahi. Te tuku tono tuku ano (Te ahua Huihuinga):
public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
// ...
if (/*проверка на потерянные пакеты */)
{
// отправляем запросы на повторную доставку
// устанавливаем таймер во второй раз, для повторной попытки передачи
if (!connectionRecord.TimerSecondTry)
{
connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
connectionRecord.TimerSecondTry = true;
return;
}
// если после двух попыток срабатываний WaitForPacketTimer
// не удалось получить пакеты - запускаем таймер завершения соединения
StartCloseWaitTimer(connectionRecord);
}
else if (/*пришел последний пакет и успешная проверка */)
{
// ...
StartCloseWaitTimer(connectionRecord);
}
// если ack на блок пакетов был потерян
else
{
if (!connectionRecord.TimerSecondTry)
{
// повторно отсылаем ack
connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
connectionRecord.TimerSecondTry = true;
return;
}
// запускаем таймер завершения соединения
StartCloseWaitTimer(connectionRecord);
}
}
Kua tautuhia te taurangi TimerSecondTry ki pono. Ko tenei taurangi te kawenga mo te whakaara ano i te taima mahi.
I te taha o te kaituku, ka puta ano te matama mahi, ka tukuna ano te paakete whakamutunga. Whakahohe ana i te taima kati hononga (te ahua o teSendingCycle):
public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
// ...
// отправляем повторно последний пакет
// ...
// включаем таймер CloseWait – для ожидания восстановления соединения или его завершения
StartCloseWaitTimer(connectionRecord);
}
I muri i tera, ka timata te matama kati hononga i te hononga putaatu. ReliableUdpState.StartCloseWaitTimer:
protected void StartCloseWaitTimer(ReliableUdpConnectionRecord connectionRecord)
{
if (connectionRecord.CloseWaitTimer != null)
connectionRecord.CloseWaitTimer.Change(connectionRecord.LongTimerPeriod, -1);
else
connectionRecord.CloseWaitTimer = new Timer(DisposeByTimeout, connectionRecord, connectionRecord.LongTimerPeriod, -1);
}
He 30 hēkona te taunoa o te wā kati matawā hononga.
Whai muri i te wa poto, ka mura ano te kaima mahi i te taha o te kaiwhiwhi, ka tukuna ano nga tono, ka mutu ka tiimata te wa kati hononga mo te hononga taumai
Ka pa ana nga taima kati, ka tukuna nga rauemi katoa o nga rekoata hononga e rua. Ka whakaatu te kaituku i te kore tuku ki te tono whakarunga (tirohia API UDP pono). Te tuku rauemi rekoata hononga:
public void Dispose()
{
try
{
System.Threading.Monitor.Enter(this.LockerReceive);
}
finally
{
Interlocked.Increment(ref this.IsDone);
if (WaitForPacketsTimer != null)
{
WaitForPacketsTimer.Dispose();
}
if (CloseWaitTimer != null)
{
CloseWaitTimer.Dispose();
}
byte[] stream;
Tcb.IncomingStreams.TryRemove(Key, out stream);
stream = null;
Tcb.OutcomingStreams.TryRemove(Key, out stream);
stream = null;
System.Threading.Monitor.Exit(this.LockerReceive);
}
}
Hohonu atu ki te waehere. Te whakaora i te whakawhiti raraunga
Hoahoa whakaora tuku raraunga mena ka ngaro te kete:
Ka rite ki te korero kua korerohia mo te kati i te hononga i te wa mutunga, ka pau te wa mahi, ka tirohia e te kaiwhiwhi mo nga putea kua ngaro. Mena kua ngaro te kete, ka whakahiatohia he rarangi o te maha o nga paakete kaore i tae ki te kaiwhiwhi. Ka whakauruhia enei nama ki roto i te rarangi LostPackets o tetahi hononga motuhake, ka tukuna nga tono mo te tuku ano. Te tuku tono ki te tuku ano i nga kete (Te ahua Huihuinga):
public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
//...
if (!ReliableUdpStateTools.CheckForNoPacketLoss(connectionRecord, connectionRecord.IsLastPacketReceived != 0))
{
// есть потерянные пакеты, отсылаем запросы на них
foreach (int seqNum in connectionRecord.LostPackets)
{
if (seqNum != 0)
{
ReliableUdpStateTools.SendAskForLostPacket(connectionRecord, seqNum);
}
}
// ...
}
}
Ka whakaae te kaituku i te tono tuku ano ka tukuna atu nga paakete kua ngaro. He mea tika kia mohio koe i tenei wa kua timata te kaituku i te wa kati hononga, a, ka tae mai he tono, ka tautuhi ano. Te tuku ano i nga kete kua ngaro (te ahua o teSendingCycle):
public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
// ...
connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
// сброс таймера закрытия соединения
if (connectionRecord.CloseWaitTimer != null)
connectionRecord.CloseWaitTimer.Change(-1, -1);
// ...
// это запрос на повторную передачу – отправляем требуемый пакет
else
ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.RetransmissionCreateUdpPayload(connectionRecord, header.PacketNumber));
}
Ko te paatete riri (pakete #3 kei te hoahoa) ka riro mai i te hononga taumai. Ka mahia he haki ki te kite mena kua ki tonu te matapihi whiwhinga ka whakahokia mai ano te tuku raraunga. Te tirotiro mo nga patu i te matapihi whiwhi (te ahua Huihuinga):
public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
// ...
// увеличиваем счетчик пакетов
connectionRecord.PacketCounter++;
// записываем в массив управления окном текущий номер пакета
connectionRecord.WindowControlArray[header.PacketNumber - connectionRecord.WindowLowerBound] = header.PacketNumber;
// устанавливаем наибольший пришедший пакет
if (header.PacketNumber > connectionRecord.RcvCurrent)
connectionRecord.RcvCurrent = header.PacketNumber;
// перезапускам таймеры
connectionRecord.TimerSecondTry = false;
connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
if (connectionRecord.CloseWaitTimer != null)
connectionRecord.CloseWaitTimer.Change(-1, -1);
// ...
// если нам пришли все пакеты окна, то сбрасываем счетчик
// и высылаем пакет подтверждение
else if (connectionRecord.PacketCounter == connectionRecord.WindowSize)
{
// сбрасываем счетчик.
connectionRecord.PacketCounter = 0;
// сдвинули окно передачи
connectionRecord.WindowLowerBound += connectionRecord.WindowSize;
// обнуление массива управления передачей
connectionRecord.WindowControlArray.Nullify();
ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
}
// ...
}
API UDP pono
Ki te taunekeneke ki te kawa whakawhiti raraunga, kei reira he akomanga Udp Whakapono tuwhera, he takai i runga i te poraka mana whakawhiti. Anei nga mema tino nui o te akomanga:
public sealed class ReliableUdp : IDisposable
{
// получает локальную конечную точку
public IPEndPoint LocalEndpoint
// создает экземпляр ReliableUdp и запускает
// прослушивание входящих пакетов на указанном IP адресе
// и порту. Значение 0 для порта означает использование
// динамически выделенного порта
public ReliableUdp(IPAddress localAddress, int port = 0)
// подписка на получение входящих сообщений
public ReliableUdpSubscribeObject SubscribeOnMessages(ReliableUdpMessageCallback callback, ReliableUdpMessageTypes messageType = ReliableUdpMessageTypes.Any, IPEndPoint ipEndPoint = null)
// отписка от получения сообщений
public void Unsubscribe(ReliableUdpSubscribeObject subscribeObject)
// асинхронно отправить сообщение
// Примечание: совместимость с XP и Server 2003 не теряется, т.к. используется .NET Framework 4.0
public Task<bool> SendMessageAsync(ReliableUdpMessage reliableUdpMessage, IPEndPoint remoteEndPoint, CancellationToken cToken)
// начать асинхронную отправку сообщения
public IAsyncResult BeginSendMessage(ReliableUdpMessage reliableUdpMessage, IPEndPoint remoteEndPoint, AsyncCallback asyncCallback, Object state)
// получить результат асинхронной отправки
public bool EndSendMessage(IAsyncResult asyncResult)
// очистить ресурсы
public void Dispose()
}
Ka riro nga karere ma te ohaurunga. Tukua te waitohu mo te aratuka hoki:
public delegate void ReliableUdpMessageCallback( ReliableUdpMessage reliableUdpMessage, IPEndPoint remoteClient );
Karere:
public class ReliableUdpMessage
{
// тип сообщения, простое перечисление
public ReliableUdpMessageTypes Type { get; private set; }
// данные сообщения
public byte[] Body { get; private set; }
// если установлено в true – механизм подтверждения доставки будет отключен
// для передачи конкретного сообщения
public bool NoAsk { get; private set; }
}
Hei ohauru ki tetahi momo karere motuhake me/ranei tetahi kaituku motuhake, ka whakamahia nga tawhā e rua: ReliableUdpMessageTypes messageType me IPEndPoint ipEndPoint.
Momo Karere:
public enum ReliableUdpMessageTypes : short
{
// Любое
Any = 0,
// Запрос к STUN server
StunRequest = 1,
// Ответ от STUN server
StunResponse = 2,
// Передача файла
FileTransfer =3,
// ...
}
Ka tukuna te karere i te tukutahi; mo tenei, ka whakatinanahia e te kawa he tauira hotaka tukutahi:
public IAsyncResult BeginSendMessage(ReliableUdpMessage reliableUdpMessage, IPEndPoint remoteEndPoint, AsyncCallback asyncCallback, Object state)
Ko te hua o te tuku karere ka pono - mena kua tutuki pai te karere ki te kaiwhiwhi me te teka - mena ka kati te hononga i te wa mutunga:
public bool EndSendMessage(IAsyncResult asyncResult)
mutunga
He maha nga korero kaore i te korerohia i tenei tuhinga. Nga tikanga orite miro, otahi me te whakahaere hapa, te whakatinanatanga o nga tikanga tuku karere tukutahi. Engari ko te kaupapa matua o te kawa, ko te whakamaarama mo te arorau mo te tukatuka i nga paatete, te whakatu hononga, me te whakahaere i nga waahi, me marama ki a koe.
Ko te putanga whakaatu o te kawa tuku pono he pakari, he ngawari hoki ki te whakatutuki i nga whakaritenga kua tautuhia i mua. Engari e hiahia ana ahau ki te taapiri ka taea te whakapai ake te whakatinanatanga kua whakaahuatia. Hei tauira, ki te whakanui ake i te urunga me te huri whakahihiri i nga wa taima, ka taea te taapiri i nga tikanga penei i te matapihi reti me te RTT ki te kawa, ka whai hua ano ki te whakatinana i tetahi tikanga mo te whakatau MTU i waenga i nga pona hononga (engari mena ka tukuna nga karere nui) .
He mihi nui ki a koe mo to whakaaro, ka tatari ahau ki o korero me o korero.
PS Mo te hunga e hiahia ana ki nga korero, e hiahia ana ranei ki te whakamatautau i te kawa, te hono ki te kaupapa i runga i GitHube: Kaupapa UDP pono
Whakahōu: Tēnā koe mayorovp и sidristij mo te whakaaro ki te taapiri i tetahi mahi ki te atanga. Ko te hototahi o te whare pukapuka me nga punaha whakahaere tawhito kaore i te takahia, no te mea Ko te anga 4 e tautoko ana i te XP me te 2003 tūmau.