C#实现Web服务连接测试(Ping、下载、上传)需求咨询
Hey Sebastian, let's work through this problem together—you're right that NetworkInterface isn't the right tool here because it's meant for managing local network hardware, not testing remote web services. Here's a straightforward, actionable plan to build your monitoring service:
核心思路
Instead of targeting network interfaces, we'll:
- Use scheduled tasks to run checks every minute
- Validate web service connectivity via HTTP requests
- Measure "ping" (TCP-based, no admin rights needed) or ICMP ping
- Test download/upload speeds by sending/receiving known-size data
- Store all metrics in your database for later analysis
Step 1: Set Up Scheduled Tasks
You'll need a way to trigger your monitoring logic every 60 seconds. Here are options for common languages:
- Python: Use
APScheduler(lightweight, easy to configure) - Java/Spring Boot: Use
@Scheduledannotations - C#: Use
HangfireorSystem.Timers.Timer - Bash: Use
cronjobs (for simple shell-script-based checks)
Step 2: Check Web Service Connectivity
First, add a dedicated health check endpoint to your web service (e.g., /health) that returns a 200 OK response when the service is up. This lets you quickly verify if the service is accepting connections.
For example, in Python with Flask:
@app.route('/health') def health_check(): return "OK", 200
In your monitoring service, send a GET request to this endpoint and check the status code. If it times out or returns a non-200 code, mark the service as unavailable.
Step 3: Measure Ping (TCP or ICMP)
TCP Ping (Recommended)
ICMP ping often requires admin privileges, so TCP ping is more practical for web services. It works by timing how long it takes to establish a connection to your web service's port (80/443):
import time import requests def tcp_ping(url, timeout=5): try: start = time.time() requests.head(url, timeout=timeout) return round((time.time() - start) * 1000, 2) # Convert to ms except Exception as e: return None # Or raise an error
ICMP Ping (If You Have Permissions)
If you can run the monitoring service with admin rights, you can use ICMP ping for a more traditional network-level check:
import ping3 def icmp_ping(host): try: return round(ping3.ping(host), 2) # Returns ms except Exception as e: return None
Step 4: Test Download & Upload Speeds
Download Speed
Request a fixed-size test file from your web service (e.g., a 5MB or 10MB static file) and calculate the speed based on transfer time:
def test_download_speed(url, timeout=10): try: start = time.time() response = requests.get(url, timeout=timeout) response.raise_for_status() file_size_bytes = len(response.content) elapsed_time = time.time() - start # Convert to kbps (kilobits per second) return round((file_size_bytes * 8) / (elapsed_time * 1024), 2) except Exception as e: return None
Upload Speed
Send a fixed-size payload to a dedicated upload test endpoint on your web service (this endpoint should just acknowledge receipt, no need to store the data):
def test_upload_speed(url, payload_size_mb=5, timeout=10): try: payload = b'X' * (payload_size_mb * 1024 * 1024) # 5MB of dummy data start = time.time() response = requests.post(url, data=payload, timeout=timeout) response.raise_for_status() elapsed_time = time.time() - start # Convert to kbps return round((len(payload) * 8) / (elapsed_time * 1024), 2) except Exception as e: return None
Step 5: Store Metrics in Database
Create a table to store your monitoring logs (adjust schema to match your database):
CREATE TABLE service_monitor_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, status VARCHAR(20) NOT NULL, -- 'success' or 'failed' ping_ms REAL, download_speed_kbps REAL, upload_speed_kbps REAL, error_message TEXT );
In your monitoring code, after collecting metrics, insert them into this table. Here's a Python example with SQLite (replace with your database driver):
import sqlite3 def save_to_db(metrics): conn = sqlite3.connect('monitor.db') cursor = conn.cursor() cursor.execute(''' INSERT INTO service_monitor_logs (status, ping_ms, download_speed_kbps, upload_speed_kbps, error_message) VALUES (?, ?, ?, ?, ?) ''', ( metrics['status'], metrics['ping_ms'], metrics['download_speed_kbps'], metrics['upload_speed_kbps'], metrics['error_message'] )) conn.commit() conn.close()
Full Example (Python)
Here's a complete, runnable example that ties everything together:
import time import requests import ping3 from apscheduler.schedulers.background import BackgroundScheduler import sqlite3 # Configuration WEB_SERVICE_BASE = "http://your-web-service-url" HEALTH_ENDPOINT = f"{WEB_SERVICE_BASE}/health" DOWNLOAD_TEST_FILE = f"{WEB_SERVICE_BASE}/test-5mb.bin" UPLOAD_TEST_ENDPOINT = f"{WEB_SERVICE_BASE}/upload-test" def init_db(): conn = sqlite3.connect('monitor.db') cursor = conn.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS service_monitor_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, status VARCHAR(20) NOT NULL, ping_ms REAL, download_speed_kbps REAL, upload_speed_kbps REAL, error_message TEXT ) ''') conn.commit() conn.close() def run_monitoring_check(): metrics = { "status": "success", "ping_ms": None, "download_speed_kbps": None, "upload_speed_kbps": None, "error_message": None } # 1. TCP Ping try: metrics["ping_ms"] = tcp_ping(WEB_SERVICE_BASE) if metrics["ping_ms"] is None: raise Exception("TCP ping failed") except Exception as e: metrics["status"] = "failed" metrics["error_message"] = f"Ping error: {str(e)}" save_to_db(metrics) return # 2. Health Check try: response = requests.get(HEALTH_ENDPOINT, timeout=5) if response.status_code != 200: raise Exception(f"Health check returned {response.status_code}") except Exception as e: metrics["status"] = "failed" metrics["error_message"] = f"Health check error: {str(e)}" save_to_db(metrics) return # 3. Download Speed Test try: metrics["download_speed_kbps"] = test_download_speed(DOWNLOAD_TEST_FILE) except Exception as e: metrics["status"] = "failed" metrics["error_message"] = f"Download test error: {str(e)}" # 4. Upload Speed Test try: metrics["upload_speed_kbps"] = test_upload_speed(UPLOAD_TEST_ENDPOINT) except Exception as e: metrics["status"] = "failed" metrics["error_message"] = f"Upload test error: {str(e)}" # Save results save_to_db(metrics) print(f"Logged metrics: {metrics}") # Helper functions (from earlier steps) def tcp_ping(url, timeout=5): try: start = time.time() requests.head(url, timeout=timeout) return round((time.time() - start) * 1000, 2) except: return None def test_download_speed(url, timeout=10): try: start = time.time() response = requests.get(url, timeout=timeout) response.raise_for_status() size = len(response.content) elapsed = time.time() - start return round((size * 8) / (elapsed * 1024), 2) except: return None def test_upload_speed(url, payload_size_mb=5, timeout=10): try: payload = b'X' * (payload_size_mb * 1024 * 1024) start = time.time() response = requests.post(url, data=payload, timeout=timeout) response.raise_for_status() elapsed = time.time() - start return round((len(payload) * 8) / (elapsed * 1024), 2) except: return None def save_to_db(metrics): conn = sqlite3.connect('monitor.db') cursor = conn.cursor() cursor.execute(''' INSERT INTO service_monitor_logs (status, ping_ms, download_speed_kbps, upload_speed_kbps, error_message) VALUES (?, ?, ?, ?, ?) ''', ( metrics['status'], metrics['ping_ms'], metrics['download_speed_kbps'], metrics['upload_speed_kbps'], metrics['error_message'] )) conn.commit() conn.close() if __name__ == "__main__": init_db() scheduler = BackgroundScheduler() scheduler.add_job(run_monitoring_check, 'interval', minutes=1) scheduler.start() print("Monitoring service started. Press Ctrl+C to stop.") try: while True: time.sleep(1) except KeyboardInterrupt: scheduler.shutdown() print("Monitoring service stopped.")
Key Notes
- Permissions: TCP ping works without admin rights; ICMP ping requires elevated privileges.
- Endpoint Design: Use dedicated test endpoints to avoid impacting your web service's normal traffic.
- Timeout Handling: Always add timeouts to your requests to prevent the monitoring task from hanging.
- Resource Usage: Keep test file/payload sizes reasonable (1-10MB) to avoid consuming excessive bandwidth.
- Deployment: Run the monitoring service as a background process (e.g., systemd service on Linux, Windows Service, or Docker container).
内容的提问来源于stack exchange,提问作者Sebastian




