TCP üzerinden veri göndermek ve almak için Yuvaları kullanma

Uzak cihazlarla iletişim kurmak için yuva kullanabilmeniz için önce yuvanın protokol ve ağ adresi bilgileriyle başlatılması gerekir. sınıfının oluşturucusunun, yuvanın Socket bağlantı oluşturmak için kullandığı adres ailesini, yuva türünü ve protokol türünü belirten parametreleri vardır. İstemci yuvasını bir sunucu yuvasına bağlarken, istemci sunucunun ağ adresini belirtmek için bir IPEndPoint nesne kullanır.

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.

Socket İstemci oluşturma

endPoint nesnesi oluşturulduktan sonra sunucuya bağlanmak için bir istemci yuvası oluşturun. Yuva bağlandıktan sonra, sunucu yuva bağlantısından veri gönderip alabilir.

using Socket client = new(
    ipEndPoint.AddressFamily, 
    SocketType.Stream, 
    ProtocolType.Tcp);

await client.ConnectAsync(ipEndPoint);
while (true)
{
    // Send message.
    var message = "Hi friends 👋!<|EOM|>";
    var messageBytes = Encoding.UTF8.GetBytes(message);
    _ = await client.SendAsync(messageBytes, SocketFlags.None);
    Console.WriteLine($"Socket client sent message: \"{message}\"");

    // Receive ack.
    var buffer = new byte[1_024];
    var received = await client.ReceiveAsync(buffer, SocketFlags.None);
    var response = Encoding.UTF8.GetString(buffer, 0, received);
    if (response == "<|ACK|>")
    {
        Console.WriteLine(
            $"Socket client received acknowledgment: \"{response}\"");
        break;
    }
    // Sample output:
    //     Socket client sent message: "Hi friends 👋!<|EOM|>"
    //     Socket client received acknowledgment: "<|ACK|>"
}

client.Shutdown(SocketShutdown.Both);

Yukarıdaki C# kodu:

  • Belirli endPoint bir örnek adres ailesi, ve ProtocolType.Tcpile yeni Socket bir nesne örneği SocketType.Streamoluşturur.

  • Socket.ConnectAsync bağımsız değişken olarak örneğiyle endPoint yöntemini çağırır.

  • Döngüde while :

    • kullanarak Socket.SendAsyncsunucuya bir ileti kodlar ve gönderir.
    • Gönderilen iletiyi konsola yazar.
    • kullanarak Socket.ReceiveAsyncsunucudan veri almak için bir arabellek başlatır.
    • response bir bildirim olduğunda, konsola yazılır ve döngüden çıkarılır.
  • Son olarak verilen client yuva, Socket.ShutdownSocketShutdown.Bothhem gönderme hem de alma işlemlerini kapatır.

Sunucu oluşturma Socket

Sunucu yuvasını oluşturmak için, endPoint nesne herhangi bir IP adresinde gelen bağlantıları dinleyebilir, ancak bağlantı noktası numarası belirtilmelidir. Yuva oluşturulduktan sonra, sunucu gelen bağlantıları kabul edebilir ve istemcilerle iletişim kurabilir.

using Socket listener = new(
    ipEndPoint.AddressFamily,
    SocketType.Stream,
    ProtocolType.Tcp);

listener.Bind(ipEndPoint);
listener.Listen(100);

var handler = await listener.AcceptAsync();
while (true)
{
    // Receive message.
    var buffer = new byte[1_024];
    var received = await handler.ReceiveAsync(buffer, SocketFlags.None);
    var response = Encoding.UTF8.GetString(buffer, 0, received);
    
    var eom = "<|EOM|>";
    if (response.IndexOf(eom) > -1 /* is end of message */)
    {
        Console.WriteLine(
            $"Socket server received message: \"{response.Replace(eom, "")}\"");

        var ackMessage = "<|ACK|>";
        var echoBytes = Encoding.UTF8.GetBytes(ackMessage);
        await handler.SendAsync(echoBytes, 0);
        Console.WriteLine(
            $"Socket server sent acknowledgment: \"{ackMessage}\"");

        break;
    }
    // Sample output:
    //    Socket server received message: "Hi friends 👋!"
    //    Socket server sent acknowledgment: "<|ACK|>"
}

Yukarıdaki C# kodu:

  • Belirli endPoint bir örnek adres ailesi, ve ProtocolType.Tcpile yeni Socket bir nesne örneği SocketType.Streamoluşturur.

  • , listener yuvayı Socket.BindendPoint ağ adresiyle ilişkilendirmek için bir bağımsız değişken olarak örneğiyle yöntemini çağırır.

  • yöntemi Socket.Listen() , gelen bağlantıları dinlemek için çağrılır.

  • , listener yuvada Socket.AcceptAsynchandler gelen bir bağlantıyı kabul etmek için yöntemini çağırır.

  • Döngüde while :

    • İstemciden veri almak için çağrılar Socket.ReceiveAsync .
    • Veriler alındığında kodu çözülerek konsola yazılır.
    • response İleti ile <|EOM|>biterse, kullanılarak istemciye Socket.SendAsyncbir onay gönderilir.

Örnek istemciyi ve sunucuyu çalıştırma

Önce sunucu uygulamasını başlatın ve ardından istemci uygulamasını başlatın.

dotnet run --project socket-server
Socket server starting...
Found: 172.23.64.1 available on port 9000.
Socket server received message: "Hi friends 👋!"
Socket server sent acknowledgment: "<|ACK|>"
Press ENTER to continue...

İstemci uygulaması sunucuya bir ileti gönderir ve sunucu bir bildirimle yanıt verir.

dotnet run --project socket-client
Socket client starting...
Found: 172.23.64.1 available on port 9000.
Socket client sent message: "Hi friends 👋!<|EOM|>"
Socket client received acknowledgment: "<|ACK|>"
Press ENTER to continue...

Ayrıca bkz.