Aracılığıyla paylaş


TCP'ye genel bakış

Önemli

sınıfıSocket, ve TcpListeneryerine TcpClient ileri düzey kullanıcılar için kesinlikle önerilir.

İletim Denetimi Protokolü (TCP) ile çalışmak için iki seçeneğiniz vardır: maksimum denetim ve performans için kullanın Socket veya ve TcpListener yardımcı sınıflarını TcpClient kullanın. TcpClient ve TcpListener sınıfının en üstünde System.Net.Sockets.Socket oluşturulur ve kullanım kolaylığı için veri aktarımının ayrıntılarıyla ilgilenir.

Protokol sınıfları, durum bilgilerini koruma veya protokole özgü yuvaları ayarlama ayrıntılarını öğrenme yükü olmadan ağ hizmetlerine basit erişim sağlamak için temel sınıfı Socket kullanır. Zaman uyumsuz Socket yöntemleri kullanmak için sınıfı tarafından NetworkStream sağlanan zaman uyumsuz yöntemleri kullanabilirsiniz. Protokol sınıfları tarafından kullanıma sunulmayan sınıfın Socket özelliklerine erişmek için sınıfını Socket kullanmanız gerekir.

TcpClient ve TcpListener sınıfını kullanarak ağı temsil edin NetworkStream . yöntemini kullanarak GetStream ağ akışını döndürecek ve ardından akışın NetworkStream.ReadAsync ve NetworkStream.WriteAsync yöntemlerini çağıracaksınız. NetworkStream, protokol sınıflarının temel alınan yuvasına sahip olmadığından yuvayı kapatmaz.

ve kullanın TcpClientTcpListener

sınıfı, TcpClient TCP kullanarak bir internet kaynağından veri istemektedir. TCP kullanarak veri istemek ve almak için oluşturma Socket ayrıntılarını özetleme yöntemleri ve özellikleriTcpClient. Uzak cihaza bağlantı bir akış olarak temsil edildiğinden, veriler .NET Framework akış işleme teknikleri ile okunabilir ve yazılabilir.

TCP protokolü, uzak uç noktayla bir bağlantı kurar ve ardından veri paketlerini gönderip almak için bu bağlantıyı kullanır. TCP, veri paketlerinin uç noktaya gönderilmesini ve ulaştıklarında doğru sırada bir araya getirildiğinden emin olmakla sorumludur.

IP uç noktası oluşturma

ile System.Net.Socketsçalışırken bir ağ uç noktasını nesne olarak IPEndPoint temsil edebilirsiniz. IPEndPoint, ve IPAddress buna karşılık gelen bağlantı noktası numarasıyla oluşturulur. aracılığıyla Socketbir konuşma başlatabilmeniz için önce uygulamanızla uzak hedef arasında bir veri kanalı oluşturursunuz.

TCP/IP, bir hizmeti benzersiz olarak tanımlamak için bir ağ adresi ve hizmet bağlantı noktası numarası kullanır. Ağ adresi belirli bir ağ hedefini tanımlar; bağlantı noktası numarası, o cihazdaki bağlanacak hizmeti tanımlar. Ağ adresi ve hizmet bağlantı noktası birleşimi, sınıfı tarafından EndPoint .NET'te temsil edilen uç nokta olarak adlandırılır. Alt öğesi EndPoint desteklenen her adres ailesi için tanımlanır; IP adresi ailesi için sınıfı olur IPEndPoint.

sınıfı, Dns TCP/IP internet hizmetlerini kullanan uygulamalara etki alanı adı hizmetleri sağlar. yöntemi, GetHostEntryAsync kullanıcı dostu bir etki alanı adını ("host.contoso.com") sayısal bir İnternet adresiyle (örneğin 192.168.1.1) eşlemek için bir DNS sunucusunu sorgular. GetHostEntryAsyncTask<IPHostEntry>, beklendiğinde istenen ad için adreslerin ve diğer adların listesini içeren bir döndürür. Çoğu durumda, dizide AddressList döndürülen ilk adresi kullanabilirsiniz. Aşağıdaki kod, sunucusunun host.contoso.comIP adresini içeren bir IPAddress alır.

IPHostEntry ipHostInfo = await Dns.GetHostEntryAsync("host.contoso.com");
IPAddress ipAddress = ipHostInfo.AddressList[0];

