paint-brush
Unity Gerçek Zamanlı Çok Oyunculu, Bölüm 2: TCP, UDP, WebSocket Protokolleriile@dmitrii
3,401 okumalar
3,401 okumalar

Unity Gerçek Zamanlı Çok Oyunculu, Bölüm 2: TCP, UDP, WebSocket Protokolleri

ile Dmitrii Ivashchenko16m2023/08/06
Read on Terminal Reader
Read this story w/o Javascript

Çok uzun; Okumak

2023'teki Unity Ağ Ortamı serisi, gerçek zamanlı çok oyunculu oyunlarda veri iletim protokollerine odaklanmaya devam ediyor. OSI modelinin TCP ve UDP'li Aktarım Katmanı, oyuncular arasında optimum veri alışverişi için araştırıldı. TCP güvenilir veri teslimatı sağlar ancak gecikmelere neden olabilir; UDP ise potansiyel veri kaybıyla daha hızlı iletim sunar. TCP'ye dayalı uygulama düzeyinde bir protokol olan WebSocket, kalıcı çift yönlü iletişim sağlar ve gerçek zamanlı çok oyunculu oyunlar için uygundur. TCP ve UDP istemcileri ve sunucularının yanı sıra WebSocket istemcisi ve sunucusuna yönelik kod örnekleri, uygulama yaklaşımlarını göstermektedir. Protokol seçimi oyun gereksinimlerine bağlıdır; güvenilirlik için TCP, hız için UDP ve çift yönlü iletişim için WebSocket. Bir sonraki makale UDP kullanarak güvenilir veri aktarımının organize edilmesini ele alacak.
featured image - Unity Gerçek Zamanlı Çok Oyunculu, Bölüm 2: TCP, UDP, WebSocket Protokolleri
Dmitrii Ivashchenko HackerNoon profile picture
0-item
1-item


2023'te Unity Networking Ortamı ile ilgili makale serim devam ediyor! Bugünkü yazımızda gerçek zamanlı çok oyunculu oyunlarda kullanılan veri iletim protokolleri ele alınacak.


Herkese selamlar! Ben MY.GAMES'in Baş Yazılım Mühendisi Dmitrii Ivashchenko. Farklı ağ etkileşimi seviyelerinde hangi protokollerin mevcut olduğuna kısa bir genel bakışla başlayacağız.


İçeriğe Genel Bakış

  • OSI Seviyeleri
  • Geçiş kontrol protokolü
    • TCP İstemcisi
    • TCP Sunucusu
  • Kullanıcı Datagram Protokolü
    • UDP istemcisi
    • UDP Sunucusu
  • Web soketi
    • Websocket İstemcisi
    • Websoket Sunucusu
  • Çözüm


OSI Seviyeleri

OSI (Açık Sistemler Bağlantısı) modeli, bir iletişim sisteminin işlevlerini soyutlama düzeyleri açısından karakterize eden ve standartlaştıran kavramsal bir modeldir. Bu model 1978 yılında Uluslararası Standardizasyon Örgütü (ISO) tarafından geliştirilmiştir.

Yedi katmandan oluşur:


  1. Fiziksel Katman : Bu katman ham bitlerin kanal üzerinden iletilmesi ve alınmasıyla ilgilidir. Bu katmandaki protokoller, bit temsilleri, iletim hızları, fiziksel kablolar, kartlar ve konektör tasarımları dahil olmak üzere fiziksel arayüzü ve ortamın özelliklerini tanımlar.


  2. Veri Bağlantı Katmanı : Bu katman, fiziksel ortam üzerinden veri aktarımını sağlar ve fiziksel düzeyde oluşabilecek hataları yönetir.


  3. Ağ Katmanı : Bu katman, ağlar arasındaki veri aktarımının yolunu (yönlendirmesini) belirler.


  4. Aktarım Katmanı : Bu katman, noktalar arasındaki mesaj dağıtımını yönetir ve gerektiğinde güvenilirlik sağlar.


  5. Oturum Katmanı : Bu katman, kullanıcılar ve uygulamalar arasında oturum oluşturulmasını, sürdürülmesini ve sonlandırılmasını yönetir.


  6. Sunum Katmanı : Bu katman, gönderici ve alıcı tarafındaki veri temsilindeki (kodlama) farklılıklardan veri bağımsızlığını sağlar.


  7. Uygulama Katmanı : Bu katman, kullanıcının etkileşimde bulunduğu uygulamalarla doğrudan ilişkisi olan protokolleri içerir.



