Megosztás a következőn keresztül:


TCP foglalatok használata adatok küldésére és fogadására

Mielőtt hálózati csatlakozón keresztül tudna kommunikálni a távoli eszközökkel, a csatlakozót inicializálni kell a protokoll- és hálózati címadatokkal. Az osztály konstruktorának Socket paraméterei megadják a címcsaládot, a szoftvercsatorna típusát és a protokoll típusát, amelyet a szoftvercsatorna használ a kapcsolatok létrehozásához. Amikor egy ügyfélcsatornát egy kiszolgálócsatornához csatlakoztat, az ügyfél egy IPEndPoint objektummal adja meg a kiszolgáló hálózati címét.

IP-végpont létrehozása

A System.Net.Sockets munka során egy hálózati végpontot IPEndPoint objektumként jelöl. A IPEndPoint felépítése egy IPAddress és annak megfelelő portszámmal történik. Mielőtt beszélgetést kezdeményezhet egy Socketalkalmazáson keresztül, hozzon létre egy adatcsatornát az alkalmazás és a távoli cél között.

A TCP/IP egy hálózati címet és egy szolgáltatásportszámot használ a szolgáltatás egyedi azonosításához. A hálózati cím azonosít egy adott hálózati célt; a portszám azonosítja az adott szolgáltatást azon az eszközön, amelyhez csatlakozni szeretne. A hálózati cím és a szolgáltatásport kombinációját végpontnak nevezzük, amelyet a .NET-ben az EndPoint osztály jelöl. A program minden támogatott címcsaládhoz meghatároz egy leszármazottat EndPoint ; az IP-címcsalád esetében az osztály a IPEndPoint.

Az Dns osztály tartománynév-szolgáltatásokat biztosít a TCP/IP internetszolgáltatásokat használó alkalmazások számára. A GetHostEntryAsync módszer egy DNS-kiszolgálótól lekéri, hogy egy felhasználóbarát tartománynevet (például "host.contoso.com") egy numerikus internetcímre (például 192.168.1.1) alakítson. GetHostEntryAsync visszaad egy Task<IPHostEntry> olyan értéket, amely a várt állapotban tartalmazza a kért név címeinek és aliasainak listáját. A legtöbb esetben használhatja a AddressList által visszaadott első címet a tömbben. A következő kód egy IPAddress-t kap, amely tartalmazza a host.contoso.com szerver IP-címét.

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

Jótanács

Manuális tesztelési és hibakeresési célokra általában a GetHostEntryAsync metódust használhatja az eredményül kapott gazdagépnévvel az Dns.GetHostName() értékből a localhost név IP-címre való feloldásához. Vegye figyelembe a következő kódrészletet:

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

Az Internet Assigned Numbers Authority (IANA) a gyakori szolgáltatások portszámait határozza meg. További információért lásd: IANA: Service Name and Transport Protocol Port Number Registry Más szolgáltatások 1024 és 65 535 közötti tartományba tartozó regisztrált portszámokkal rendelkezhetnek. Az alábbi kód az IP-címet a host.contoso.com portszámmal egyesíti, hogy létrehozzon egy távoli végpontot egy kapcsolathoz.

IPEndPoint ipEndPoint = new(ipAddress, 11_000);

A távoli eszköz címének meghatározása és a kapcsolathoz használandó port kiválasztása után az alkalmazás kapcsolatot létesíthet a távoli eszközzel.

Socket Ügyfelet hozzon létre

endPoint Az objektum létrehozásával hozzon létre egy ügyfélcsatornát a kiszolgálóhoz való csatlakozáshoz. A foglalathoz csatlakoztatva adatokat küldhet és fogadhat a kiszolgáló foglalat kapcsolatától.

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

Az előző C# kód:

  • Létrehoz egy új Socket objektumot egy adott endPoint példány címcsaládjával, a SocketType.Stream és ProtocolType.Tcp.

  • Argumentumként meghívja a Socket.ConnectAsync metódust a endPoint példánnyal.

  • Ciklusban while :

    • Kódolja és elküldi az üzenetet a kiszolgálónak a használatával Socket.SendAsync.
    • Az elküldött üzenetet a konzolra írja.
    • Inicializál egy puffert, hogy adatokat fogadjon a kiszolgálóról a következő használatával Socket.ReceiveAsync: .
    • Amikor a response egy nyugtázás, a konzolra van írva, és a ciklus megszakad.
  • Végül pedig a client megadott Socket.Shutdownszoftvercsatornás hívásokSocketShutdown.Both, amelyek a küldési és fogadási műveleteket is leállítják.

Kiszolgáló létrehozása Socket

A kiszolgálócsatorna létrehozásához az endPoint objektum bármely IP-címen figyelheti a bejövő kapcsolatokat, de meg kell adni a portszámot. A csatlakozó létrehozása után a kiszolgáló fogadni tudja a bejövő kapcsolatokat, és kommunikálhat az ügyfelekkel.

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

Az előző C# kód:

  • Létrehoz egy új Socket objektumot egy adott endPoint példány címcsaládjával, a SocketType.Stream és ProtocolType.Tcp.

  • A listener meghívja a Socket.Bind metódust a endPoint példány argumentumként való megadásával, hogy a foglalatot a hálózati címhez társítsa.

  • A Socket.Listen() metódus a bejövő kapcsolatok figyelésére van meghívva.

  • A listener metódus meghívja a Socket.AcceptAsync metódust, hogy fogadjon el egy bejövő kapcsolatot a handler szoftvercsatornán.

  • Ciklusban while :

    • Az ügyféltől érkező adatok fogadására irányuló hívások Socket.ReceiveAsync .
    • Az adatok fogadásakor az adatok dekódolva lesznek, és a konzolra lesznek írva.
    • Ha az response üzenet <|EOM|>-re végződik, akkor az ügyfélnek nyugtát küldünk a Socket.SendAsync használatával.

A mintaügyfél és a kiszolgáló futtatása

Először indítsa el a kiszolgálóalkalmazást, majd indítsa el az ügyfélalkalmazást.

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

Az ügyfélalkalmazás üzenetet küld a kiszolgálónak, és a kiszolgáló nyugtával válaszol.

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

Lásd még