İpucu

El ile test ve hata ayıklama amacıyla, localhost adını bir IP adresine çözümlemek için genellikle değerinin Dns.GetHostName() elde edilen ana bilgisayar adıyla yöntemini kullanabilirsinizGetHostEntryAsync. Aşağıdaki kod parçacığını göz önünde bulundurun:

var hostName = Dns.GetHostName();
IPHostEntry localhost = await Dns.GetHostEntryAsync(hostName);
// This is the IP address of the local machine
IPAddress localIpAddress = localhost.AddressList[0];

İnternet Atanan Numaralar Yetkilisi (IANA), ortak hizmetler için bağlantı noktası numaralarını tanımlar. Daha fazla bilgi için bkz . IANA: Hizmet Adı ve Aktarım Protokolü Bağlantı Noktası Numarası Kayıt Defteri). Diğer hizmetler 1.024 ile 65.535 arasında kayıtlı bağlantı noktası numaralarına sahip olabilir. Aşağıdaki kod, bağlantı için uzak uç nokta oluşturmak üzere host.contoso.com ip adresini bir bağlantı noktası numarasıyla birleştirir.

IPEndPoint ipEndPoint = new(ipAddress, 11_000);

Uzak cihazın adresini belirledikten ve bağlantı için kullanılacak bağlantı noktasını seçtikten sonra uygulama uzak cihazla bağlantı kurabilir.

TcpClient oluşturma

sınıfı, TcpClient TCP hizmetlerini sınıftan daha yüksek bir soyutlama Socket düzeyinde sağlar. TcpClient uzak bir ana bilgisayara istemci bağlantısı oluşturmak için kullanılır. alma hakkında IPEndPointbilgi sahibi olmak için, istediğiniz bağlantı noktası numarasıyla eşleştirmeniz olduğunu IPAddress varsayalım. Aşağıdaki örnekte, 13 numaralı TCP bağlantı noktasındaki bir zaman sunucusuna bağlanmak için bir ayarlama TcpClient gösterilmektedir:

var ipEndPoint = new IPEndPoint(ipAddress, 13);

using TcpClient client = new();
await client.ConnectAsync(ipEndPoint);
await using NetworkStream stream = client.GetStream();

var buffer = new byte[1_024];
int received = await stream.ReadAsync(buffer);

var message = Encoding.UTF8.GetString(buffer, 0, received);
Console.WriteLine($"Message received: \"{message}\"");
// Sample output:
//     Message received: "📅 8/22/2022 9:07:17 AM 🕛"

Yukarıdaki C# kodu:

  • Bilinen IPAddress ve bağlantı noktasından bir IPEndPoint oluşturur.
  • Yeni TcpClient bir nesne örneği oluşturma.
  • client kullanarak TcpClient.ConnectAsync13 numaralı bağlantı noktasında uzak TCP zaman sunucusuna bağlar.
  • Uzak konaktan verileri okumak için bir NetworkStream kullanır.
  • Bayt okuma arabelleği 1_024 bildirir.
  • 'den stream okuma arabelleğine veri okur.
  • Sonuçları konsola dize olarak yazar.

İstemci iletinin küçük olduğunu bildiği için, iletinin tamamı tek bir işlemde okuma arabelleğine okunabilir. Daha büyük iletilerde veya belirsiz uzunluktaki iletilerde istemci, arabelleği daha uygun bir şekilde kullanmalı ve döngüde while okumalıdır.

Önemli

İleti gönderirken ve alırken, Encoding hem sunucuya hem de istemciye önceden bilinmesi gerekir. Örneğin, sunucu kullanarak ASCIIEncoding iletişim kurar ancak istemci kullanmayı UTF8Encodingdenerse, iletiler hatalı biçimlendirilmiş olur.

TcpListener oluşturma

Türü TcpListener , gelen istekler için bir TCP bağlantı noktasını izlemek ve ardından istemci bağlantısını yöneten bir Socket veya bir TcpClient oluşturmak için kullanılır. Start yöntemi dinlemeyi etkinleştirir ve Stop yöntem bağlantı noktasında dinlemeyi devre dışı bırakır. AcceptTcpClientAsync yöntemi gelen bağlantı isteklerini kabul eder ve isteği işlemek için bir TcpClient oluşturur ve AcceptSocketAsync yöntem gelen bağlantı isteklerini kabul eder ve isteği işlemek için bir Socket oluşturur.

