Heim > Web-Frontend > js-Tutorial > Hauptteil

WebRTC WHIP & WHEP Tutorial: Erstellen Sie eine Live-Streaming-App

Susan Sarandon
Freigeben: 2024-11-01 09:38:30
Original
139 Leute haben es durchsucht

Dieser Artikel wurde ursprünglich im Metered-Blog veröffentlicht: WebRTC WHIP & WHEP Tutorial: Erstellen Sie eine Live-Streaming-App

WHIP (WebRTC-HTTP Ingestion Protocol) und WHEP (WebRTC-HTTP Egress Protocol) sind Protokolle, die darauf ausgelegt sind, die Signalisierung in WebRTC mithilfe von Standard-HTTP-Methoden zu optimieren

  • Definition von WHIP: WHIP vereinfacht die Art und Weise, wie Clientgeräte Medienströme an den Server senden.

    • Es ersetzt den komplexen Signalisierungsmechanismus, der bei einfachen HTTP-GET-Anfragen erforderlich ist, und erleichtert so die Aufnahme von Medien in Server
  • Definition von WHEP: Das WHEP-Protokoll wird für die Bereitstellung von Medienströmen von Servern an Clients verwendet. Es verwendet das HTTP-Protokoll, um die Signalisierung für den Medienkonsum zu verarbeiten, sodass Client-Geräte Medienströme ohne komplexe Einstellungen empfangen können

Rollen bei der Vereinfachung der WebRTC-Signalisierung

  • Einfache Implementierung: WHEP und WHIP verwenden HTTP-Protokolle, sodass diese Protokolle die damit verbundene Komplexität reduzieren

  • Zustandslose Kommunikation: Da HTTP ein zustandsloses Protokoll ist, muss der Server keine laufenden Sitzungsinformationen zwischen Anfragen verwalten.

  • Verbesserte Kompatibilität: Da HTTP universell kompatibel ist, ist die Verwendung von HTTP für die Signalisierung die beste Lösung für die Kompatibilität zwischen Plattformen und Geräten

  • Schnelle Entwicklung: Entwickler können WebRTC-Apps effizienter implementieren, da sie keine komplizierten Details traditioneller Signalisierungsmethoden berücksichtigen müssen

WebRTC WHIP & WHEP Tutorial: Build a live Streaming App

Wie funktioniert WHIP

Wie geht WHIP mit der Medienstream-Aufnahme um?

Das WHIP-Protokoll hat die Art und Weise revolutioniert, wie Medienströme von Client-Geräten an die Server gesendet werden können, indem HTTP-Methoden zur Signalisierung verwendet werden

Traditionell müssen Sie zum Einrichten von WebRTC einen komplexen Signalmechanismus mithilfe von Web-Sockets oder anderen Protokollen einrichten. Mit WHIP wird dieser Vorgang einfacher, da das HTTP-Protokoll zum Signalisieren und Starten einer WebRTC-Sitzung verwendet wird

  • HTTP-POST-Anfrage: Hier sendet das Clientgerät eine HTTP-POST-Anfrage mit dem SDP- oder Sitzungsbeschreibungsprotokollangebot im Textkörper an den WHIP-Endpunkt

  • Serverantwort: Der Medienserver verarbeitet dann das SDP-Angebot und antwortet mit dem Statuscode 200, einschließlich der SDP-Antwort im Anfragetext

  • ICE-Kandidatenaustausch: Das WHIP-Protokoll unterstützt das ICE-Protokoll, indem es dem Client ermöglicht, zusätzliche HTTP-PATCH-Anfragen zu senden, wenn neue ICE-Kandidaten verfügbar werden 

  • Verbindungsaufbau: Sobald der SDP-Austausch abgeschlossen ist, wird eine Peer-to-Peer-Verbindung hergestellt, die es dem Client ermöglicht, die Medien zum Server zu streamen

