Dela via


Använda Sockets för att skicka och ta emot data via TCP

Innan du kan använda en socket för att kommunicera med fjärrenheter måste socketen initieras med protokoll- och nätverksadressinformation. Konstruktorn för Socket klassen har parametrar som anger den adressfamilj, sockettyp och protokolltyp som socketen använder för att upprätta anslutningar. När du ansluter en klientsocket till en server socket använder klienten ett IPEndPoint -objekt för att ange serverns nätverksadress.

Skapa en IP-slutpunkt

När du arbetar med System.Net.Socketsrepresenterar du en nätverksslutpunkt som ett IPEndPoint objekt. IPEndPoint är konstruerad med ett IPAddress och dess motsvarande portnummer. Innan du kan starta en konversation via en Socketskapar du en datapipe mellan din app och fjärrmålet.

TCP/IP använder en nätverksadress och ett tjänstportnummer för att unikt identifiera en tjänst. Nätverksadressen identifierar ett specifikt nätverksmål. portnumret identifierar den specifika tjänst på enheten som ska anslutas till. Kombinationen av nätverksadress och tjänstport kallas för en slutpunkt, som representeras i .NET av EndPoint klassen. En underordnad EndPoint till definieras för varje adressfamilj som stöds. För IP-adressfamiljen är IPEndPointklassen .

Klassen Dns tillhandahåller domännamnstjänster till appar som använder TCP/IP-internettjänster. Metoden GetHostEntryAsync frågar en DNS-server om du vill mappa ett användarvänligt domännamn (till exempel "host.contoso.com") till en numerisk Internetadress (till exempel 192.168.1.1). GetHostEntryAsync returnerar en Task<IPHostEntry> som när den väntar innehåller en lista med adresser och alias för det begärda namnet. I de flesta fall kan du använda den första adressen som returneras i matrisen AddressList . Följande kod hämtar en IPAddress som innehåller IP-adressen för servern host.contoso.com.

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

Dricks

För manuell testning och felsökning kan du vanligtvis använda GetHostEntryAsync metoden med det resulterande värdnamnet från Dns.GetHostName() värdet för att matcha localhost-namnet till en IP-adress. Överväg följande kodfragment:

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

IANA (Internet Assigned Numbers Authority) definierar portnummer för vanliga tjänster. Mer information finns i IANA: Service Name och Transport Protocol Port Number Registry). Andra tjänster kan ha registrerade portnummer i intervallet 1 024 till 65 535. Följande kod kombinerar IP-adressen för med ett portnummer för host.contoso.com att skapa en fjärrslutpunkt för en anslutning.

IPEndPoint ipEndPoint = new(ipAddress, 11_000);

När du har fastställt fjärrenhetens adress och valt en port som ska användas för anslutningen kan appen upprätta en anslutning till fjärrenheten.

Skapa en Socket klient

När objektet endPoint har skapats skapar du en klient socket för att ansluta till servern. När socketen är ansluten kan den skicka och ta emot data från server socketanslutningen.

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

Föregående C#-kod:

  • Instansierar ett nytt Socket objekt med en angiven endPoint instansadressfamilj, SocketType.Stream, och ProtocolType.Tcp.

  • Socket.ConnectAsync Anropar metoden med instansen endPoint som ett argument.

  • I en while loop:

    • Kodar och skickar ett meddelande till servern med hjälp av Socket.SendAsync.
    • Skriver det skickade meddelandet till konsolen.
    • Initierar en buffert för att ta emot data från servern med hjälp av Socket.ReceiveAsync.
    • response När är en bekräftelse skrivs den till konsolen och loopen avslutas.
  • Slutligen anropar socket-anropen clientSocket.ShutdownSocketShutdown.Both, som stänger av både sändnings- och mottagningsåtgärder.

Skapa en Socket server

För att skapa server-socketen endPoint kan objektet lyssna efter inkommande anslutningar på valfri IP-adress, men portnumret måste anges. När socketen har skapats kan servern acceptera inkommande anslutningar och kommunicera med klienter.

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

Föregående C#-kod:

  • Instansierar ett nytt Socket objekt med en angiven endPoint instansadressfamilj, SocketType.Stream, och ProtocolType.Tcp.

  • Anropar listenerSocket.Bind metoden med instansen endPoint som ett argument för att associera socketen med nätverksadressen.

  • Metoden Socket.Listen() anropas för att lyssna efter inkommande anslutningar.

  • Anropar listenerSocket.AcceptAsync metoden för att acceptera en inkommande anslutning i socketen handler .

  • I en while loop:

    • Anrop Socket.ReceiveAsync för att ta emot data från klienten.
    • När data tas emot avkodas och skrivs de till konsolen.
    • Om meddelandet response slutar med <|EOM|>skickas en bekräftelse till klienten med hjälp av Socket.SendAsync.

Kör exempelklienten och servern

Starta serverprogrammet först och starta sedan klientprogrammet.

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

Klientprogrammet skickar ett meddelande till servern och servern svarar med en bekräftelse.

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

Se även