Aşağıdaki örnekte, 13 numaralı TCP bağlantı noktasını izlemek için kullanarak bir TcpListener ağ zaman sunucusu oluşturma gösterilmektedir. Gelen bağlantı isteği kabul edildiğinde, zaman sunucusu konak sunucudan geçerli tarih ve saatle yanıt verir.

var ipEndPoint = new IPEndPoint(IPAddress.Any, 13);
TcpListener listener = new(ipEndPoint);

try
{    
    listener.Start();

    using TcpClient handler = await listener.AcceptTcpClientAsync();
    await using NetworkStream stream = handler.GetStream();

    var message = $"📅 {DateTime.Now} 🕛";
    var dateTimeBytes = Encoding.UTF8.GetBytes(message);
    await stream.WriteAsync(dateTimeBytes);

    Console.WriteLine($"Sent message: \"{message}\"");
    // Sample output:
    //     Sent message: "📅 8/22/2022 9:07:17 AM 🕛"
}
finally
{
    listener.Stop();
}

Yukarıdaki C# kodu:

  • IPEndPoint ile IPAddress.Any ve bağlantı noktası oluşturur.
  • Yeni TcpListener bir nesne örneği oluşturma.
  • Start Bağlantı noktasında dinlemeye başlamak için yöntemini çağırır.
  • Gelen bağlantı isteklerini kabul etmek için yönteminden AcceptTcpClientAsync bir TcpClient kullanır.
  • Geçerli tarih ve saati dize iletisi olarak kodlar.
  • Bağlı istemciye veri yazmak için bir NetworkStream kullanır.
  • Gönderilen iletiyi konsola yazar.
  • Son olarak, bağlantı noktasında dinlemeyi durdurmak için yöntemini çağırır Stop .

Sınıfıyla Socket sonlu TCP denetimi

TcpListener Hem hem de TcpClient dahili olarak sınıfına Socket güvenir, yani bu sınıflarla yapabileceğiniz her şey doğrudan yuvalar kullanılarak gerçekleştirilebilir. Bu bölümde, işlevsel olarak eşdeğer olan karşılıklarıyla Socket birlikte birkaç TcpClient ve TcpListener kullanım örneği gösterilmektedir.

İstemci yuvası oluşturma

TcpClient'nin varsayılan oluşturucu, Socket(SocketType, ProtocolType) oluşturucu aracılığıyla çift yığınlı bir yuva oluşturmaya çalışır. Bu oluşturucu, IPv6 destekleniyorsa çift yığınlı bir yuva oluşturur, aksi takdirde IPv4'e geri döner.

Aşağıdaki TCP istemci kodunu göz önünde bulundurun:

using var client = new TcpClient();

Yukarıdaki TCP istemci kodu işlevsel olarak aşağıdaki yuva koduna eşdeğerdir:

using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

TcpClient(AddressFamily) Oluşturucu

Bu oluşturucu yalnızca üç AddressFamily değer kabul eder, aksi takdirde bir ArgumentExceptionoluşturur. Geçerli değerler:

Aşağıdaki TCP istemci kodunu göz önünde bulundurun:

using var client = new TcpClient(AddressFamily.InterNetwork);

Yukarıdaki TCP istemci kodu işlevsel olarak aşağıdaki yuva koduna eşdeğerdir:

using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

TcpClient(IPEndPoint) Oluşturucu

Yuva oluşturulduktan sonra, bu oluşturucu sağlanan yerel IPEndPointöğesine de bağlanır. IPEndPoint.AddressFamily özelliği, yuvanın adres ailesini belirlemek için kullanılır.

Aşağıdaki TCP istemci kodunu göz önünde bulundurun:

var endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5001);
using var client = new TcpClient(endPoint);

Yukarıdaki TCP istemci kodu işlevsel olarak aşağıdaki yuva koduna eşdeğerdir:

// Example IPEndPoint object
var endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5001);
using var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(endPoint);

TcpClient(String, Int32) Oluşturucu

Bu oluşturucu, varsayılan oluşturucuya benzer bir çift yığın oluşturmayı ve ve çifti tarafından tanımlanan uzak DNS uç noktasına bağlamayı port hostname dener.