Her katmanın bir öncekinin üzerine inşa edildiğini belirtmekte fayda var. Aktarım katmanının üzerindeki katmanlar (Oturum, Sunum ve Uygulama) oldukça uzmanlaşmıştır ve gerçek zamanlı çok oyunculu oyunu düzenlememize yardımcı olamaz. Bu nedenle, Aktarım Katmanında durmalı ve oyuncular arasında en iyi veri alışverişini sağlamak için TCP ve UDP protokollerini kullanmalıyız.


Geçiş kontrol protokolü

TCP bağlantı odaklı bir protokoldür; bu, veri alışverişi için bağlantı kuran iki cihaz arasında iletişimin gerçekleştiği anlamına gelir. Bu protokol, iletilen tüm verilerin hedefine doğru sırayla ulaşacağını garanti ettiğinden güvenilirliği sağlar. İletim sırasında herhangi bir veri kaybolursa, TCP, tüm veriler başarıyla iletilinceye kadar isteği otomatik olarak yeniden deneyecektir.


Bağlantı kurmak aşağıdaki adımları içerir:


  • İstemci ve sunucu, TCP üzerinden veri alışverişi için yuvalar oluşturur.
  • İstemci, belirtilen hedef bağlantı noktasıyla sunucuya bir SYN (senkronizasyon) segmenti gönderir.
  • Sunucu SYN segmentini kabul eder, kendi soketini oluşturur ve istemciye bir SYN-ACK (senkronizasyon-onay) segmenti gönderir.
  • İstemci SYN-ACK segmentini kabul eder ve bağlantı kurma işlemini tamamlamak için sunucuya bir ACK (onay) segmenti gönderir. Artık güvenilir bir iki yönlü bağlantı kurulmuştur.





TCP İstemcisi

Aşağıdaki örnek, bir TCP istemcisinin temel uygulamasını gösterir ve belirli veriler ve oyun mantığıyla çalışacak şekilde genişletilebilir.


