Windows 网络编程 - C# 示例
Windows平台C#网络编程示例,包括HTTP请求、TCP套接字、UDP通信和Web服务器实现
💻 HTTP请求与HttpClient csharp
🟢 simple
⭐⭐
使用C# HttpClient进行GET、POST、PUT、DELETE HTTP请求,包括错误处理和异步操作
⏱️ 25 min
🏷️ csharp, http, networking, async, rest api, windows
Prerequisites:
C# async/await, HTTP protocol basics, JSON serialization
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Text;
using System.Text.Json;
class HttpRequestsDemo
{
private static readonly HttpClient httpClient = new HttpClient();
// 1. Simple GET request
public static async Task SimpleGetRequest()
{
Console.WriteLine("=== Simple GET Request ===");
try
{
// Set base address
httpClient.BaseAddress = new Uri("https://jsonplaceholder.typicode.com");
Console.WriteLine("Making GET request to /posts/1...");
HttpResponseMessage response = await httpClient.GetAsync("/posts/1");
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Response Status: {response.StatusCode}");
Console.WriteLine($"Response Content: {content}");
}
else
{
Console.WriteLine($"Request failed with status: {response.StatusCode}");
}
}
catch (HttpRequestException ex)
{
Console.WriteLine($"HTTP Request Error: {ex.Message}");
}
catch (TaskCanceledException)
{
Console.WriteLine("Request timed out");
}
}
// 2. GET request with query parameters
public static async Task GetWithQueryParameters()
{
Console.WriteLine("\n=== GET Request with Query Parameters ===");
try
{
string userId = "1";
string url = $"/posts?userId={userId}&_limit=5";
Console.WriteLine($"Making GET request to: {url}");
HttpResponseMessage response = await httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Response Status: {response.StatusCode}");
Console.WriteLine($"Response Content: {content}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
// 3. POST request with JSON body
public static async Task PostRequestWithJson()
{
Console.WriteLine("\n=== POST Request with JSON Body ===");
try
{
var postData = new
{
title = "My New Post",
body = "This is the content of my new post",
userId = 1
};
string jsonContent = JsonSerializer.Serialize(postData);
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
Console.WriteLine("Sending POST request to /posts...");
Console.WriteLine($"Request Body: {jsonContent}");
HttpResponseMessage response = await httpClient.PostAsync("/posts", content);
if (response.IsSuccessStatusCode)
{
string responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Response Status: {response.StatusCode}");
Console.WriteLine($"Response Content: {responseContent}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
// 4. PUT request to update resource
public static async Task PutRequestToUpdate()
{
Console.WriteLine("\n=== PUT Request to Update Resource ===");
try
{
var updateData = new
{
id = 1,
title = "Updated Post Title",
body = "This post has been updated",
userId = 1
};
string jsonContent = JsonSerializer.Serialize(updateData);
var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
Console.WriteLine("Sending PUT request to /posts/1...");
Console.WriteLine($"Request Body: {jsonContent}");
HttpResponseMessage response = await httpClient.PutAsync("/posts/1", content);
if (response.IsSuccessStatusCode)
{
string responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Response Status: {response.StatusCode}");
Console.WriteLine($"Response Content: {responseContent}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
// 5. DELETE request
public static async Task DeleteRequest()
{
Console.WriteLine("\n=== DELETE Request ===");
try
{
Console.WriteLine("Sending DELETE request to /posts/1...");
HttpResponseMessage response = await httpClient.DeleteAsync("/posts/1");
if (response.IsSuccessStatusCode)
{
string responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Response Status: {response.StatusCode}");
Console.WriteLine($"Response Content: {responseContent}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
// 6. Request with custom headers
public static async Task RequestWithCustomHeaders()
{
Console.WriteLine("\n=== Request with Custom Headers ===");
try
{
// Clear existing headers
httpClient.DefaultRequestHeaders.Clear();
// Add custom headers
httpClient.DefaultRequestHeaders.Add("User-Agent", "MyCSharpApp/1.0");
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
httpClient.DefaultRequestHeaders.Add("X-Custom-Header", "CustomValue");
Console.WriteLine("Headers added to request");
HttpResponseMessage response = await httpClient.GetAsync("/posts/1");
if (response.IsSuccessStatusCode)
{
// Display response headers
Console.WriteLine("\nResponse Headers:");
foreach (var header in response.Headers)
{
Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
}
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine($"\nResponse Content: {content}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
// 7. Request with timeout
public static async Task RequestWithTimeout()
{
Console.WriteLine("\n=== Request with Timeout ===");
try
{
// Set timeout to 2 seconds
httpClient.Timeout = TimeSpan.FromSeconds(2);
Console.WriteLine("Making request with 2-second timeout...");
// This might timeout if the server is slow
HttpResponseMessage response = await httpClient.GetAsync("https://httpbin.org/delay/5");
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Request completed: {content}");
}
}
catch (TaskCanceledException)
{
Console.WriteLine("Request timed out after 2 seconds");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
// Reset timeout
httpClient.Timeout = TimeSpan.FromSeconds(30);
}
}
// 8. Download file
public static async Task DownloadFile()
{
Console.WriteLine("\n=== Download File ===");
try
{
string fileUrl = "https://jsonplaceholder.typicode.com/posts/1";
string localFilePath = "downloaded_post.json";
Console.WriteLine($"Downloading file from: {fileUrl}");
HttpResponseMessage response = await httpClient.GetAsync(fileUrl);
response.EnsureSuccessStatusCode();
// Save to file
byte[] fileBytes = await response.Content.ReadAsByteArrayAsync();
await System.IO.File.WriteAllBytesAsync(localFilePath, fileBytes);
Console.WriteLine($"File downloaded successfully to: {localFilePath}");
Console.WriteLine($"File size: {fileBytes.Length} bytes");
// Display file content
string content = await System.IO.File.ReadAllTextAsync(localFilePath);
Console.WriteLine($"\nFile content: {content}");
// Cleanup
if (System.IO.File.Exists(localFilePath))
{
System.IO.File.Delete(localFilePath);
Console.WriteLine($"Cleaned up: {localFilePath}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error downloading file: {ex.Message}");
}
}
// 9. Upload file with multipart/form-data
public static async Task UploadFile()
{
Console.WriteLine("\n=== Upload File with Multipart Form Data ===");
try
{
// Create a temporary file to upload
string tempFilePath = "upload_test.txt";
await System.IO.File.WriteAllTextAsync(tempFilePath, "This is a test file for upload\nSecond line\nThird line");
using (var form = new MultipartFormDataContent())
{
// Add file
var fileContent = new ByteArrayContent(await System.IO.File.ReadAllBytesAsync(tempFilePath));
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("text/plain");
form.Add(fileContent, "file", "test_upload.txt");
// Add form fields
form.Add(new StringContent("Document"), "documentType");
form.Add(new StringContent("Description of uploaded file"), "description");
Console.WriteLine("Uploading file with form data...");
// Note: This endpoint may not actually accept file uploads
// In real scenario, use proper file upload endpoint
HttpResponseMessage response = await httpClient.PostAsync("https://httpbin.org/post", form);
if (response.IsSuccessStatusCode)
{
string responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Upload response: {responseContent}");
}
}
// Cleanup
if (System.IO.File.Exists(tempFilePath))
{
System.IO.File.Delete(tempFilePath);
}
}
catch (Exception ex)
{
Console.WriteLine($"Error uploading file: {ex.Message}");
}
}
// 10. Parallel requests
public static async Task ParallelRequests()
{
Console.WriteLine("\n=== Parallel HTTP Requests ===");
try
{
string[] endpoints = { "/posts/1", "/posts/2", "/posts/3", "/posts/4", "/posts/5" };
Console.WriteLine("Making 5 parallel requests...");
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
// Create tasks for parallel requests
var tasks = endpoints.Select(async endpoint =>
{
try
{
var response = await httpClient.GetAsync(endpoint);
return new { Endpoint = endpoint, Status = response.StatusCode, Success = response.IsSuccessStatusCode };
}
catch (Exception ex)
{
return new { Endpoint = endpoint, Status = System.Net.HttpStatusCode.ServiceUnavailable, Success = false, Error = ex.Message };
}
});
// Wait for all requests to complete
var results = await Task.WhenAll(tasks);
stopwatch.Stop();
Console.WriteLine($"All {results.Length} requests completed in {stopwatch.ElapsedMilliseconds}ms");
foreach (var result in results)
{
if (result.Success)
{
Console.WriteLine($"✓ {result.Endpoint}: {result.Status}");
}
else
{
Console.WriteLine($"✗ {result.Endpoint}: {result.Status} {result.Error}");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error in parallel requests: {ex.Message}");
}
}
// 11. Advanced error handling and retry logic
public static async Task RequestWithRetry()
{
Console.WriteLine("\n=== Request with Retry Logic ===");
int maxRetries = 3;
int delayMs = 1000;
for (int attempt = 1; attempt <= maxRetries; attempt++)
{
try
{
Console.WriteLine($"Attempt {attempt} of {maxRetries}");
// Use a URL that might fail sometimes
HttpResponseMessage response = await httpClient.GetAsync("https://httpbin.org/status/200,500");
if (response.IsSuccessStatusCode)
{
Console.WriteLine($"✓ Request succeeded on attempt {attempt}");
return;
}
else if ((int)response.StatusCode >= 500)
{
Console.WriteLine($"Server error: {response.StatusCode}, retrying...");
if (attempt < maxRetries)
{
await Task.Delay(delayMs * attempt); // Exponential backoff
}
}
else
{
Console.WriteLine($"Client error: {response.StatusCode}, not retrying");
return;
}
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Network error on attempt {attempt}: {ex.Message}");
if (attempt < maxRetries)
{
await Task.Delay(delayMs * attempt);
}
}
}
Console.WriteLine("All retry attempts failed");
}
// 12. HTTP response streaming
public static async Task StreamResponse()
{
Console.WriteLine("\n=== HTTP Response Streaming ===");
try
{
HttpResponseMessage response = await httpClient.GetAsync("https://jsonplaceholder.typicode.com/posts", HttpCompletionOption.ResponseHeadersRead);
using (var stream = await response.Content.ReadAsStreamAsync())
using (var reader = new System.IO.StreamReader(stream))
{
char[] buffer = new char[1024];
int bytesRead;
int totalChars = 0;
Console.WriteLine("Streaming response content...");
while ((bytesRead = await reader.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
totalChars += bytesRead;
string chunk = new string(buffer, 0, bytesRead);
Console.Write(chunk);
// Break after reading some content for demo
if (totalChars > 1000)
{
Console.WriteLine("\n... (streaming continues)");
break;
}
}
Console.WriteLine($"\n\nTotal characters read: {totalChars}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error streaming response: {ex.Message}");
}
}
// 13. HTTP client with proxy
public static async Task RequestWithProxy()
{
Console.WriteLine("\n=== HTTP Request with Proxy ===");
try
{
// Note: This is example code - proxy details would be different in real scenario
var proxy = new System.Net.WebProxy("http://proxy.example.com:8080")
{
BypassProxyOnLocal = false
};
// Create new HttpClient with proxy
var httpClientWithProxy = new HttpClient(new HttpClientHandler
{
Proxy = proxy,
UseProxy = true
});
Console.WriteLine("Making request through proxy...");
// This would be replaced with actual request in real scenario
Console.WriteLine("Proxy configuration complete (demo - not actually making request)");
httpClientWithProxy.Dispose();
}
catch (Exception ex)
{
Console.WriteLine($"Error with proxy: {ex.Message}");
}
}
static async Task Main(string[] args)
{
Console.WriteLine("=== C# HTTP Requests Demo ===\n");
try
{
await SimpleGetRequest();
await GetWithQueryParameters();
await PostRequestWithJson();
await PutRequestToUpdate();
await DeleteRequest();
await RequestWithCustomHeaders();
await RequestWithTimeout();
await DownloadFile();
await UploadFile();
await ParallelRequests();
await RequestWithRetry();
await StreamResponse();
await RequestWithProxy();
Console.WriteLine("\nAll HTTP request examples completed successfully!");
}
catch (Exception ex)
{
Console.WriteLine($"Error in HTTP demo: {ex.Message}");
}
finally
{
httpClient?.Dispose();
}
}
}
💻 TCP套接字编程 csharp
🟡 intermediate
⭐⭐⭐
创建TCP客户端和服务器进行双向通信,使用C#套接字
⏱️ 30 min
🏷️ csharp, tcp, socket, networking, server, client, windows
Prerequisites:
C# async/await, Network programming basics, TCP/IP understanding
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
class TcpSocketDemo
{
// 1. Simple TCP Server
public static async Task SimpleTcpServer()
{
Console.WriteLine("=== Simple TCP Server ===");
int port = 8080;
TcpListener server = null;
try
{
server = new TcpListener(IPAddress.Any, port);
server.Start();
Console.WriteLine($"TCP Server started on port {port}");
Console.WriteLine("Waiting for client connections...");
while (true)
{
TcpClient client = await server.AcceptTcpClientAsync();
Console.WriteLine($"Client connected from {client.Client.RemoteEndPoint}");
// Handle client in a separate task
_ = Task.Run(() => HandleSimpleClient(client));
}
}
catch (Exception ex)
{
Console.WriteLine($"Server error: {ex.Message}");
}
finally
{
server?.Stop();
}
}
static async Task HandleSimpleClient(TcpClient client)
{
try
{
using (client)
using (NetworkStream stream = client.GetStream())
{
byte[] buffer = new byte[1024];
StringBuilder message = new StringBuilder();
while (true)
{
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0) break; // Client disconnected
string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
message.Append(data);
if (data.Contains("\n"))
{
string fullMessage = message.ToString().Trim();
Console.WriteLine($"Received: {fullMessage}");
// Echo back response
string response = $"Server received: {fullMessage}\n";
byte[] responseBytes = Encoding.UTF8.GetBytes(response);
await stream.WriteAsync(responseBytes, 0, responseBytes.Length);
message.Clear();
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error handling client: {ex.Message}");
}
finally
{
Console.WriteLine($"Client disconnected");
}
}
// 2. Simple TCP Client
public static async Task SimpleTcpClient(string serverIp = "127.0.0.1", int port = 8080)
{
Console.WriteLine("\n=== Simple TCP Client ===");
try
{
using (TcpClient client = new TcpClient())
{
Console.WriteLine($"Connecting to server {serverIp}:{port}...");
await client.ConnectAsync(serverIp, port);
Console.WriteLine("Connected to server!");
using (NetworkStream stream = client.GetStream())
{
// Send messages
string[] messages = {
"Hello, Server!",
"This is message 2",
"Final message from client"
};
foreach (string message in messages)
{
Console.WriteLine($"Sending: {message}");
byte[] messageBytes = Encoding.UTF8.GetBytes(message + "\n");
await stream.WriteAsync(messageBytes, 0, messageBytes.Length);
// Receive response
byte[] buffer = new byte[1024];
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
string response = Encoding.UTF8.GetString(buffer, 0, bytesRead).Trim();
Console.WriteLine($"Received: {response}");
await Task.Delay(1000);
}
}
Console.WriteLine("Communication completed");
}
}
catch (Exception ex)
{
Console.WriteLine($"Client error: {ex.Message}");
}
}
// 3. TCP Server with Multiple Client Support
public static async Task MultiClientTcpServer()
{
Console.WriteLine("\n=== Multi-Client TCP Server ===");
int port = 8081;
TcpListener server = null;
ConcurrentDictionary<string, TcpClient> clients = new ConcurrentDictionary<string, TcpClient>();
try
{
server = new TcpListener(IPAddress.Any, port);
server.Start();
Console.WriteLine($"Multi-client server started on port {port}");
// Accept clients continuously
while (true)
{
TcpClient client = await server.AcceptTcpClientAsync();
string clientId = $"Client_{DateTime.Now:HHmmss}_{client.Client.RemoteEndPoint}";
clients[clientId] = client;
Console.WriteLine($"New client connected: {clientId}");
_ = Task.Run(() => HandleMultiClient(client, clientId, clients));
}
}
catch (Exception ex)
{
Console.WriteLine($"Server error: {ex.Message}");
}
finally
{
server?.Stop();
}
}
static async Task HandleMultiClient(TcpClient client, string clientId, ConcurrentDictionary<string, TcpClient> clients)
{
try
{
using (client)
using (NetworkStream stream = client.GetStream())
{
// Send welcome message
string welcome = $"Welcome! You are {clientId}. Connected clients: {clients.Count}\n";
byte[] welcomeBytes = Encoding.UTF8.GetBytes(welcome);
await stream.WriteAsync(welcomeBytes, 0, welcomeBytes.Length);
while (true)
{
byte[] buffer = new byte[1024];
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0) break;
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead).Trim();
Console.WriteLine($"{clientId}: {message}");
// Broadcast message to all clients (except sender)
string broadcastMsg = $"{clientId}: {message}\n";
byte[] broadcastBytes = Encoding.UTF8.GetBytes(broadcastMsg);
foreach (var kvp in clients)
{
try
{
if (kvp.Key != clientId && kvp.Value.Connected)
{
NetworkStream clientStream = kvp.Value.GetStream();
await clientStream.WriteAsync(broadcastBytes, 0, broadcastBytes.Length);
}
}
catch
{
// Remove disconnected client
clients.TryRemove(kvp.Key, out _);
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error handling client {clientId}: {ex.Message}");
}
finally
{
clients.TryRemove(clientId, out _);
Console.WriteLine($"{clientId} disconnected");
}
}
// 4. TCP File Transfer Server
public static async Task FileTransferServer()
{
Console.WriteLine("\n=== TCP File Transfer Server ===");
int port = 8082;
TcpListener server = null;
try
{
server = new TcpListener(IPAddress.Any, port);
server.Start();
Console.WriteLine($"File transfer server started on port {port}");
while (true)
{
TcpClient client = await server.AcceptTcpClientAsync();
Console.WriteLine($"File client connected from {client.Client.RemoteEndPoint}");
_ = Task.Run(() => HandleFileTransferClient(client));
}
}
catch (Exception ex)
{
Console.WriteLine($"File server error: {ex.Message}");
}
finally
{
server?.Stop();
}
}
static async Task HandleFileTransferClient(TcpClient client)
{
try
{
using (client)
using (NetworkStream stream = client.GetStream())
{
// Receive filename
byte[] fileNameBuffer = new byte[256];
int fileNameBytes = await stream.ReadAsync(fileNameBuffer, 0, fileNameBuffer.Length);
string fileName = Encoding.UTF8.GetString(fileNameBuffer, 0, fileNameBytes).Trim('\0');
Console.WriteLine($"Receiving file: {fileName}");
// Receive file size
byte[] fileSizeBuffer = new byte[8];
await stream.ReadAsync(fileSizeBuffer, 0, 8);
long fileSize = BitConverter.ToInt64(fileSizeBuffer, 0);
Console.WriteLine($"File size: {fileSize} bytes");
// Receive file content
using (var fileStream = System.IO.File.Create($"received_{fileName}"))
{
long totalBytesReceived = 0;
byte[] buffer = new byte[8192];
while (totalBytesReceived < fileSize)
{
int bytesToRead = (int)Math.Min(buffer.Length, fileSize - totalBytesReceived);
int bytesRead = await stream.ReadAsync(buffer, 0, bytesToRead);
if (bytesRead == 0) break;
await fileStream.WriteAsync(buffer, 0, bytesRead);
totalBytesReceived += bytesRead;
// Show progress
double progress = (double)totalBytesReceived / fileSize * 100;
Console.Write($"\rProgress: {progress:F1}% ({totalBytesReceived:N0}/{fileSize:N0} bytes)");
}
Console.WriteLine("\nFile received successfully!");
}
// Send confirmation
string confirmation = "File received successfully\n";
byte[] confirmationBytes = Encoding.UTF8.GetBytes(confirmation);
await stream.WriteAsync(confirmationBytes, 0, confirmationBytes.Length);
}
}
catch (Exception ex)
{
Console.WriteLine($"File transfer error: {ex.Message}");
}
}
// 5. TCP File Transfer Client
public static async Task FileTransferClient(string filePath, string serverIp = "127.0.0.1", int port = 8082)
{
Console.WriteLine("\n=== TCP File Transfer Client ===");
if (!System.IO.File.Exists(filePath))
{
Console.WriteLine($"File not found: {filePath}");
return;
}
try
{
using (TcpClient client = new TcpClient())
{
Console.WriteLine($"Connecting to file server {serverIp}:{port}...");
await client.ConnectAsync(serverIp, port);
Console.WriteLine("Connected to file server!");
using (NetworkStream stream = client.GetStream())
using (var fileStream = System.IO.File.OpenRead(filePath))
{
// Send filename
string fileName = System.IO.Path.GetFileName(filePath);
byte[] fileNameBytes = Encoding.UTF8.GetBytes(fileName);
await stream.WriteAsync(fileNameBytes, 0, fileNameBytes.Length);
Console.WriteLine($"Sending file: {fileName}");
// Send file size
long fileSize = fileStream.Length;
byte[] fileSizeBytes = BitConverter.GetBytes(fileSize);
await stream.WriteAsync(fileSizeBytes, 0, fileSizeBytes.Length);
Console.WriteLine($"File size: {fileSize:N0} bytes");
// Send file content
byte[] buffer = new byte[8192];
long totalBytesSent = 0;
while (totalBytesSent < fileSize)
{
int bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length);
await stream.WriteAsync(buffer, 0, bytesRead);
totalBytesSent += bytesRead;
// Show progress
double progress = (double)totalBytesSent / fileSize * 100;
Console.Write($"\rProgress: {progress:F1}% ({totalBytesSent:N0}/{fileSize:N0} bytes)");
}
Console.WriteLine("\nFile sent successfully!");
// Receive confirmation
byte[] confirmationBuffer = new byte[1024];
int confirmationBytes = await stream.ReadAsync(confirmationBuffer, 0, confirmationBuffer.Length);
string confirmation = Encoding.UTF8.GetString(confirmationBuffer, 0, confirmationBytes).Trim();
Console.WriteLine($"Server confirmation: {confirmation}");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"File transfer client error: {ex.Message}");
}
}
// 6. TCP Chat Server
public static async Task TcpChatServer()
{
Console.WriteLine("\n=== TCP Chat Server ===");
int port = 8083;
TcpListener server = null;
ConcurrentDictionary<string, TcpClient> chatClients = new ConcurrentDictionary<string, TcpClient>();
try
{
server = new TcpListener(IPAddress.Any, port);
server.Start();
Console.WriteLine($"Chat server started on port {port}");
// Accept clients
while (true)
{
TcpClient client = await server.AcceptTcpClientAsync();
string username = await GetUsername(client);
if (username != null)
{
chatClients[username] = client;
Console.WriteLine($"{username} joined the chat");
// Broadcast join message
await BroadcastMessage($"{username} joined the chat\n", chatClients, username);
_ = Task.Run(() => HandleChatClient(client, username, chatClients));
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Chat server error: {ex.Message}");
}
finally
{
server?.Stop();
}
}
static async Task<string> GetUsername(TcpClient client)
{
try
{
using (NetworkStream stream = client.GetStream())
{
byte[] buffer = new byte[1024];
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
string username = Encoding.UTF8.GetString(buffer, 0, bytesRead).Trim();
return !string.IsNullOrEmpty(username) ? username : null;
}
}
catch
{
return null;
}
}
static async Task HandleChatClient(TcpClient client, string username, ConcurrentDictionary<string, TcpClient> clients)
{
try
{
using (client)
using (NetworkStream stream = client.GetStream())
{
while (true)
{
byte[] buffer = new byte[1024];
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0) break;
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead).Trim();
Console.WriteLine($"{username}: {message}");
// Broadcast message to all clients
await BroadcastMessage($"{username}: {message}\n", clients);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error handling {username}: {ex.Message}");
}
finally
{
clients.TryRemove(username, out _);
Console.WriteLine($"{username} left the chat");
// Broadcast leave message
_ = BroadcastMessage($"{username} left the chat\n", clients);
}
}
static async Task BroadcastMessage(string message, ConcurrentDictionary<string, TcpClient> clients, string excludeUser = null)
{
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
foreach (var kvp in clients)
{
if (kvp.Key != excludeUser)
{
try
{
NetworkStream stream = kvp.Value.GetStream();
await stream.WriteAsync(messageBytes, 0, messageBytes.Length);
}
catch
{
// Remove disconnected client
clients.TryRemove(kvp.Key, out _);
}
}
}
}
// 7. TCP Chat Client
public static async Task TcpChatClient(string username, string serverIp = "127.0.0.1", int port = 8083)
{
Console.WriteLine("\n=== TCP Chat Client ===");
try
{
using (TcpClient client = new TcpClient())
{
Console.WriteLine($"Connecting to chat server {serverIp}:{port}...");
await client.ConnectAsync(serverIp, port);
Console.WriteLine("Connected to chat server!");
using (NetworkStream stream = client.GetStream())
{
// Send username
byte[] usernameBytes = Encoding.UTF8.GetBytes(username);
await stream.WriteAsync(usernameBytes, 0, usernameBytes.Length);
// Start receiving messages
_ = Task.Run(async () =>
{
byte[] buffer = new byte[1024];
while (true)
{
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0) break;
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.Write(message);
}
});
// Send messages from console
Console.WriteLine("\nType your messages (type 'quit' to exit):");
while (true)
{
string input = Console.ReadLine();
if (string.IsNullOrEmpty(input)) continue;
if (input.ToLower() == "quit")
{
break;
}
byte[] messageBytes = Encoding.UTF8.GetBytes(input);
await stream.WriteAsync(messageBytes, 0, messageBytes.Length);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Chat client error: {ex.Message}");
}
}
// 8. TCP Server with Protocol
public static async Task ProtocolTcpServer()
{
Console.WriteLine("\n=== TCP Server with Protocol ===");
int port = 8084;
TcpListener server = null;
try
{
server = new TcpListener(IPAddress.Any, port);
server.Start();
Console.WriteLine($"Protocol server started on port {port}");
while (true)
{
TcpClient client = await server.AcceptTcpClientAsync();
Console.WriteLine($"Protocol client connected from {client.Client.RemoteEndPoint}");
_ = Task.Run(() => HandleProtocolClient(client));
}
}
catch (Exception ex)
{
Console.WriteLine($"Protocol server error: {ex.Message}");
}
finally
{
server?.Stop();
}
}
static async Task HandleProtocolClient(TcpClient client)
{
try
{
using (client)
using (NetworkStream stream = client.GetStream())
{
while (true)
{
// Read message type (1 byte)
byte[] typeBuffer = new byte[1];
int typeBytesRead = await stream.ReadAsync(typeBuffer, 0, 1);
if (typeBytesRead == 0) break;
byte messageType = typeBuffer[0];
// Read message length (4 bytes)
byte[] lengthBuffer = new byte[4];
await stream.ReadAsync(lengthBuffer, 0, 4);
int messageLength = BitConverter.ToInt32(lengthBuffer, 0);
// Read message content
byte[] messageBuffer = new byte[messageLength];
await stream.ReadAsync(messageBuffer, 0, messageLength);
string messageContent = Encoding.UTF8.GetString(messageBuffer);
Console.WriteLine($"Received message type: {messageType}, length: {messageLength}, content: {messageContent}");
// Process and respond based on message type
string response = ProcessMessage(messageType, messageContent);
await SendProtocolMessage(stream, messageType, response);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Protocol client error: {ex.Message}");
}
}
static string ProcessMessage(byte messageType, string content)
{
switch (messageType)
{
case 1: // Echo
return $"Echo: {content}";
case 2: // Upper case
return content.ToUpper();
case 3: // Reverse
char[] chars = content.ToCharArray();
Array.Reverse(chars);
return new string(chars);
case 4: // Get time
return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
default:
return "Unknown message type";
}
}
static async Task SendProtocolMessage(NetworkStream stream, byte messageType, string content)
{
byte[] messageBytes = Encoding.UTF8.GetBytes(content);
byte[] lengthBytes = BitConverter.GetBytes(messageBytes.Length);
await stream.WriteAsync(new byte[] { messageType }, 0, 1);
await stream.WriteAsync(lengthBytes, 0, 4);
await stream.WriteAsync(messageBytes, 0, messageBytes.Length);
}
// 9. TCP Protocol Client
public static async Task ProtocolTcpClient(string serverIp = "127.0.0.1", int port = 8084)
{
Console.WriteLine("\n=== TCP Protocol Client ===");
try
{
using (TcpClient client = new TcpClient())
{
Console.WriteLine($"Connecting to protocol server {serverIp}:{port}...");
await client.ConnectAsync(serverIp, port);
Console.WriteLine("Connected to protocol server!");
using (NetworkStream stream = client.GetStream())
{
// Test different message types
string[] testMessages = { "Hello World", "This will be uppercased", "Reverse this string" };
byte[] messageTypes = { 1, 2, 3 };
for (int i = 0; i < testMessages.Length; i++)
{
Console.WriteLine($"Sending message type {messageTypes[i]}: {testMessages[i]}");
await SendProtocolMessage(stream, messageTypes[i], testMessages[i]);
// Receive response
byte[] responseTypeBuffer = new byte[1];
await stream.ReadAsync(responseTypeBuffer, 0, 1);
byte[] responseLengthBuffer = new byte[4];
await stream.ReadAsync(responseLengthBuffer, 0, 4);
int responseLength = BitConverter.ToInt32(responseLengthBuffer, 0);
byte[] responseBuffer = new byte[responseLength];
await stream.ReadAsync(responseBuffer, 0, responseLength);
string response = Encoding.UTF8.GetString(responseBuffer);
Console.WriteLine($"Received response: {response}\n");
await Task.Delay(1000);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Protocol client error: {ex.Message}");
}
}
// 10. TCP Keep-alive and Heartbeat
public static async Task HeartbeatTcpServer()
{
Console.WriteLine("\n=== TCP Heartbeat Server ===");
int port = 8085;
TcpListener server = null;
try
{
server = new TcpListener(IPAddress.Any, port);
server.Start();
Console.WriteLine($"Heartbeat server started on port {port}");
while (true)
{
TcpClient client = await server.AcceptTcpClientAsync();
Console.WriteLine($"Heartbeat client connected from {client.Client.RemoteEndPoint}");
_ = Task.Run(() => HandleHeartbeatClient(client));
}
}
catch (Exception ex)
{
Console.WriteLine($"Heartbeat server error: {ex.Message}");
}
finally
{
server?.Stop();
}
}
static async Task HandleHeartbeatClient(TcpClient client)
{
DateTime lastHeartbeat = DateTime.Now;
int missedHeartbeats = 0;
const int maxMissedHeartbeats = 3;
try
{
using (client)
using (NetworkStream stream = client.GetStream())
{
// Send initial heartbeat request
await SendHeartbeat(stream);
while (true)
{
// Wait for heartbeat response (5 second timeout)
byte[] buffer = new byte[1024];
var readTask = stream.ReadAsync(buffer, 0, buffer.Length);
var timeoutTask = Task.Delay(5000);
var completedTask = await Task.WhenAny(readTask, timeoutTask);
if (completedTask == timeoutTask)
{
missedHeartbeats++;
Console.WriteLine($"Missed heartbeat {missedHeartbeats}/{maxMissedHeartbeats}");
if (missedHeartbeats >= maxMissedHeartbeats)
{
Console.WriteLine("Client disconnected - too many missed heartbeats");
break;
}
await SendHeartbeat(stream);
continue;
}
int bytesRead = await readTask;
if (bytesRead == 0) break;
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead).Trim();
if (message == "HEARTBEAT")
{
lastHeartbeat = DateTime.Now;
missedHeartbeats = 0;
Console.WriteLine($"Received heartbeat from client");
await SendHeartbeatAck(stream);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Heartbeat client error: {ex.Message}");
}
}
static async Task SendHeartbeat(NetworkStream stream)
{
string message = "HEARTBEAT\n";
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
await stream.WriteAsync(messageBytes, 0, messageBytes.Length);
}
static async Task SendHeartbeatAck(NetworkStream stream)
{
string message = "HEARTBEAT_ACK\n";
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
await stream.WriteAsync(messageBytes, 0, messageBytes.Length);
}
// 11. TCP Heartbeat Client
public static async Task HeartbeatTcpClient(string serverIp = "127.0.0.1", int port = 8085)
{
Console.WriteLine("\n=== TCP Heartbeat Client ===");
try
{
using (TcpClient client = new TcpClient())
{
Console.WriteLine($"Connecting to heartbeat server {serverIp}:{port}...");
await client.ConnectAsync(serverIp, port);
Console.WriteLine("Connected to heartbeat server!");
using (NetworkStream stream = client.GetStream())
{
// Handle server messages
_ = Task.Run(async () =>
{
byte[] buffer = new byte[1024];
while (true)
{
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0) break;
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead).Trim();
if (message == "HEARTBEAT")
{
Console.WriteLine("Received heartbeat request");
string response = "HEARTBEAT\n";
byte[] responseBytes = Encoding.UTF8.GetBytes(response);
await stream.WriteAsync(responseBytes, 0, responseBytes.Length);
Console.WriteLine("Sent heartbeat response");
}
else if (message == "HEARTBEAT_ACK")
{
Console.WriteLine("Received heartbeat acknowledgment");
}
}
});
// Keep client alive
Console.WriteLine("Heartbeat client running. Press Enter to stop...");
Console.ReadLine();
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Heartbeat client error: {ex.Message}");
}
}
static async Task Main(string[] args)
{
Console.WriteLine("=== C# TCP Socket Demo ===\n");
try
{
Console.WriteLine("Choose which demo to run:");
Console.WriteLine("1. Simple TCP Server");
Console.WriteLine("2. Simple TCP Client");
Console.WriteLine("3. File Transfer");
Console.WriteLine("4. Chat Server");
Console.WriteLine("5. Protocol Server");
// Note: In real scenario, you would choose one demo at a time
Console.WriteLine("\nNote: Each demo runs continuously. Start appropriate client/server pairs.");
// Example: Run file transfer
Console.WriteLine("\nStarting File Transfer Server on port 8082...");
_ = Task.Run(() => FileTransferServer());
// Wait a bit then start client with test file
await Task.Delay(2000);
// Create a test file
string testFile = "test_transfer.txt";
await System.IO.File.WriteAllTextAsync(testFile, "This is a test file for TCP transfer\nLine 2\nLine 3");
Console.WriteLine($"Starting file transfer client for {testFile}...");
await FileTransferClient(testFile);
// Cleanup
if (System.IO.File.Exists(testFile))
{
System.IO.File.Delete(testFile);
}
if (System.IO.File.Exists("received_test_transfer.txt"))
{
System.IO.File.Delete("received_test_transfer.txt");
}
Console.WriteLine("\nTCP socket demos completed!");
}
catch (Exception ex)
{
Console.WriteLine($"Error in TCP demo: {ex.Message}");
}
}
}
💻 UDP套接字编程 csharp
🟡 intermediate
⭐⭐⭐
UDP客户端和服务器实现,用于无连接通信、广播和多播
⏱️ 28 min
🏷️ csharp, udp, socket, networking, broadcast, multicast, windows
Prerequisites:
C# async/await, Network programming basics, UDP understanding
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
class UdpSocketDemo
{
// 1. Simple UDP Server
public static async Task SimpleUdpServer()
{
Console.WriteLine("=== Simple UDP Server ===");
int port = 9090;
UdpClient udpServer = null;
try
{
udpServer = new UdpClient(port);
Console.WriteLine($"UDP Server started on port {port}");
Console.WriteLine("Waiting for UDP messages...");
while (true)
{
var result = await udpServer.ReceiveAsync();
string receivedMessage = Encoding.UTF8.GetString(result.Buffer);
IPEndPoint clientEndPoint = result.RemoteEndPoint;
Console.WriteLine($"Received from {clientEndPoint}: {receivedMessage}");
// Echo back response
string response = $"Server received: {receivedMessage}";
byte[] responseBytes = Encoding.UTF8.GetBytes(response);
await udpServer.SendAsync(responseBytes, responseBytes.Length, clientEndPoint);
}
}
catch (Exception ex)
{
Console.WriteLine($"UDP Server error: {ex.Message}");
}
finally
{
udpServer?.Close();
}
}
// 2. Simple UDP Client
public static async Task SimpleUdpClient(string serverIp = "127.0.0.1", int port = 9090)
{
Console.WriteLine("\n=== Simple UDP Client ===");
UdpClient udpClient = null;
try
{
udpClient = new UdpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(serverIp), port);
string[] messages = {
"Hello, UDP Server!",
"This is message 2",
"Final message from UDP client"
};
foreach (string message in messages)
{
Console.WriteLine($"Sending: {message}");
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
await udpClient.SendAsync(messageBytes, messageBytes.Length, serverEndPoint);
// Receive response
var response = await udpClient.ReceiveAsync();
string responseMessage = Encoding.UTF8.GetString(response.Buffer);
Console.WriteLine($"Received from server: {responseMessage}");
await Task.Delay(1000);
}
}
catch (Exception ex)
{
Console.WriteLine($"UDP Client error: {ex.Message}");
}
finally
{
udpClient?.Close();
}
}
// 3. UDP Broadcast Server
public static async Task UdpBroadcastServer()
{
Console.WriteLine("\n=== UDP Broadcast Server ===");
int port = 9091;
UdpClient udpServer = null;
try
{
udpServer = new UdpClient();
udpServer.EnableBroadcast = true;
udpServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpServer.Client.Bind(new IPEndPoint(IPAddress.Any, port));
Console.WriteLine($"UDP Broadcast Server started on port {port}");
Console.WriteLine("Waiting for broadcast messages...");
while (true)
{
var result = await udpServer.ReceiveAsync();
string receivedMessage = Encoding.UTF8.GetString(result.Buffer);
IPEndPoint clientEndPoint = result.RemoteEndPoint;
Console.WriteLine($"Broadcast received from {clientEndPoint}: {receivedMessage}");
// Respond to the sender
string response = $"Server received broadcast: {receivedMessage}";
byte[] responseBytes = Encoding.UTF8.GetBytes(response);
await udpServer.SendAsync(responseBytes, responseBytes.Length, clientEndPoint);
}
}
catch (Exception ex)
{
Console.WriteLine($"Broadcast Server error: {ex.Message}");
}
finally
{
udpServer?.Close();
}
}
// 4. UDP Broadcast Client
public static async Task UdpBroadcastClient(int port = 9091)
{
Console.WriteLine("\n=== UDP Broadcast Client ===");
UdpClient udpClient = null;
try
{
udpClient = new UdpClient();
udpClient.EnableBroadcast = true;
// Get broadcast address (typically last address in subnet)
IPAddress broadcastAddress = IPAddress.Broadcast;
IPEndPoint broadcastEndPoint = new IPEndPoint(broadcastAddress, port);
Console.WriteLine($"Sending broadcasts to {broadcastAddress}:{port}");
string[] messages = {
"Broadcast Message 1",
"Broadcast Message 2",
"Anyone out there?"
};
foreach (string message in messages)
{
Console.WriteLine($"Broadcasting: {message}");
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
await udpClient.SendAsync(messageBytes, messageBytes.Length, broadcastEndPoint);
// Wait for responses
var receiveTask = udpClient.ReceiveAsync();
var timeoutTask = Task.Delay(3000);
var completedTask = await Task.WhenAny(receiveTask, timeoutTask);
if (completedTask == receiveTask)
{
var response = await receiveTask;
string responseMessage = Encoding.UTF8.GetString(response.Buffer);
Console.WriteLine($"Response from {response.RemoteEndPoint}: {responseMessage}");
}
else
{
Console.WriteLine("No response received within timeout");
}
await Task.Delay(1000);
}
}
catch (Exception ex)
{
Console.WriteLine($"Broadcast Client error: {ex.Message}");
}
finally
{
udpClient?.Close();
}
}
// 5. UDP Multicast Server
public static async Task UdpMulticastServer()
{
Console.WriteLine("\n=== UDP Multicast Server ===");
string multicastAddress = "239.0.0.1";
int port = 9092;
UdpClient udpClient = null;
try
{
// Create and bind UDP client
udpClient = new UdpClient();
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, port));
// Join multicast group
udpClient.JoinMulticastGroup(IPAddress.Parse(multicastAddress));
Console.WriteLine($"UDP Multicast Server joined group {multicastAddress}:{port}");
while (true)
{
var result = await udpClient.ReceiveAsync();
string receivedMessage = Encoding.UTF8.GetString(result.Buffer);
IPEndPoint senderEndPoint = result.RemoteEndPoint;
Console.WriteLine($"Multicast message from {senderEndPoint}: {receivedMessage}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Multicast Server error: {ex.Message}");
}
finally
{
udpClient?.DropMulticastGroup(IPAddress.Parse(multicastAddress));
udpClient?.Close();
}
}
// 6. UDP Multicast Client
public static async Task UdpMulticastClient()
{
Console.WriteLine("\n=== UDP Multicast Client ===");
string multicastAddress = "239.0.0.1";
int port = 9092;
UdpClient udpClient = null;
try
{
udpClient = new UdpClient();
IPEndPoint multicastEndPoint = new IPEndPoint(IPAddress.Parse(multicastAddress), port);
string[] messages = {
"Multicast Message 1",
"Hello multicast group!",
"Final multicast message"
};
foreach (string message in messages)
{
Console.WriteLine($"Sending multicast: {message}");
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
await udpClient.SendAsync(messageBytes, messageBytes.Length, multicastEndPoint);
await Task.Delay(2000);
}
}
catch (Exception ex)
{
Console.WriteLine($"Multicast Client error: {ex.Message}");
}
finally
{
udpClient?.Close();
}
}
// 7. UDP File Transfer (with acknowledgment)
public static async Task UdpFileServer()
{
Console.WriteLine("\n=== UDP File Server ===");
int port = 9093;
UdpClient udpClient = null;
try
{
udpClient = new UdpClient(port);
Console.WriteLine($"UDP File Server listening on port {port}");
while (true)
{
var result = await udpClient.ReceiveAsync();
ProcessFileTransferRequest(udpClient, result.Buffer, result.RemoteEndPoint);
}
}
catch (Exception ex)
{
Console.WriteLine($"UDP File Server error: {ex.Message}");
}
finally
{
udpClient?.Close();
}
}
static async Task ProcessFileTransferRequest(UdpClient udpClient, byte[] data, IPEndPoint clientEndPoint)
{
try
{
string request = Encoding.UTF8.GetString(data);
string[] parts = request.Split(':');
if (parts.Length == 2 && parts[0] == "REQUEST_FILE")
{
string fileName = parts[1];
Console.WriteLine($"File request received: {fileName}");
if (System.IO.File.Exists(fileName))
{
byte[] fileData = await System.IO.File.ReadAllBytesAsync(fileName);
const int chunkSize = 1024; // Small chunks for UDP
Console.WriteLine($"Sending file {fileName} ({fileData.Length} bytes) in chunks of {chunkSize}");
for (int i = 0; i < fileData.Length; i += chunkSize)
{
int chunkLength = Math.Min(chunkSize, fileData.Length - i);
byte[] chunk = new byte[chunkLength + 8]; // 8 bytes for sequence number
// Add sequence number
BitConverter.GetBytes(i).CopyTo(chunk, 0);
// Add data
Array.Copy(fileData, i, chunk, 8, chunkLength);
await udpClient.SendAsync(chunk, chunk.Length, clientEndPoint);
// Wait for acknowledgment
var ackResult = await udpClient.ReceiveAsync();
string ack = Encoding.UTF8.GetString(ackResult.Buffer);
if (ack != $"ACK:{i}")
{
Console.WriteLine($"Missing ACK for chunk at position {i}, resending...");
await udpClient.SendAsync(chunk, chunk.Length, clientEndPoint);
}
Console.Write($"\rProgress: {Math.Min(100, (i + chunkLength) * 100 / fileData.Length)}%");
await Task.Delay(10); // Small delay
}
// Send end marker
byte[] endMarker = Encoding.UTF8.GetBytes("END:FILE");
await udpClient.SendAsync(endMarker, endMarker.Length, clientEndPoint);
Console.WriteLine("\nFile transfer completed");
}
else
{
string error = "ERROR:File not found";
byte[] errorBytes = Encoding.UTF8.GetBytes(error);
await udpClient.SendAsync(errorBytes, errorBytes.Length, clientEndPoint);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error processing file transfer: {ex.Message}");
}
}
// 8. UDP File Client
public static async Task UdpFileClient(string fileName, string serverIp = "127.0.0.1", int port = 9093)
{
Console.WriteLine("\n=== UDP File Client ===");
UdpClient udpClient = null;
try
{
udpClient = new UdpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(serverIp), port);
// Request file
string request = $"REQUEST_FILE:{fileName}";
byte[] requestBytes = Encoding.UTF8.GetBytes(request);
await udpClient.SendAsync(requestBytes, requestBytes.Length, serverEndPoint);
Console.WriteLine($"Requested file: {fileName}");
// Receive file data
var fileData = new System.Collections.Generic.List<byte>();
var receivedChunks = new System.Collections.Generic.SortedDictionary<int, byte[]>();
while (true)
{
var result = await udpClient.ReceiveAsync();
byte[] data = result.Buffer;
if (data.Length >= 8)
{
string header = Encoding.UTF8.GetString(data, 0, 4);
if (header == "END:")
{
Console.WriteLine("\nFile transfer completed");
break;
}
else if (header.StartsWith("ERROR:"))
{
Console.WriteLine($"\nServer error: {Encoding.UTF8.GetString(data)}");
return;
}
else
{
// File data chunk
int sequenceNumber = BitConverter.ToInt32(data, 0);
byte[] chunkData = new byte[data.Length - 8];
Array.Copy(data, 8, chunkData, 0, chunkData.Length);
receivedChunks[sequenceNumber] = chunkData;
// Send acknowledgment
string ack = $"ACK:{sequenceNumber}";
byte[] ackBytes = Encoding.UTF8.GetBytes(ack);
await udpClient.SendAsync(ackBytes, ackBytes.Length, serverEndPoint);
Console.Write($"\rReceived {receivedChunks.Count} chunks");
}
}
}
// Assemble file
using (var fileStream = System.IO.File.Create($"received_{fileName}"))
{
foreach (var chunk in receivedChunks.Values)
{
await fileStream.WriteAsync(chunk, 0, chunk.Length);
}
}
Console.WriteLine($$"\nFile saved as: received_{fileName}");
}
catch (Exception ex)
{
Console.WriteLine($"UDP File Client error: {ex.Message}");
}
finally
{
udpClient?.Close();
}
}
// 9. UDP Chat Server (connectionless chat)
public static async Task UdpChatServer()
{
Console.WriteLine("\n=== UDP Chat Server ===");
int port = 9094;
UdpClient udpServer = null;
var clients = new System.Collections.Generic.Dictionary<string, IPEndPoint>();
try
{
udpServer = new UdpClient(port);
Console.WriteLine($"UDP Chat Server started on port {port}");
while (true)
{
var result = await udpServer.ReceiveAsync();
string message = Encoding.UTF8.GetString(result.Buffer);
IPEndPoint senderEndPoint = result.RemoteEndPoint;
// Handle different message types
if (message.StartsWith("JOIN:"))
{
string username = message.Substring(5);
string clientKey = $"{senderEndPoint.Address}:{senderEndPoint.Port}";
clients[clientKey] = senderEndPoint;
Console.WriteLine($"{username} joined the chat");
// Notify all clients
string joinMessage = $"SYSTEM:{username} joined the chat";
await BroadcastToAllClients(udpServer, joinMessage, clients, null);
}
else if (message.StartsWith("LEAVE:"))
{
string username = message.Substring(6);
string clientKey = $"{senderEndPoint.Address}:{senderEndPoint.Port}";
clients.Remove(clientKey);
Console.WriteLine($"{username} left the chat");
string leaveMessage = $"SYSTEM:{username} left the chat";
await BroadcastToAllClients(udpServer, leaveMessage, clients, null);
}
else if (message.StartsWith("CHAT:"))
{
string chatMessage = message.Substring(5);
string clientKey = $"{senderEndPoint.Address}:{senderEndPoint.Port}";
if (clients.ContainsKey(clientKey))
{
Console.WriteLine($"Chat message: {chatMessage}");
await BroadcastToAllClients(udpServer, $"MSG:{chatMessage}", clients, senderEndPoint);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine($"UDP Chat Server error: {ex.Message}");
}
finally
{
udpServer?.Close();
}
}
static async Task BroadcastToAllClients(UdpClient udpClient, string message,
System.Collections.Generic.Dictionary<string, IPEndPoint> clients, IPEndPoint exclude)
{
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
foreach (var client in clients.Values)
{
if (exclude == null || !client.Equals(exclude))
{
try
{
await udpClient.SendAsync(messageBytes, messageBytes.Length, client);
}
catch
{
// Client might be disconnected
}
}
}
}
// 10. UDP Chat Client
public static async Task UdpChatClient(string username, string serverIp = "127.0.0.1", int port = 9094)
{
Console.WriteLine("\n=== UDP Chat Client ===");
UdpClient udpClient = null;
try
{
udpClient = new UdpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(serverIp), port);
// Join chat
string joinMessage = $"JOIN:{username}";
byte[] joinBytes = Encoding.UTF8.GetBytes(joinMessage);
await udpClient.SendAsync(joinBytes, joinBytes.Length, serverEndPoint);
// Start receiving messages
_ = Task.Run(async () =>
{
while (true)
{
var result = await udpClient.ReceiveAsync();
string message = Encoding.UTF8.GetString(result.Buffer);
if (message.StartsWith("SYSTEM:"))
{
Console.WriteLine($"\n{message.Substring(7)}");
}
else if (message.StartsWith("MSG:"))
{
Console.WriteLine($"\n{message.Substring(4)}");
}
}
});
// Send messages
Console.WriteLine("Type messages (type 'quit' to exit):");
while (true)
{
string input = Console.ReadLine();
if (string.IsNullOrEmpty(input)) continue;
if (input.ToLower() == "quit")
{
string leaveMessage = $"LEAVE:{username}";
byte[] leaveBytes = Encoding.UTF8.GetBytes(leaveMessage);
await udpClient.SendAsync(leaveBytes, leaveBytes.Length, serverEndPoint);
break;
}
string chatMessage = $"CHAT:{input}";
byte[] messageBytes = Encoding.UTF8.GetBytes(chatMessage);
await udpClient.SendAsync(messageBytes, messageBytes.Length, serverEndPoint);
}
}
catch (Exception ex)
{
Console.WriteLine($"UDP Chat Client error: {ex.Message}");
}
finally
{
udpClient?.Close();
}
}
// 11. UDP Discovery Service
public static async Task UdpDiscoveryService()
{
Console.WriteLine("\n=== UDP Discovery Service ===");
int port = 9095;
UdpClient discoveryServer = null;
try
{
discoveryServer = new UdpClient();
discoveryServer.EnableBroadcast = true;
discoveryServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
discoveryServer.Client.Bind(new IPEndPoint(IPAddress.Any, port));
Console.WriteLine($"UDP Discovery Service listening on port {port}");
while (true)
{
var result = await discoveryServer.ReceiveAsync();
string message = Encoding.UTF8.GetString(result.Buffer);
IPEndPoint clientEndPoint = result.RemoteEndPoint;
if (message == "DISCOVER")
{
Console.WriteLine($"Discovery request from {clientEndPoint}");
// Respond with service information
string response = $"SERVICE:MyApp:127.0.0.1:8080:{DateTime.Now:O}";
byte[] responseBytes = Encoding.UTF8.GetBytes(response);
await discoveryServer.SendAsync(responseBytes, responseBytes.Length, clientEndPoint);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Discovery Service error: {ex.Message}");
}
finally
{
discoveryServer?.Close();
}
}
// 12. UDP Discovery Client
public static async Task UdpDiscoveryClient(int port = 9095)
{
Console.WriteLine("\n=== UDP Discovery Client ===");
UdpClient udpClient = null;
try
{
udpClient = new UdpClient();
udpClient.EnableBroadcast = true;
// Send discovery broadcast
string discoveryMessage = "DISCOVER";
byte[] discoveryBytes = Encoding.UTF8.GetBytes(discoveryMessage);
IPAddress broadcastAddress = IPAddress.Broadcast;
IPEndPoint broadcastEndPoint = new IPEndPoint(broadcastAddress, port);
Console.WriteLine("Sending discovery broadcast...");
await udpClient.SendAsync(discoveryBytes, discoveryBytes.Length, broadcastEndPoint);
// Collect responses
var responses = new System.Collections.Generic.List<string>();
var endTime = DateTime.Now.AddSeconds(5);
while (DateTime.Now < endTime)
{
var receiveTask = udpClient.ReceiveAsync();
var timeoutTask = Task.Delay(500);
var completedTask = await Task.WhenAny(receiveTask, timeoutTask);
if (completedTask == receiveTask)
{
var response = await receiveTask;
string responseMessage = Encoding.UTF8.GetString(response.Buffer);
responses.Add($"From {response.RemoteEndPoint}: {responseMessage}");
}
}
Console.WriteLine($"\nFound {responses.Count} services:");
foreach (string response in responses)
{
Console.WriteLine(response);
}
}
catch (Exception ex)
{
Console.WriteLine($"Discovery Client error: {ex.Message}");
}
finally
{
udpClient?.Close();
}
}
static async Task Main(string[] args)
{
Console.WriteLine("=== C# UDP Socket Demo ===\n");
try
{
Console.WriteLine("Choose which demo to run:");
Console.WriteLine("1. Simple UDP Server/Client");
Console.WriteLine("2. Broadcast");
Console.WriteLine("3. Multicast");
Console.WriteLine("4. File Transfer");
Console.WriteLine("5. Chat");
Console.WriteLine("6. Discovery");
// Run a simple demo
Console.WriteLine("\nStarting simple UDP server on port 9090...");
_ = Task.Run(() => SimpleUdpServer());
await Task.Delay(1000);
Console.WriteLine("Starting UDP client to send messages...");
await SimpleUdpClient();
Console.WriteLine("\nUDP socket demos completed!");
}
catch (Exception ex)
{
Console.WriteLine($"Error in UDP demo: {ex.Message}");
}
}
}