Vorteile gegenüber herkömmlichen Einnahmemethoden

  • Einfachheit: Durch die Verwendung der WHIP-Methoden reduziert das WHIP den Bedarf an dauerhaften Verbindungen und Signalisierungsservern.

  • Einfache Implementierung: Entwickler können HTTP verwenden, das universell kompatibel ist, um den Entwicklungsprozess zu beschleunigen

  • Skalierbarkeit: Die zustandslosen HTTP-Anfragen ermöglichen es den Servern, mehrere Verbindungsanfragen gleichzeitig zu verarbeiten und so eine große Anzahl von Verbindungen problemlos zu verwalten.

  • Firewall- und Proxy-freundlich: HTTP ist Firewall-freundlich, fast alle Arten von Firewalls erlauben HTTP-Verkehr 

  • Kostengünstig: Die vereinfachte Signalisierung über HTTP reduziert die Kosten, die mit dem Hinzufügen eines Signalisierungsservers verbunden sind

WebRTC WHIP & WHEP Tutorial: Build a live Streaming App

Wie funktioniert WHEP?

Das WHEP-Protokoll vereinfacht den Prozess der Medienbereitstellung vom Server an die Clientgeräte. 

Das WHEP-Protokoll ermöglicht Ihnen daher die Verwendung von HTTP, um die Signalisierung für den Empfang von Medien vom Server und den Client-Geräten einzurichten.

Wie funktioniert WHEP beim Medien-Streaming?

  • HTTP-GET-Anfrage: Der Client fordert einen Medienstream an, indem er eine HTTP-GET-Anfrage an den WHEP-Endpunkt des Servers sendet

  • SDP-Austausch: Der Server antwortet mit dem SDP-Angebot in einer HTTP-Antwort, der Client sendet dann die SDP-Antwort in der nachfolgenden POST-Anfrage zurück

  • Medienempfang: Sobald die Verbindung hergestellt ist, wird der Medienstream über die eingerichtete WebRTC-Verbindung empfangen. HINWEIS: Oft benötigen Sie einen TURN-Server um eine WebRTC-Verbindung herzustellen

  • Unterstützung für ICE: WHEP ermöglicht den Austausch von ICE-Kandidaten über zusätzliche HTTP-Patch-Anfragen und ermöglicht so eine bessere Konnektivität 

Vorteile beim clientseitigen Streaming

  • Vereinfachte Client-Implementierung: Verwendung von HTTP-Anfragen, wodurch der Bedarf an komplexen Signalisierungsmechanismen reduziert wird 

  • Verbesserte Kompatibilität: Die universelle Unterstützung für das HTTP-Protokoll sorgt für eine verbesserte Kompatibilität zwischen Geräten 

  • Erweiterte Skalierbarkeit: Da HTTP ein zustandsloses Protokoll ist, verbessert dies die Skalierbarkeit der Server und Sie können mit kleinen Ressourcen auf eine sehr große Anzahl von Benutzern skalieren

  • Bessere Netzwerkdurchquerung: Da Sie die Signalisierung mit HTTP durchführen können und keine Web-Sockets oder andere Mechanismen benötigen, verbessert dies die NAT-Durchquerung für die Konnektivität. Sobald die Verbindung hergestellt ist, benötigen Sie einen TURN-Server für WebRTC

  • Reduzierte Latenz: Signalisierung über HTTP kann zu schnelleren Verbindungen führen und so das Benutzererlebnis verbessern.

WebRTC WHIP & WHEP Tutorial: Build a live Streaming App

Synergie zwischen WHIP und WHEP

Kombination beider Protokolle für eine effiziente End-to-End-Kommunikation:

Durch die Kombination von WHIP und WHEP können die Entwickler eine umfassende Signalisierungslösung für WebRTC erstellen

Die Kombination vereinfacht die Aufnahme und Bereitstellung von Medienströmen und sorgt so für eine reibungslosere Implementierung von WebRTC

  • Einheitlicher Signalisierungsansatz: Die Verwendung von HTTP sowohl für die Aufnahme als auch für die Zustellung schafft eine konsistente Signalisierungsmethodik

  • Reduzierte Komplexität: Entwickler müssen sich nur mit dem HTTP-Protokoll befassen, wodurch die Lernkurve und die Wartung des Codes reduziert werden

  • Verbesserte Leistung: Die Optimierung des Codes mit einem einzigen Protokoll für die Signalisierung führt zu schnelleren Verbindungszeiten und geringerer Latenz bei der Übertragung von Medien

