Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Fontos
Az Socket osztály kifejezetten ajánlott a haladó felhasználók számára, ahelyett, hogy a TcpClient és TcpListener osztályokat használják.
A Transmission Control Protocol (TCP) használatához két lehetősége van: vagy a maximális vezérlés és teljesítmény érdekében használja a Socket-t, vagy alkalmazza a TcpClient és TcpListener segédosztályokat. TcpClient és TcpListener az osztályra System.Net.Sockets.Socket épülnek, és a könnyű használat érdekében gondoskodnak az adatok átvitelének részleteiről.
A protokollosztályok az alapul szolgáló Socket osztály használatával egyszerű hozzáférést biztosítanak a hálózati szolgáltatásokhoz az állapotinformációk fenntartása vagy a protokollspecifikus szoftvercsatornák beállításának részleteinek ismerete nélkül. Az aszinkron Socket metódusok használatához használhatja az osztály által NetworkStream biztosított aszinkron metódusokat. A Socket osztály olyan funkcióinak eléréséhez, amelyeket a protokollosztályok nem tesznek elérhetővé, az Socket osztályt kell használnia.
TcpClient és TcpListener a NetworkStream osztály használatával reprezentálják a hálózatot. A GetStream metódust használja a hálózati stream visszaadására, majd meghívja a stream NetworkStream.ReadAsync és NetworkStream.WriteAsync metódusait. A NetworkStream protokollosztályok alapjául szolgáló szoftvercsatornának nincs tulajdonosa, ezért a lezárás nem befolyásolja a szoftvercsatornát.
Használja TcpClient és TcpListener
Az TcpClient osztály TCP használatával kér adatokat egy internetes erőforrástól. Az TcpClient módszerei és tulajdonságai elvonatkoztatnak a TCP-t használó adatkérésekhez és -fogadásokhoz szükséges Socket létrehozásának részleteiről. Mivel a távoli eszközhöz való kapcsolat streamként van ábrázolva, az adatok .NET-keretrendszer streamkezelési technikákkal olvashatók és írhatók.
A TCP protokoll kapcsolatot létesít egy távoli végponttal, majd ezt a kapcsolatot használja adatcsomagok küldéséhez és fogadásához. A TCP feladata annak biztosítása, hogy az adatcsomagok a végpontra érkezve a megfelelő sorrendben legyenek összeállítva.
IP-végpont létrehozása
Amikor a System.Net.Sockets-val dolgozik, egy hálózati végpontot IPEndPoint objektumként ábrázol. 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 kérdez le, hogy egy felhasználóbarát tartománynevet (például "host.contoso.com") numerikus internetcímre (például 192.168.1.1) képezzen le.
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 a AddressList tömbben visszaadott első címet használhatja. A következő kód megszerzi azt a IPAddress elemet, amely a kiszolgáló host.contoso.com IP-címét tartalmazza.
IPHostEntry ipHostInfo = await Dns.GetHostEntryAsync("host.contoso.com");
IPAddress ipAddress = ipHostInfo.AddressList[0];
Tipp.
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: Szolgáltatásnevek és szállítási protokoll portszámok nyilvántartása). 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 host.contoso.com IP-címet portszámmal kombinálva hoz létre 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.
Hozzon létre egy TcpClient
Az TcpClient osztály a TCP-szolgáltatásokat az osztálynál Socket magasabb absztrakciós szinten biztosítja.
TcpClient egy távoli gazdagép ügyfélkapcsolatának létrehozására szolgál. Mivel tudja, hogyan lehet beszerezni egy IPEndPoint, tegyük fel, hogy van egy IPAddress, amit párosíthat a kívánt portszámmal. Az alábbi példa bemutatja egy időkiszolgálóhoz való csatlakozás beállítását a 13-as TCP-porton: TcpClient
var ipEndPoint = new IPEndPoint(ipAddress, 13);
using TcpClient client = new();
await client.ConnectAsync(ipEndPoint);
await using NetworkStream stream = client.GetStream();
var buffer = new byte[1_024];
int received = await stream.ReadAsync(buffer);
var message = Encoding.UTF8.GetString(buffer, 0, received);
Console.WriteLine($"Message received: \"{message}\"");
// Sample output:
// Message received: "📅 8/22/2022 9:07:17 AM 🕛"
Az előző C# kód:
- Hozz létre egy
IPEndPointegy ismertIPAddressés port alapján. - Példányosítson egy új
TcpClientobjektumot. - Csatlakoztatja a
clienttávoli TCP-időkiszolgálót a 13-as porton a használatával TcpClient.ConnectAsync. - NetworkStream A távoli gazdagépről származó adatok olvasására szolgál.
- Olvasási pufferként deklarál
1_024byte-ot. - Beolvassa az adatokat az olvasási
streampufferbe. - Az eredményeket karakterláncként írja a konzolra.
Mivel az ügyfél tudja, hogy az üzenet kicsi, a teljes üzenet beolvasható az olvasási pufferbe egyetlen műveletben. Nagyobb üzenetek vagy meghatározhatatlan hosszúságú üzenetek esetén az ügyfélnek a puffert megfelelőbben kell használnia, és egy while hurokban kell olvasnia.
Fontos
Üzenetek küldésekor és fogadásakor a kiszolgálónak és az ügyfélnek is előre kell tudnia az Encoding. Ha például a kiszolgáló a ASCIIEncoding használatával kommunikál, de az ügyfél megpróbálja használni UTF8Encoding, az üzenetek hibásan lesznek formázva.
Hozzon létre egy TcpListener
A TcpListener típus arra szolgál, hogy figyelje a bejövő kérések TCP-portját, majd létrehoz egy Socket vagy egy TcpClient-t, amely az ügyféllel való kapcsolatot kezeli. A Start metódus lehetővé teszi a figyelés használatát, a Stop metódus pedig letiltja a port hallgatását. A AcceptTcpClientAsync metódus fogadja a bejövő kapcsolatkéréseket, és létrehoz egy TcpClient kérést a kérés kezeléséhez, a metódus pedig fogadja a AcceptSocketAsync bejövő kapcsolatkéréseket, és létrehoz egy Socket kérést a kérés kezeléséhez.
Az alábbi példa bemutatja, hogyan hozhat létre hálózati időkiszolgálót a TcpListener 13-ás TCP-port figyeléséhez. Bejövő kapcsolatkérés elfogadásakor az időkiszolgáló a gazdakiszolgáló aktuális dátumával és időpontjával válaszol.
var ipEndPoint = new IPEndPoint(IPAddress.Any, 13);
TcpListener listener = new(ipEndPoint);
try
{
listener.Start();
using TcpClient handler = await listener.AcceptTcpClientAsync();
await using NetworkStream stream = handler.GetStream();
var message = $"📅 {DateTime.Now} 🕛";
var dateTimeBytes = Encoding.UTF8.GetBytes(message);
await stream.WriteAsync(dateTimeBytes);
Console.WriteLine($"Sent message: \"{message}\"");
// Sample output:
// Sent message: "📅 8/22/2022 9:07:17 AM 🕛"
}
finally
{
listener.Stop();
}
Az előző C# kód:
- Létrehoz egy
IPEndPointIPAddress.Any-val és port. - Példányosítson egy új
TcpListenerobjektumot. - Meghívja a Start metódust, hogy figyelni kezdjen a porton.
- A AcceptTcpClientAsync metódus egy
TcpClient-ját/ét használja a bejövő kapcsolatkérések fogadására. - Az aktuális dátumot és időt sztringüzenetként kódolja.
- NetworkStream használatával adatot ír a csatlakoztatott ügyfélnek.
- Az elküldött üzenetet a konzolra írja.
- Végül meghívja a Stop metódust, hogy leállítsa a port figyelését.
Véges TCP-vezérlő az Socket osztálysal
Mind a TcpClient, mind a TcpListener belsőleg az Socket osztályra támaszkodik, ami azt jelenti, hogy bármi, amit ezekkel az osztályokkal el lehet érni, közvetlenül az aljzatok használatával is megvalósítható. Ez a szakasz számos TcpClient és TcpListener használati esetet mutat be, valamint funkcionálisan egyenértékű Socket megfelelőjüket.
Ügyfélcsatorna létrehozása
TcpClientAz alapértelmezett konstruktor egy kettős veremű socketet próbál létrehozni a Socket(SocketType, ProtocolType) konstruktoron keresztül. Ez a konstruktor kettős veremű csatlakozót hoz létre, ha az IPv6 támogatott, ellenkező esetben visszavált az IPv4-re.
Vegye figyelembe a következő TCP-ügyfélkódot:
using var client = new TcpClient();
Az előző TCP-ügyfélkód funkcionálisan egyenértékű a következő szoftvercsatornás kóddal:
using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
A TcpClient(AddressFamily) konstruktor
Ez a konstruktor csak három AddressFamily értéket fogad el; ellenkező esetben egy ArgumentException kivételt dob. Az érvényes értékek a következők:
- AddressFamily.InterNetwork: IPv4-szoftvercsatornához.
- AddressFamily.InterNetworkV6: IPv6-szoftvercsatornához.
- AddressFamily.Unknown: ez egy dual-stack socketet próbál létrehozni, hasonlóan az alapértelmezett konstruktorhoz.
Vegye figyelembe a következő TCP-ügyfélkódot:
using var client = new TcpClient(AddressFamily.InterNetwork);
Az előző TCP-ügyfélkód funkcionálisan egyenértékű a következő szoftvercsatornás kóddal:
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
A TcpClient(IPEndPoint) konstruktor
A szoftvercsatorna létrehozásakor a konstruktor a megadott helyi címhez is kapcsolódik/csatlakozikIPEndPoint. A IPEndPoint.AddressFamily tulajdonság a socket cím-családjának meghatározására szolgál.
Vegye figyelembe a következő TCP-ügyfélkódot:
var endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5001);
using var client = new TcpClient(endPoint);
Az előző TCP-ügyfélkód funkcionálisan egyenértékű a következő szoftvercsatornás kóddal:
// Example IPEndPoint object
var endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5001);
using var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(endPoint);
A TcpClient(String, Int32) konstruktor
Ez a konstruktor megpróbál létrehozni egy kettős veremű struktúrát, amely hasonló az alapértelmezett konstruktorhoz, és csatlakoztatja a távoli DNS végponthoz, amelyet a hostname és port páros határoz meg.
Vegye figyelembe a következő TCP-ügyfélkódot:
using var client = new TcpClient("www.example.com", 80);
Az előző TCP-ügyfélkód funkcionálisan egyenértékű a következő szoftvercsatornás kóddal:
using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
socket.Connect("www.example.com", 80);
Csatlakozás kiszolgálóhoz
Az összes Connect, ConnectAsyncBeginConnectés EndConnect a TcpClient túlterhelések funkcionálisan egyenértékűek a megfelelő Socket módszerekkel.
Vegye figyelembe a következő TCP-ügyfélkódot:
using var client = new TcpClient();
client.Connect("www.example.com", 80);
A fenti TcpClient kód egyenértékű a következő socket kóddal:
using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
socket.Connect("www.example.com", 80);
Szerver socket létrehozása
A nyers TcpClient megfelelőkkel funkcionális egyenértékűséggel rendelkező példányokhoz hasonlóan ez a szakasz a TcpListener konstruktorokat a megfelelő socket kódhoz rendeli. Az első konstruktor, amelyet figyelembe kell venni, a TcpListener(IPAddress localaddr, int port).
var listener = new TcpListener(IPAddress.Loopback, 5000);
Az előző TCP-figyelőkód funkcionálisan egyenértékű a következő szoftvercsatornás kóddal:
var ep = new IPEndPoint(IPAddress.Loopback, 5000);
using var socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
Hallgatózás indítása a kiszolgálón
A Start() metódus egy burkoló, amely egyesíti a Socket és a BindListen() funkcionalitását.
Vegye figyelembe a következő TCP-figyelőkódot:
var listener = new TcpListener(IPAddress.Loopback, 5000);
listener.Start(10);
Az előző TCP-figyelőkód funkcionálisan egyenértékű a következő szoftvercsatornás kóddal:
var endPoint = new IPEndPoint(IPAddress.Loopback, 5000);
using var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(endPoint);
try
{
socket.Listen(10);
}
catch (SocketException)
{
socket.Dispose();
}
Kiszolgálókapcsolat elfogadása
A háttérben a bejövő TCP-kapcsolatok mindig új socketet hoznak létre, amikor elfogadják őket.
TcpListener elfogadhat közvetlenül egy Socket példányt (AcceptSocket() vagy AcceptSocketAsync() útján), vagy elfogadhat egy TcpClient-t (AcceptTcpClient() és AcceptTcpClientAsync() útján).
Vegye figyelembe a következő TcpListener kódot:
var listener = new TcpListener(IPAddress.Loopback, 5000);
using var acceptedSocket = await listener.AcceptSocketAsync();
// Synchronous alternative.
// var acceptedSocket = listener.AcceptSocket();
Az előző TCP-figyelőkód funkcionálisan egyenértékű a következő szoftvercsatornás kóddal:
var endPoint = new IPEndPoint(IPAddress.Loopback, 5000);
using var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
using var acceptedSocket = await socket.AcceptAsync();
// Synchronous alternative
// var acceptedSocket = socket.Accept();
Hozzon létre egy NetworkStream az adatok küldésére és fogadására.
Az TcpClient esetében egy NetworkStream-t kell példányosítania a GetStream() metódus segítségével, hogy adatokat küldhessen és fogadhasson. A Socket használatával manuálisan kell elvégeznie a NetworkStream létrehozását.
Vegye figyelembe a következő TcpClient kódot:
using var client = new TcpClient();
using NetworkStream stream = client.GetStream();
Ami egyenértékű a következő socket-kóddal:
using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
// Be aware that transferring the ownership means that closing/disposing the stream will also close the underlying socket.
using var stream = new NetworkStream(socket, ownsSocket: true);
Tipp.
Ha a kódnak nem kell egy példánnyal Stream dolgoznia, közvetlenül támaszkodhat a Socket küldési/fogadási metódusaira (Send, SendAsync, Receive és ReceiveAsync) ahelyett, hogy létrehoz egy példányt NetworkStream.