TCP'ye genel bakış
Önemli
sınıfıSocket, ve TcpListener
yerine 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 TcpClient
TcpListener
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. GetHostEntryAsync
Task<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.com
IP 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 IPEndPoint
bilgi 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 birIPEndPoint
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:
- AddressFamily.InterNetwork: IPv4 yuvası için.
- AddressFamily.InterNetworkV6: IPv6 yuvası için.
- AddressFamily.Unknown: Bu, varsayılan oluşturucuya benzer şekilde çift yığınlı bir yuva oluşturmayı dener.
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
ConnectAsync
ve 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 Socket
bir 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. TcpListener
bir 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 Socket
oluş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
.