Events
Mar 17, 11 PM - Mar 21, 11 PM
Join the meetup series to build scalable AI solutions based on real-world use cases with fellow developers and experts.
Register nowThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Before you can use a socket to communicate with remote devices, the socket must be initialized with protocol and network address information. The constructor for the Socket class has parameters that specify the address family, socket type, and protocol type that the socket uses to make connections. When connecting a client socket to a server socket, the client will use an IPEndPoint
object to specify the network address of the server.
When working with System.Net.Sockets, you represent a network endpoint as an IPEndPoint object. The IPEndPoint
is constructed with an IPAddress and its corresponding port number. Before you can initiate a conversation through a Socket, you create a data pipe between your app and the remote destination.
TCP/IP uses a network address and a service port number to uniquely identify a service. The network address identifies a specific network destination; the port number identifies the specific service on that device to connect to. The combination of network address and service port is called an endpoint, which is represented in the .NET by the EndPoint class. A descendant of EndPoint
is defined for each supported address family; for the IP address family, the class is IPEndPoint.
The Dns class provides domain-name services to apps that use TCP/IP internet services. The GetHostEntryAsync method queries a DNS server to map a user-friendly domain name (such as "host.contoso.com") to a numeric Internet address (such as 192.168.1.1
). GetHostEntryAsync
returns a Task<IPHostEntry>
that when awaited contains a list of addresses and aliases for the requested name. In most cases, you can use the first address returned in the AddressList array. The following code gets an IPAddress containing the IP address for the server host.contoso.com
.
IPHostEntry ipHostInfo = await Dns.GetHostEntryAsync("host.contoso.com");
IPAddress ipAddress = ipHostInfo.AddressList[0];
Tip
For manual testing and debugging purposes, you can typically use the GetHostEntryAsync method with the resulting host name from the Dns.GetHostName() value to resolve the localhost name to an IP address. Consider the following code snippet:
var hostName = Dns.GetHostName();
IPHostEntry localhost = await Dns.GetHostEntryAsync(hostName);
// This is the IP address of the local machine
IPAddress localIpAddress = localhost.AddressList[0];
The Internet Assigned Numbers Authority (IANA) defines port numbers for common services. For more information, see IANA: Service Name and Transport Protocol Port Number Registry). Other services can have registered port numbers in the range 1,024 to 65,535. The following code combines the IP address for host.contoso.com
with a port number to create a remote endpoint for a connection.
IPEndPoint ipEndPoint = new(ipAddress, 11_000);
After determining the address of the remote device and choosing a port to use for the connection, the app can establish a connection with the remote device.
With the endPoint
object created, create a client socket to connect to the server. Once the socket is connected, it can send and receive data from the server socket connection.
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);
The preceding C# code:
Instantiates a new Socket
object with a given endPoint
instances address family, the SocketType.Stream, and ProtocolType.Tcp.
Calls the Socket.ConnectAsync method with the endPoint
instance as an argument.
In a while
loop:
response
is an acknowledgment, it is written to the console and the loop is exited.Finally, the client
socket calls Socket.Shutdown given SocketShutdown.Both, which shuts down both send and receive operations.
To create the server socket, the endPoint
object can listen for incoming connections on any IP address but the port number must be specified. Once the socket is created, the server can accept incoming connections and communicate with 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|>"
}
The preceding C# code:
Instantiates a new Socket
object with a given endPoint
instances address family, the SocketType.Stream, and ProtocolType.Tcp.
The listener
calls the Socket.Bind method with the endPoint
instance as an argument to associate the socket with the network address.
The Socket.Listen() method is called to listen for incoming connections.
The listener
calls the Socket.AcceptAsync method to accept an incoming connection on the handler
socket.
In a while
loop:
response
message ends with <|EOM|>
, an acknowledgment is sent to the client using the Socket.SendAsync.Start the server application first, and then start the client application.
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...
The client application will send a message to the server, and the server will respond with an acknowledgment.
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...
.NET feedback
.NET is an open source project. Select a link to provide feedback:
Events
Mar 17, 11 PM - Mar 21, 11 PM
Join the meetup series to build scalable AI solutions based on real-world use cases with fellow developers and experts.
Register nowTraining
Module
Send messages with RabbitMQ in a .NET Aspire project - Training
In this module, you'll learn about the RabbitMQ message broker and how you can use it to decouple microservices while ensuring that they can communicate reliably. You'll also see how .NET Aspire makes it easy to integrate with RabbitMQ.