Anwendungsfälle, die eine verbesserte Leistung zeigen

  • Live-Streaming-Plattformen: 

  • Interaktive Anwendungen

  • Skalierbare Architektur

Aufbau der Live-Streaming-App

Die Implementierung von WHIP und WHEP in Ihrer WebRTC-App ist ganz einfach. In diesem Abschnitt richten wir einen WHIP-Server ein und integrieren ihn mithilfe moderner Technologien wie Node und Docker

in Ihre Anwendung

Hier verwenden wir den TURN-Serverdienst von Metered.ca für die NAT-Durchquerung

Einrichten des WHIP-Servers

Voraussetzungen und Umgebungseinrichtung:

  • Node.js und NPM: Stellen Sie sicher, dass Sie den neuesten Node und NVM installiert haben

  • Metered.ca-Konto: Erstellen Sie ein kostenloses Konto auf Metered TURN-Servern

  • Öffentliche IP-Adresse: Dies ist erforderlich, damit der Server im Internet erreichbar ist. Wenn Sie für Ihre Anwendung einen Cloud-Anbieter nutzen, erhalten Sie damit eine kostenlose öffentliche IP-Adresse

  • WebRTC-Medienserver: Wir benötigen einen Medienserver wie GStreamer oder Janus, der WHIP-Unterstützung bietet

Erweiterte Schrittkonfiguration mit Node.Js und GStreamer

  1. Installieren Sie GStreamer mit WHIP-Unterstützung

  2. Richten Sie den WHIP-Server mit GStreamer ein

    1. Erstellen Sie eine GStreamer-Pipeline, die auf die WHIP-Verbindungen hört
gst-launch-1.0 whipserversrc name=whip \
  ! queue ! videoconvert ! autovideosink
Nach dem Login kopieren
Nach dem Login kopieren

Der obige Befehl startet einen WHIP-Server, der eingehende Medienströme akzeptiert und anzeigt 

  1. Konfigurieren Sie den Server für die Verwendung des Metered.ca TURN-Servers

    1. Ändern Sie die GStreamer-Pipeline, um den TURN-Server zu verwenden. Dies ist wichtig, da NAT-Router und Firewalls Verbindungen blockieren
gst-launch-1.0 whipserversrc name=whip ice-server="turn://YOUR_USERNAME:YOUR_CREDENTIAL@relay.metered.ca:80" \
  ! queue ! videoconvert ! autovideosink
Nach dem Login kopieren
Nach dem Login kopieren
  1. Einen Reverse Proxy mit Node.JS einrichten (optional):

    1. Wenn Sie HTTP-Endpunkte verwalten oder andere zusätzliche Logik hinzufügen möchten, können Sie einen einfachen Express-JS-Server einrichten
const express = require('express');
const httpProxy = require('http-proxy');
const app = express();
const proxy = httpProxy.createProxyServer();

app.post('/whip', (req, res) => {
  proxy.web(req, res, { target: 'http://localhost:PORT_WHERE_GSTREAMER_IS_RUNNING' });
});

app.listen(3000, () => {
  console.log('Proxy server running on port 3000');
});
Nach dem Login kopieren
Nach dem Login kopieren

Implementieren von WHIP in Ihrer Anwendung

Codeausschnitte für die Integration von WHIP:

Auf der Clientseite können Sie Medienströme mit Hilfe von RTCPeerConnection erfassen und HTTP-Anfragen verwenden, um die Signalisierung zu verarbeiten, die zum Herstellen einer Verbindung erforderlich ist.

  1. Medienstreams erfassen:

    1. Sie können Medienströme wie erfassen
const mediaStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
Nach dem Login kopieren
Nach dem Login kopieren
  1. Erstellen Sie eine RTCPeerConnection:

Sie können mithilfe von Metered TURN Servern eine RTCPeerConnection erstellen