Kod, belirli bir IP adresine ve bağlantı noktasına sahip bir sunucuya bağlanır ve ardından bağlantı üzerinden veri gönderip alır. Sunucudan eşzamansız veri alımı için bir ağ akışı kullanılır.


 using System; using System.Net; using System.Net.Sockets; using UnityEngine; public class TCPClient : MonoBehaviour { private TcpClient tcpClient; private NetworkStream networkStream; private byte[] receiveBuffer; private void Start() { // Example: Connect to server with IP address 127.0.0.1 (localhost) and port 5555 ConnectToServer("127.0.0.1", 5555); } private void ConnectToServer(string ipAddress, int port) { tcpClient = new TcpClient(); tcpClient.Connect(IPAddress.Parse(ipAddress), port); networkStream = tcpClient.GetStream(); // Start asynchronous operation to receive data from the server receiveBuffer = new byte[tcpClient.ReceiveBufferSize]; networkStream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReceiveData, null); } private void ReceiveData(IAsyncResult result) { int bytesRead = networkStream.EndRead(result); byte[] receivedBytes = new byte[bytesRead]; Array.Copy(receiveBuffer, receivedBytes, bytesRead); string receivedMessage = System.Text.Encoding.UTF8.GetString(receivedBytes); Debug.Log("Received from server: " + receivedMessage); // Continue the asynchronous operation to receive data networkStream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReceiveData, null); } private void SendData(string message) { byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes(message); networkStream.Write(sendBytes, 0, sendBytes.Length); networkStream.Flush(); } }


ConnectToServer(string ipAddress, int port) yöntemi, belirtilen IP adresi ve bağlantı noktasında sunucuya bağlantı kurar. Sunucudan veri alımı ReceiveData(IAsyncResult result) yöntemiyle gerçekleştirilir, veri iletimi ise SendData(string message) yöntemiyle yapılır. Alınan veriler Debug.Log kullanılarak konsola gönderilir.


TCP Sunucusu

Aşağıdaki kod örneği Unity'deki basit bir TCP sunucusunu temsil etmektedir. Kod, sunucuyu başlatır, belirtilen bağlantı noktasını dinler ve istemcilerden gelen bağlantıları kabul eder. Bir istemciye bağlandıktan sonra sunucu, ağ akışı aracılığıyla veri gönderip alır.


StartServer(int port) yöntemi, sunucuyu belirtilen bağlantı noktasında başlatır ve gelen bağlantıları dinlemeye başlar. Bir istemci bağlantısı kurulduğunda, istemciden veri alan ve verileri almak için zaman uyumsuz bir işlem başlatan HandleIncomingConnection(IAsyncResult result) yöntemi yürütülür.


Alınan veriler, ReceiveData(IAsyncResult result) yönteminde işlenir. Sunucu, istemciden veri aldıktan sonra gerekli işlemleri gerçekleştirebilir veya verileri istemciye geri gönderebilir.


SendData(string message) yöntemi, verileri istemciye ağ akışı aracılığıyla gönderir. Veriler bir bayt dizisine dönüştürülür ve istemciye gönderilir.


 using System; using System.Net; using System.Net.Sockets; using UnityEngine; public class TCPServer : MonoBehaviour { private TcpListener tcpListener; private TcpClient connectedClient; private NetworkStream networkStream; private byte[] receiveBuffer; private void Start() { // Example: Start the server on port 5555 StartServer(5555); } private void StartServer(int port) { tcpListener = new TcpListener(IPAddress.Any, port); tcpListener.Start(); Debug.Log("Server started. Waiting for connections..."); // Start accepting client connections asynchronously tcpListener.BeginAcceptTcpClient(HandleIncomingConnection, null); } }


HandleIncomingConnection yöntemi, gelen bir istemci bağlantısını işlemek için kullanılır. Bağlantıyı kabul ettikten sonra istemciyle veri alışverişi için bir akış elde eder ve istemciden veri almak için eşzamansız bir işlem başlatır.


Daha sonra yöntem, bağlı istemciden alınan arabellek boyutuna göre veri almak için bir arabellek oluşturur. Oluşturulan arabelleği kullanarak akıştan veri okumak için eşzamansız bir işlem başlatılır. Okuma işlemi tamamlandıktan sonra veriler daha ileri işlemler için ReceiveData yöntemine aktarılacaktır.


Ayrıca yöntem, bir sonraki istemciyi kabul etme olasılığı için gelen bağlantıları kabul etmek üzere başka bir eşzamansız işlem başlatır.


Bir istemci sunucuya bağlandığında, bağlantıyı yönetmek için bu yöntem çağrılacak ve sunucu, sonraki istemcileri eşzamansız olarak kabul etmeye hazır olacaktır.


 private void HandleIncomingConnection(IAsyncResult result) { connectedClient = tcpListener.EndAcceptTcpClient(result); networkStream = connectedClient.GetStream(); Debug.Log("Client connected: " + connectedClient.Client.RemoteEndPoint); // Start asynchronous operation to receive data from the client receiveBuffer = new byte[connectedClient.ReceiveBufferSize]; networkStream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReceiveData, null); // Accept next client connection asynchronously tcpListener.BeginAcceptTcpClient(HandleIncomingConnection, null); }


ReceiveData yöntemi, istemciden alınan verileri işlemek için kullanılır. Veri okuma işlemi tamamlandıktan sonra yöntem okunan bayt sayısını kontrol eder. Bayt sayısı sıfırdan küçük veya sıfıra eşitse bu, istemcinin bağlantısının kesildiği anlamına gelir. Bu durumda yöntem istemciyle bağlantıyı kapatır ve yürütmeyi sonlandırır.


Okunan bayt sayısı sıfırdan büyükse yöntem, alınan veri için bir bayt dizisi oluşturur ve okunan veriyi bu diziye kopyalar. Daha sonra yöntem, alınan baytları UTF-8 kodlamasını kullanarak bir dizeye dönüştürür ve alınan mesajı konsola çıkarır.


 private void ReceiveData(IAsyncResult result) { int bytesRead = networkStream.EndRead(result); if (bytesRead <= 0) { Debug.Log("Client disconnected: " + connectedClient.Client.RemoteEndPoint); connectedClient.Close(); return; } byte[] receivedBytes = new byte[bytesRead]; Array.Copy(receiveBuffer, receivedBytes, bytesRead); string receivedMessage = System.Text.Encoding.UTF8.GetString(receivedBytes); Debug.Log("Received from client: " + receivedMessage); // Process received data // Continue the asynchronous operation to receive data networkStream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, ReceiveData, null); } private void SendData(string message) { byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes(message); networkStream.Write(sendBytes, 0, sendBytes.Length); networkStream.Flush(); Debug.Log("Sent to client: " + message); }


SendData yöntemi istemciye veri göndermek için kullanılır. Mesaj dizisini UTF-8 kodlamasını kullanarak bir bayt dizisine dönüştürür ve bu diziyi ağ akışına yazar. Verileri gönderdikten sonra yöntem akışı temizler ve gönderilen mesajı konsola çıkarır.

Güvenilirlik büyük bir artı gibi görünse de bu TCP özelliği, gerçek zamanlı çok oyunculu oyunlarda sorun yaratabiliyor. TCP'de veri iletimi, yeniden iletim ve akış kontrolü mekanizması tarafından yavaşlatılabilir ve bu da gecikmelere veya "gecikmelere" yol açabilir.


Kullanıcı Datagram Protokolü

UDP, teslimatı veya paket sırasını garanti etmeyen daha basit bir protokoldür. Bu, bağlantı kurmak veya kayıp paketleri yeniden iletmek için zaman harcamadığından TCP'den çok daha hızlı olmasını sağlar. Hızı ve basitliği nedeniyle UDP, ağ oyunlarında ve gerçek zamanlı veri iletimi gerektiren diğer uygulamalarda sıklıkla kullanılır.



Ancak UDP'yi kullanmak, geliştiricilerin veri aktarımını daha dikkatli yönetmesini gerektirir. UDP teslimatı garanti etmediğinden, kayıp paketlerle veya hatalı gelen paketlerle başa çıkmak için kendi mekanizmalarınızı uygulamanız gerekebilir.


UDP İstemcisi

Bu kod, Unity'de bir UDP istemcisinin temel uygulamasını gösterir. StartUDPClient yöntemi UDP istemcisini başlatır ve onu IP adresi ve bağlantı noktasıyla belirtilen uzak sunucuya bağlar. İstemci, BeginReceive yöntemini kullanarak eşzamansız olarak veri almaya başlar ve SendData yöntemini kullanarak sunucuya bir mesaj gönderir.


 using System; using System.Net; using System.Net.Sockets; using UnityEngine; public class UDPExample : MonoBehaviour { private UdpClient udpClient; private IPEndPoint remoteEndPoint; private void Start() { // Example: Start the UDP client and connect to the remote server StartUDPClient("127.0.0.1", 5555); } private void StartUDPClient(string ipAddress, int port) { udpClient = new UdpClient(); remoteEndPoint = new IPEndPoint(IPAddress.Parse(ipAddress), port); // Start receiving data asynchronously udpClient.BeginReceive(ReceiveData, null); // Send a message to the server SendData("Hello, server!"); } private void ReceiveData(IAsyncResult result) { byte[] receivedBytes = udpClient.EndReceive(result, ref remoteEndPoint); string receivedMessage = System.Text.Encoding.UTF8.GetString(receivedBytes); Debug.Log("Received from server: " + receivedMessage); // Continue receiving data asynchronously udpClient.BeginReceive(ReceiveData, null); } private void SendData(string message) { byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes(message); // Send the message to the server udpClient.Send(sendBytes, sendBytes.Length, remoteEndPoint); Debug.Log("Sent to server: " + message); } }

Sunucudan veri alındığında, alınan baytları işleyen ve bunları bir dizeye dönüştüren ReceiveData yöntemi çağrılır. Alınan mesaj daha sonra konsola kaydedilir. İstemci, BeginReceive yeniden çağırarak verileri zaman uyumsuz olarak almaya devam eder.

SendData yöntemi, mesajı bayta dönüştürür ve UDP istemcisinin Send yöntemini kullanarak sunucuya gönderir.


UDP Sunucusu

Bu kod, Unity'deki bir UDP sunucusunun temel uygulamasını gösterir. StartUDPServer yöntemi, belirtilen bağlantı noktasındaki UDP sunucusunu başlatır ve BeginReceive yöntemini kullanarak eşzamansız olarak veri almaya başlar.


Bir istemciden veri alındığında, alınan baytları işleyen ve bunları bir dizeye dönüştüren ReceiveData yöntemi çağrılır. Alınan mesaj daha sonra konsola kaydedilir. Sunucu, BeginReceive yeniden çağırarak verileri eşzamansız olarak almaya devam eder.


 using System; using System.Net; using System.Net.Sockets; using UnityEngine; public class UDPServer : MonoBehaviour { private UdpClient udpServer; private IPEndPoint remoteEndPoint; private void Start() { // Example: Start the UDP server on port 5555 StartUDPServer(5555); } private void StartUDPServer(int port) { udpServer = new UdpClient(port); remoteEndPoint = new IPEndPoint(IPAddress.Any, port); Debug.Log("Server started. Waiting for messages..."); // Start receiving data asynchronously udpServer.BeginReceive(ReceiveData, null); } private void ReceiveData(IAsyncResult result) { byte[] receivedBytes = udpServer.EndReceive(result, ref remoteEndPoint); string receivedMessage = System.Text.Encoding.UTF8.GetString(receivedBytes); Debug.Log("Received from client: " + receivedMessage); // Process the received data // Continue receiving data asynchronously udpServer.BeginReceive(ReceiveData, null); } private void SendData(string message, IPEndPoint endPoint) { byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes(message); // Send the message to the client udpServer.Send(sendBytes, sendBytes.Length, endPoint); Debug.Log("Sent to client: " + message); } }


SendData yöntemi, bir mesaj ve istemcinin adresini ve bağlantı noktasını temsil eden bir IPEndPoint alır. Mesajı bayta dönüştürür ve UDP sunucusunun Send yöntemini kullanarak istemciye gönderir.


Oyun geliştirme bağlamında TCP ve UDP arasındaki seçim büyük ölçüde oyununuzun türüne bağlıdır. Oyununuz güvenilir veri dağıtımı gerektiriyorsa ve yanıt süresi kritik bir faktör değilse (örneğin, gerçek zamanlı strateji veya sıra tabanlı oyunlarda), TCP uygun bir seçim olabilir. Öte yandan, oyununuz hızlı veri aktarımı gerektiriyorsa ve bir miktar veri kaybıyla başa çıkabiliyorsa (örneğin, birinci şahıs nişancı veya yarış oyunlarında), o zaman UDP en iyi seçim olabilir.


WebSocket

WebSocket , tarayıcı ile sunucu arasında kalıcı bir bağlantı kurulmasına olanak tanıyan bir iletişim protokolüdür. Normal HTTP'den temel farkı, çift yönlü iletişime olanak sağlamasıdır; Sunucu yalnızca istemci isteklerine yanıt vermekle kalmaz, aynı zamanda kendisine mesaj da gönderebilir.


WebSocket, TCP'ye dayalı uygulama düzeyinde bir protokoldür. Akışları değil mesajları desteklemesi onu normal TCP'den ayırır. WebSocket, performansa bir miktar ek yük getirebilecek ek işlevsellik içerir.


Adım adım şu şekilde çalışır:


  • İstemci, "Yükseltme isteği" adı verilen özel bir HTTP isteği gönderir. Bu istek, sunucuya istemcinin WebSocket'e geçmek istediğini bildirir.


  • Sunucu WebSocket'i destekliyorsa ve geçiş yapmayı kabul ediyorsa, WebSocket'e yükseltmeyi onaylayan özel bir HTTP yanıtıyla yanıt verir.


  • Bu mesajların değişiminden sonra istemci ile sunucu arasında kalıcı, çift yönlü bir bağlantı kurulur. Her iki taraf da yalnızca karşı tarafın isteklerine yanıt olarak değil, istedikleri zaman mesaj gönderebilir.


  • Artık istemci ve sunucu istedikleri zaman mesaj gönderip alabilirler. Her WebSocket mesajı, mesajın ne zaman başlayıp bittiğini gösteren "çerçeveler" içine sarılır. Bu, tarayıcı ve sunucunun, karışık bir sırada gelse veya ağ sorunları nedeniyle parçalara ayrılmış olsa bile mesajları doğru şekilde yorumlamasına olanak tanır.




Her iki taraf da istediği zaman özel bir "bağlantıyı kapat" çerçevesi göndererek bağlantıyı kapatabilir. Diğer taraf kapatma onayıyla yanıt verebilir ve bundan sonra her iki taraf da diğer verileri göndermeyi derhal bırakmalıdır. Kapatma nedenini belirtmek için durum kodları da kullanılabilir.

WebSocket İstemcisi

Aşağıdaki kod, C# dilini ve WebSocketSharp kitaplığını kullanarak Unity'de bir WebSocket istemcisinin uygulanmasına ilişkin bir örnek sağlar.


Nesnenin başlatılması üzerine çağrılan Start() yönteminde, WebSocket sunucunuzun adresiyle başlatılan yeni bir WebSocket örneği oluşturulur.


Bundan sonra OnOpen ve OnMessage olay işleyicileri ayarlanır.


 using UnityEngine; using WebSocketSharp; public class WebSocketClient : MonoBehaviour { private WebSocket ws; void Start() { ws = new WebSocket("ws://your-websocket-server-url/Auth"); ws.OnOpen += OnOpenHandler; ws.OnMessage += OnMessageHandler; ws.ConnectAsync(); } private void OnOpenHandler(object sender, System.EventArgs e) { var data = "Player1"; ws.Send(data) } private void OnMessageHandler(object sender, MessageEventArgs e) { Debug.Log("WebSocket server said: " + e.Data); } }


OnOpen sunucuyla bağlantı kurulduğunda tetiklenir. Bu örnekte bağlantı kurulduğunda sunucuya "Oyuncu1" yazılı bir mesaj gönderilmektedir.


OnMessage sunucudan bir mesaj alındığında tetiklenir. Burada bir mesaj alındığında içeriği konsolda görüntülenir.


Daha sonra sunucuya eşzamansız olarak bağlanan ConnectAsync() yöntemi çağrılır.


WebSocket Sunucusu

Aşağıdaki kod WebSocket sunucusu oluşturmanın bir örneğidir.


Nesne başlatıldığında çağrılan Start() yönteminde, WebSocket sunucunuzun adresiyle başlatılan yeni bir WebSocketServer örneği oluşturulur. Daha sonra /Auth yolunda bulunan AuthBehaviour WebSocket hizmeti sunucuya eklenir. Bundan sonra sunucu Start() yöntemi kullanılarak başlatılır.


 using UnityEngine; using WebSocketSharp; using WebSocketSharp.Server; public class WebSocketServer : MonoBehaviour { void Start() { var socket = new WebSocketServer("ws://your-websocket-server-url"); socket.AddWebSocketService<AuthBehaviour>("/Auth"); socket.Start(); } } public class AuthBehaviour : WebSocketBehavior { protected override void OnMessage (MessageEventArgs e) { var playerName = e.Data; Debug.Log("WebSocket client connected: " + playerName); Send("Auth Complete: " + playerName); } }


AuthBehaviour , istemcilerden mesaj alırken sunucu davranışını tanımlayan WebSocketBehavior türetilmiş bir sınıftır. Burada, sunucu bir istemciden mesaj aldığında çağrılan OnMessage() yöntemi geçersiz kılınır.


Bu yöntemde, önce mesaj metni çıkarılır, daha sonra mesajda geçirilen adı kullanarak hangi istemcinin bağlandığını belirten konsola bir mesaj gönderilir. Daha sonra sunucu, istemciye kimlik doğrulamanın tamamlanmasıyla ilgili bilgileri içeren bir mesaj gönderir.


Çözüm

Unity oyunları için TCP, UDP ve WebSockets kullanarak nasıl bağlantı oluşturulacağını ve her birinin avantajlarını ve dezavantajlarını tartıştık. UDP'nin hafif doğasına ve TCP'nin güvenilirliğine rağmen, oyunlarda gerçek zamanlı çok oyunculu oyunları düzenlemek için ikisi de iyi bir seçim değildir. UDP bazı verileri kaybedecek ve TCP gerekli iletim hızını sağlayamayacaktır. Bir sonraki makalede UDP kullanarak güvenilir veri aktarımının nasıl organize edileceğini tartışacağız.