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žije 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ě. Vytvoří IPEndPoint se s odpovídajícím číslem portu a jeho odpovídajícím číslem IPAddress 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 řadu adres; pro řadu IP adres je IPEndPointtřída .

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). GetHostEntryAsyncTask<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 vrácenou AddressList v poli. Následující kód získá IPAddress obsahující IP adresu serveru host.contoso.com.

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

Tip

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.ConnectAsyncendPoint s instancí jako argument.

  • Ve smyčce while :

    • Kóduje a odesílá zprávu na server pomocí .Socket.SendAsync
    • Zapíše odeslanou zprávu do konzoly.
    • Inicializuje vyrovnávací paměť pro příjem dat ze serveru pomocí Socket.ReceiveAsync.
    • response Při potvrzení se zapíše do konzoly a smyčka se ukončí.
  • Nakonec volání Socket.Shutdown soketu client zadaného SocketShutdown.Both, která 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ání listenerSocket.Bind metody s endPoint instancí jako argument pro přidružení soketu k síťové adrese.

  • Volá se Socket.Listen() metoda pro naslouchání příchozím připojením.

  • Volání listenerSocket.AcceptAsync metody přijmout příchozí připojení na soketu handler .

  • Ve smyčce while :

    • Volání Socket.ReceiveAsync pro příjem dat z klienta
    • Po přijetí se data dekódují a zapíšou do konzoly.
    • response Pokud zpráva končí <|EOM|>, potvrzení se odešle klientovi pomocí nástroje 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é