var myPeerConnection = new RTCPeerConnection({
  iceServers: [
      {
        urls: "stun:stun.relay.metered.ca:80",
      },
      {
        urls: "turn:global.relay.metered.ca:80",
        username: "your-username",
        credential: "your-credential",
      },
      {
        urls: "turn:global.relay.metered.ca:80?transport=tcp",
        username: "your-username",
        credential: "your-credential",
      },
      {
        urls: "turn:global.relay.metered.ca:443",
        username: "your-username",
        credential: "your-credential",
      },
      {
        urls: "turns:global.relay.metered.ca:443?transport=tcp",
        username: "your-username",
        credential: "your-credential",
      },
  ],
});
Nach dem Login kopieren
Nach dem Login kopieren
  1. Medientitel zur Verbindung hinzufügen:
mediaStream.getTracks().forEach((track) => {
  pc.addTrack(track, mediaStream);
});
Nach dem Login kopieren
Nach dem Login kopieren
  1. SDP-Angebot erstellen und an WHIP-Server senden:
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

const response = await fetch('http://YOUR_SERVER_IP:3000/whip', {
  method: 'POST',
  headers: { 'Content-Type': 'application/sdp' },
  body: pc.localDescription.sdp,
});

const sdpAnswer = await response.text();
await pc.setRemoteDescription({ type: 'answer', sdp: sdpAnswer });
Nach dem Login kopieren
Nach dem Login kopieren

Verarbeitung von HTTP-Anfragen und -Antworten zur Signalisierung

  • Kundenseite:

    • HTTP-POST-Anfrage: 

      • URL: http://YOUR_SERVER_IP:3000/whip
      • Header: { 'Content-Type': 'application/sdp' }
      • Text: SDP-Angebot als Klartext
    • Antwort erwartet:

      • Status: 201 Erstellt
      • Header: Standortheader mit Ressourcen-URL 
      • Text: SDP-Antwort als Klartext
  • Serverseite:

    • SDP-Angebot erhalten: 

      • Lesen Sie das SDP aus dem Req.body
      • Erstellen Sie einen WebRTC-Endpunkt und legen Sie die Remote-Beschreibung fest 
    • SDP-Antwort generieren

      • Eine SDP-Antwort vom Server-WebRTC-Endpunkt
      • SDP-Antwort im res.body zurücksenden
      • Verwendung des TURN-Serverdienstes von Metered.ca

WebRTC WHIP & WHEP Tutorial: Build a live Streaming App

Verwendung des TURN-Serverdienstes von Metered.ca

Zweck des TURN-Servers

Erleichtert die Mediendurchquerung durch NAT und Firewall, wenn eine direkte Peer-to-Peer-Verbindung nicht möglich ist

TURN-Server in die ICE-Serverkonfiguration integrieren

Hier sind TURN-Server-Anmeldeinformationen und ICE-Server

gst-launch-1.0 whipserversrc name=whip \
  ! queue ! videoconvert ! autovideosink
Nach dem Login kopieren
Nach dem Login kopieren

Bereitstellen eines WHEP-Clients

Mit einem WHIP-Client kann Ihre App Medienströme vom Server mithilfe von HTTP-Signalisierung empfangen.

Integration von WHEP auf der Clientseite

  • Grundlegendes Verständnis der WebRTC-API in Javascript 

  • Medienserver, der WHEP GStreamer Janus oder andere unterstützt

  • Metered.ca TURN-Server-Anmeldeinformationen

Schritt für Schritt WHEP-Integration in Ihre App.

  1. Initialisieren Sie die RTCPeerConnection

    1. Erstellen Sie eine RTCPeerConnection-Instanz mit dem ICE-Server, der über metered.ca-Turn-Server verfügt
gst-launch-1.0 whipserversrc name=whip ice-server="turn://YOUR_USERNAME:YOUR_CREDENTIAL@relay.metered.ca:80" \
  ! queue ! videoconvert ! autovideosink
Nach dem Login kopieren
Nach dem Login kopieren
  1. Eingehende Medientitel verarbeiten

Richten Sie einen Ereignis-Listener ein, um Remote-Tracks vom Server wiederzubeleben

const express = require('express');
const httpProxy = require('http-proxy');
const app = express();
const proxy = httpProxy.createProxyServer();

app.post('/whip', (req, res) => {
  proxy.web(req, res, { target: 'http://localhost:PORT_WHERE_GSTREAMER_IS_RUNNING' });
});

