Sdílet prostřednictvím


Použití soketů k odesílání a příjmu dat přes protokol TCP

Než budete moct použít soket ke komunikaci se vzdálenými zařízeními, musí být soket inicializován pomocí informací protokolu a síťové adresy. Konstruktor třídy Socket má parametry, které určují rodinu adres, typ soketu a typ protokolu, které soket používá k vytváření připojení. Při připojování klientského soketu k serverovém soketu používá IPEndPoint klient objekt k určení síťové adresy serveru.

Vytvoření koncového bodu PROTOKOLU IP

Při práci s System.Net.Socketsobjektem představujete koncový bod IPEndPoint sítě. IPEndPoint je vytvořeno pomocí IPAddress a jeho odpovídajícího čísla portu. Než budete moct zahájit konverzaci prostřednictvím Socketaplikace, vytvoříte mezi aplikací a vzdáleným cílem datový kanál.

TCP/IP používá síťovou adresu a číslo portu služby k jednoznačné identifikaci služby. Síťová adresa identifikuje konkrétní cíl sítě; číslo portu identifikuje konkrétní službu na daném zařízení, ke které se má připojit. Kombinace síťové adresy a portu služby se nazývá koncový bod, který je reprezentován v .NET EndPoint třídou. Potomek EndPoint je definován pro každou podporovanou adresní rodinu; pro adresní rodinu IP je třída IPEndPoint.

Třída Dns poskytuje služby pro názvy domén aplikací, které používají internetové služby TCP/IP. Metoda GetHostEntryAsync se dotazuje serveru DNS na mapování uživatelsky přívětivého názvu domény (například "host.contoso.com") na číselnou internetovou adresu (například 192.168.1.1). GetHostEntryAsync Task<IPHostEntry> vrátí hodnotu, která při čekání obsahuje seznam adres a aliasů požadovaného názvu. Ve většině případů můžete použít první adresu, která je vrácena v rámci AddressList pole. Následující kód obdrží IPAddress obsahující IP adresu pro server host.contoso.com.

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

Návod

Pro účely ručního testování a ladění můžete obvykle použít metodu GetHostEntryAsync s výsledným názvem hostitele z Dns.GetHostName() hodnoty k překladu názvu místního hostitele na IP adresu. Vezměte v úvahu následující fragment kódu:

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

Autorita IANA (Internet Assigned Numbers Authority) definuje čísla portů pro běžné služby. Další informace najdete v tématu IANA: Název služby a registr čísel portů přenosového protokolu). Ostatní služby můžou mít registrovaná čísla portů v rozsahu 1 024 až 65 535. Následující kód kombinuje IP adresu s host.contoso.com číslem portu a vytvoří vzdálený koncový bod pro připojení.

IPEndPoint ipEndPoint = new(ipAddress, 11_000);

Po určení adresy vzdáleného zařízení a výběru portu, který se má pro připojení použít, může aplikace navázat připojení ke vzdálenému zařízení.

Vytvoření Socket klienta

Pomocí vytvořeného objektu endPoint vytvořte klientský soket pro připojení k serveru. Po připojení soketu může odesílat a přijímat data z připojení soketu serveru.

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);

Předchozí kód jazyka C#:

  • Vytvoří instanci nového Socket objektu s danou endPoint sadou adres instancí, objektem SocketType.Streama ProtocolType.Tcp.

  • Volá metodu Socket.ConnectAsync s instancí endPoint jako argumentem.

  • Ve smyčce while :

    • Kóduje a odesílá zprávu na server pomocí .Socket.SendAsync
    • Zapíše odeslanou zprávu do konzoly.
    • Inicializuje buffer pro příjem dat ze serveru pomocí Socket.ReceiveAsync.
    • Pokud je response potvrzením, zapíše se do konzole a smyčka se ukončí.
  • Nakonec soket client volá funkci Socket.Shutdown zadanou SocketShutdown.Both, což vypne jak operace odesílání, tak přijímání.

Vytvoření Socket serveru

Pokud chcete vytvořit serverový soket, endPoint objekt může naslouchat příchozím připojením na libovolné IP adrese, ale musí být zadáno číslo portu. Po vytvoření soketu může server přijímat příchozí připojení a komunikovat s klienty.

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|>"
}

Předchozí kód jazyka C#:

  • Vytvoří instanci nového Socket objektu s danou endPoint sadou adres instancí, objektem SocketType.Streama ProtocolType.Tcp.

  • Volá listener, který volá metodu Socket.Bind s instancí endPoint jako argumentem, aby přidružil soket k síťové adrese.

  • Socket.Listen() metoda je volána, aby naslouchala příchozím připojením.

  • listener volá metodu Socket.AcceptAsync k přijetí příchozího připojení na soketu handler.

  • Ve smyčce while :

    • Volá Socket.ReceiveAsync pro příjem dat od klienta
    • Po přijetí se data dekódují a zapíšou do konzoly.
    • Pokud zpráva response končí <|EOM|>, potvrzení se odešle klientovi pomocí Socket.SendAsync.

Spuštění ukázkového klienta a serveru

Nejprve spusťte serverová aplikace a pak spusťte klientskou aplikaci.

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...

Klientská aplikace odešle na server zprávu a server odpoví potvrzením.

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...

Viz také