Aşağıdaki TCP istemci kodunu göz önünde bulundurun:

using var client = new TcpClient("www.example.com", 80);

Yukarıdaki TCP istemci kodu işlevsel olarak aşağıdaki yuva koduna eşdeğerdir:

using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
socket.Connect("www.example.com", 80);

Sunucuya bağlan

içindeki TcpClient tüm Connect, BeginConnect ConnectAsyncve EndConnect aşırı yüklemeleri işlevsel olarak karşılık gelen Socket yöntemlerle eşdeğerdir.

Aşağıdaki TCP istemci kodunu göz önünde bulundurun:

using var client = new TcpClient();
client.Connect("www.example.com", 80);

Yukarıdaki TcpClient kod aşağıdaki yuva koduyla eşdeğerdir:

using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
socket.Connect("www.example.com", 80);

Sunucu yuvası oluşturma

Ham Socket eşdeğerleriyle işlevsel eşitliği olan örneklere TcpClient benzer şekilde, bu bölüm oluşturucuları ilgili yuva koduyla eşlerTcpListener. dikkate alınması gereken ilk oluşturucudur TcpListener(IPAddress localaddr, int port).

var listener = new TcpListener(IPAddress.Loopback, 5000);

Yukarıdaki TCP dinleyici kodu, işlevsel olarak aşağıdaki yuva koduyla eşdeğerdir:

var ep = new IPEndPoint(IPAddress.Loopback, 5000);
using var socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

Sunucuda dinlemeye başlama

Start() yöntemi, 'Bindleri ve Listen() işlevlerini birleştiren Socketbir sarmalayıcıdır.

Aşağıdaki TCP dinleyici kodunu göz önünde bulundurun:

var listener = new TcpListener(IPAddress.Loopback, 5000);
listener.Start(10);

Yukarıdaki TCP dinleyici kodu, işlevsel olarak aşağıdaki yuva koduyla eşdeğerdir:

var endPoint = new IPEndPoint(IPAddress.Loopback, 5000);
using var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(endPoint);
try
{
    socket.Listen(10);
}
catch (SocketException)
{
    socket.Dispose();
}

Sunucu bağlantısını kabul etme

Arka planda, gelen TCP bağlantıları kabul edildiğinde her zaman yeni bir yuva oluşturur. TcpListenerbir Socket örneği doğrudan kabul edebilir (veya AcceptSocketAsync()aracılığıylaAcceptSocket()) veya bir TcpClient (ve AcceptTcpClientAsync()aracılığıylaAcceptTcpClient()) kabul edebilir.

Aşağıdaki TcpListener kodu göz önünde bulundurun:

var listener = new TcpListener(IPAddress.Loopback, 5000);
using var acceptedSocket = await listener.AcceptSocketAsync();

// Synchronous alternative.
// var acceptedSocket = listener.AcceptSocket();

Yukarıdaki TCP dinleyici kodu, işlevsel olarak aşağıdaki yuva koduyla eşdeğerdir:

var endPoint = new IPEndPoint(IPAddress.Loopback, 5000);
using var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
using var acceptedSocket = await socket.AcceptAsync();

// Synchronous alternative
// var acceptedSocket = socket.Accept();

Veri göndermek ve almak için oluşturma NetworkStream

ile TcpClient veri gönderip alabilmek için yöntemiyle GetStream() bir NetworkStream örneği oluşturmanız gerekir. ile Socketoluşturma işlemini NetworkStream el ile yapmanız gerekir.

Aşağıdaki TcpClient kodu göz önünde bulundurun:

using var client = new TcpClient();
using NetworkStream stream = client.GetStream();

Bu, aşağıdaki yuva koduna eşdeğerdir:

using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

// Be aware that transferring the ownership means that closing/disposing the stream will also close the underlying socket.
using var stream = new NetworkStream(socket, ownsSocket: true);

İpucu

Kodunuzun bir Stream örnekle çalışması gerekmiyorsa, doğrudan oluşturmak NetworkStreamyerine 'nin Gönderme/Alma yöntemlerine (Send, SendAsyncReceive ve ReceiveAsync) güvenebilirsinizSocket.

Ayrıca bkz.