app.listen(3000, () => {
  console.log('Proxy server running on port 3000');
});
Nach dem Login kopieren
Nach dem Login kopieren
  1. Senden Sie eine HTTP-GET-Anfrage an den WHEP-Server:

Senden Sie eine GET-Anfrage an den Server

const mediaStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
Nach dem Login kopieren
Nach dem Login kopieren
  1. Fernbeschreibung mit dem erhaltenen SDP-Angebot
var myPeerConnection = new RTCPeerConnection({
  iceServers: [
      {
        urls: "stun:stun.relay.metered.ca:80",
      },
      {
        urls: "turn:global.relay.metered.ca:80",
        username: "your-username",
        credential: "your-credential",
      },
      {
        urls: "turn:global.relay.metered.ca:80?transport=tcp",
        username: "your-username",
        credential: "your-credential",
      },
      {
        urls: "turn:global.relay.metered.ca:443",
        username: "your-username",
        credential: "your-credential",
      },
      {
        urls: "turns:global.relay.metered.ca:443?transport=tcp",
        username: "your-username",
        credential: "your-credential",
      },
  ],
});
Nach dem Login kopieren
Nach dem Login kopieren
  1. Erstellen und senden Sie die SDP-Antwort

Erstellen Sie eine SDP-Antwort und senden Sie sie über eine HTTP-POST-Anfrage an den Server

mediaStream.getTracks().forEach((track) => {
  pc.addTrack(track, mediaStream);
});
Nach dem Login kopieren
Nach dem Login kopieren
  1. Bearbeitung des ICE-Kandidatenaustauschs (optional):

Wenn Sie ICE-Kandidaten separat entsenden müssen, kümmern Sie sich um die Veranstaltung „icecandidate“

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

const response = await fetch('http://YOUR_SERVER_IP:3000/whip', {
  method: 'POST',
  headers: { 'Content-Type': 'application/sdp' },
  body: pc.localDescription.sdp,
});

const sdpAnswer = await response.text();
await pc.setRemoteDescription({ type: 'answer', sdp: sdpAnswer });
Nach dem Login kopieren
Nach dem Login kopieren

Verwalten Sie Medienstreams im Frontend

  1. Erstellen Sie ein Videoelement in HTML
var myPeerConnection = new RTCPeerConnection({
  iceServers: [
      {
        urls: "stun:stun.relay.metered.ca:80",
      },
      {
        urls: "turn:global.relay.metered.ca:80",
        username: "e13b9bsdfdsfsdfb0676cc5b6",
        credential: "dedewdewfer+gq5iT",
      },
      {
        urls: "turn:global.relay.metered.ca:80?transport=tcp",
        username: "e13bdfdsfds6b0676cc5b6",
        credential: "dewfrefre+gq5iT",
      },
      {
        urls: "turn:global.relay.metered.ca:443",
        username: "e13b9fsdfdsfsd86b0676cc5b6",
        credential: "csdfwefeer+gq5iT",
      },
      {
        urls: "turns:global.relay.metered.ca:443?transport=tcp",
        username: "e13b9dsfsdfe6b0676cc5b6",
        credential: "sdfewtrererer+gq5iT",
      },
  ],
});
Nach dem Login kopieren
Nach dem Login kopieren
  1. Remote-Stream an das Videoelement anhängen

Wenn ein Track-Ereignis ausgelöst wird, hängen Sie den empfangenen Stream an das Videoelement an

  1. Verwaltung des Medienstream-Ereignisses

    1. Änderung des Verbindungsstatus
var myPeerConnection = new RTCPeerConnection({
  iceServers: [
      {
        urls: "stun:stun.relay.metered.ca:80",
      },
      {
        urls: "turn:global.relay.metered.ca:80",
        username: "e13b9bsdfdsfsdfb0676cc5b6",
        credential: "dedewdewfer+gq5iT",
      },
      {
        urls: "turn:global.relay.metered.ca:80?transport=tcp",
        username: "e13bdfdsfds6b0676cc5b6",
        credential: "dewfrefre+gq5iT",
      },
      {
        urls: "turn:global.relay.metered.ca:443",
        username: "e13b9fsdfdsfsd86b0676cc5b6",
        credential: "csdfwefeer+gq5iT",
      },
      {
        urls: "turns:global.relay.metered.ca:443?transport=tcp",
        username: "e13b9dsfsdfe6b0676cc5b6",
        credential: "sdfewtrererer+gq5iT",
      },
  ],
});
Nach dem Login kopieren
Nach dem Login kopieren

