Sockets gebruiken om gegevens via TCP te verzenden en te ontvangen
Voordat u een socket kunt gebruiken om te communiceren met externe apparaten, moet de socket worden geïnitialiseerd met protocol- en netwerkadresgegevens. De constructor voor de Socket klasse heeft parameters die de adresfamilie, het sockettype en het protocoltype opgeven die door de socket worden gebruikt om verbindingen te maken. Wanneer u een clientsocket verbindt met een serversocket, gebruikt de client een IPEndPoint
object om het netwerkadres van de server op te geven.
Een IP-eindpunt maken
Wanneer u werkt System.Net.Sockets, vertegenwoordigt u een netwerkeindpunt als een IPEndPoint object. Het IPEndPoint
is samengesteld met een IPAddress en het bijbehorende poortnummer. Voordat u een gesprek kunt starten via een Socket, maakt u een gegevenspijp tussen uw app en de externe bestemming.
TCP/IP maakt gebruik van een netwerkadres en een servicepoortnummer om een service uniek te identificeren. Het netwerkadres identificeert een specifieke netwerkbestemming; het poortnummer identificeert de specifieke service op dat apparaat waarmee verbinding moet worden gemaakt. De combinatie van netwerkadres en servicepoort wordt een eindpunt genoemd, dat wordt weergegeven in .NET door de EndPoint klasse. Er wordt een afstammeling van EndPoint
gedefinieerd voor elke ondersteunde adresfamilie; voor de IP-adresfamilie is IPEndPointde klasse.
De Dns klasse biedt domeinnaamservices voor apps die gebruikmaken van TCP/IP-internetservices. De GetHostEntryAsync methode voert een query uit op een DNS-server om een gebruiksvriendelijke domeinnaam (zoals 'host.contoso.com') toe te wijzen aan een numeriek internetadres (zoals 192.168.1.1
). GetHostEntryAsync
retourneert een Task<IPHostEntry>
lijst met adressen en aliassen voor de aangevraagde naam wanneer dit wordt verwacht. In de meeste gevallen kunt u het eerste adres gebruiken dat in de AddressList matrix wordt geretourneerd. Met de volgende code wordt een IPAddress met het IP-adres voor de server host.contoso.com
ophaalt.
IPHostEntry ipHostInfo = await Dns.GetHostEntryAsync("host.contoso.com");
IPAddress ipAddress = ipHostInfo.AddressList[0];
Tip
Voor handmatige tests en foutopsporing kunt u doorgaans de GetHostEntryAsync methode gebruiken met de resulterende hostnaam van de Dns.GetHostName() waarde om de localhost-naam om te zetten in een IP-adres. Bekijk het volgende codefragment:
var hostName = Dns.GetHostName();
IPHostEntry localhost = await Dns.GetHostEntryAsync(hostName);
// This is the IP address of the local machine
IPAddress localIpAddress = localhost.AddressList[0];
De Internet Assigned Numbers Authority (IANA) definieert poortnummers voor algemene services. Zie IANA: Service Name and Transport Protocol Port Number Registry) voor meer informatie. Andere services kunnen poortnummers hebben geregistreerd in het bereik van 1024 tot 65.535. De volgende code combineert het IP-adres voor host.contoso.com
met een poortnummer om een extern eindpunt voor een verbinding te maken.
IPEndPoint ipEndPoint = new(ipAddress, 11_000);
Na het bepalen van het adres van het externe apparaat en het kiezen van een poort die moet worden gebruikt voor de verbinding, kan de app verbinding maken met het externe apparaat.
Socket
Een client maken
Wanneer het endPoint
object is gemaakt, maakt u een clientsocket om verbinding te maken met de server. Zodra de socket is verbonden, kan deze gegevens verzenden en ontvangen van de serversocketverbinding.
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);
De voorgaande C#-code:
Instantieert een nieuw
Socket
object met een bepaaldeendPoint
instantieadresfamilie, de SocketType.Stream, en ProtocolType.Tcp.Roept de Socket.ConnectAsync methode aan met het
endPoint
exemplaar als argument.In een
while
lus:- Codeert en verzendt een bericht naar de server met behulp van Socket.SendAsync.
- Hiermee schrijft u het verzonden bericht naar de console.
- Initialiseert een buffer voor het ontvangen van gegevens van de server met behulp van Socket.ReceiveAsync.
- Wanneer het
response
een bevestiging is, wordt deze naar de console geschreven en wordt de lus afgesloten.
Ten slotte worden de
client
socket-aanroepen Socket.Shutdown gegeven SocketShutdown.Both, waardoor zowel verzend- als ontvangstbewerkingen worden afgesloten.
Socket
Een server maken
Als u de serversocket wilt maken, kan het endPoint
object luisteren naar binnenkomende verbindingen op elk IP-adres, maar moet het poortnummer worden opgegeven. Zodra de socket is gemaakt, kan de server binnenkomende verbindingen accepteren en communiceren met clients.
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|>"
}
De voorgaande C#-code:
Instantieert een nieuw
Socket
object met een bepaaldeendPoint
instantieadresfamilie, de SocketType.Stream, en ProtocolType.Tcp.De
listener
methode wordt aangeroepen Socket.Bind met hetendPoint
exemplaar als argument om de socket te koppelen aan het netwerkadres.De Socket.Listen() methode wordt aangeroepen om te luisteren naar binnenkomende verbindingen.
De
listener
methode wordt aangeroepen Socket.AcceptAsync om een binnenkomende verbinding op dehandler
socket te accepteren.In een
while
lus:- Oproepen Socket.ReceiveAsync voor het ontvangen van gegevens van de client.
- Wanneer de gegevens worden ontvangen, worden deze gedecodeerd en naar de console geschreven.
- Als het
response
bericht eindigt,<|EOM|>
wordt er een bevestiging naar de client verzonden met behulp van de Socket.SendAsync.
De voorbeeldclient en -server uitvoeren
Start eerst de servertoepassing en start vervolgens de clienttoepassing.
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...
De clienttoepassing verzendt een bericht naar de server en de server reageert met een bevestiging.
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...