b. Verhandlung erforderlich

pc.addEventListener('track', (event) => {
  const [remoteStream] = event.streams;
  // Attach the remote stream to a video element
  const remoteVideo = document.getElementById('remoteVideo');
  remoteVideo.srcObject = remoteStream;
});
Nach dem Login kopieren
  1. Vollständiger Beispielcode
const whepServerEndpoint = 'http://YOUR_SERVER_IP:3000/whep'; // Replace with your server's WHEP endpoint

const response = await fetch(whepEndpoint, {
  method: 'GET',
  headers: {
    Accept: 'application/sdp',
  },
});

const sdpOffer = await response.text();
Nach dem Login kopieren

WebRTC WHIP & WHEP Tutorial: Build a live Streaming App

Gemessene TURN-Server

  1. API: TURN-Serververwaltung mit leistungsstarker API. Sie können beispielsweise Anmeldeinformationen über die API hinzufügen/entfernen, Pro Benutzer/Anmeldeinformationen und Benutzermetriken über die API abrufen, Anmeldeinformationen über die API aktivieren/deaktivieren und Nutzungsdaten nach Datum über die API abrufen.

  2. Globales Geo-Location-Targeting: Leitet den Datenverkehr automatisch an die nächstgelegenen Server weiter, für geringstmögliche Latenz und höchste Leistungsqualität. Weniger als 50 ms Latenz überall auf der Welt

  3. Server in allen Regionen der Welt: Toronto, Miami, San Francisco, Amsterdam, London, Frankfurt, Bangalore, Singapur, Sydney, Seoul, Dallas, New York

  4. Geringe Latenz: weniger als 50 ms Latenz, überall auf der Welt.

  5. Kostengünstig: Pay-as-you-go-Preisgestaltung mit verfügbaren Bandbreiten- und Mengenrabatten.

  6. Einfache Verwaltung: Erhalten Sie Nutzungsprotokolle, E-Mails, wenn Konten Schwellenwerte erreichen, Abrechnungsunterlagen sowie E-Mail- und Telefonsupport.

  7. Standardkonform: Entspricht den RFCs 5389, 5769, 5780, 5766, 6062, 6156, 5245, 5768, 6336, 6544, 5928 über UDP, TCP, TLS und DTLS.

  8. Multi-Tenant-Funktion: Erstellen Sie mehrere Anmeldeinformationen und trennen Sie die Nutzung nach Kunden oder verschiedenen Apps. Erhalten Sie Nutzungsprotokolle, Abrechnungsaufzeichnungen und Schwellenwertwarnungen.

  9. Unternehmenszuverlässigkeit: 99,999 % Betriebszeit mit SLA.

  10. Enterprise Scale: Ohne Begrenzung des gleichzeitigen Datenverkehrs oder des Gesamtdatenverkehrs. Gemessene TURN-Server bieten Unternehmensskalierbarkeit

  11. 5 GB/Monat kostenlos: Mit dem kostenlosen Plan erhalten Sie jeden Monat 5 GB kostenlose TURN-Servernutzung

  12. Läuft auf Port 80 und 443

  13. Unterstützt TURNS SSL, um Verbindungen durch Deep-Packet-Inspection-Firewalls zu ermöglichen.

  14. Unterstützt sowohl TCP als auch UDP

  15. Kostenloser, unbegrenzter STUN


Sie können sich einige unserer anderen Artikel ansehen:

  1. WebRTC-Datenkanäle: Ein Leitfaden

  2. Einfaches Peer-Tutorial: TURN-Server für Video und DataChannel hinzufügen

  3. Anleitung zum Einrichten Ihres WebRTC TURN-Servers mit Metered

  4. WebRTC vs. HLS: Welches ist das Beste für Sie?

Das obige ist der detaillierte Inhalt vonWebRTC WHIP & WHEP Tutorial: Erstellen Sie eine Live-Streaming-App. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!