← Cloudflare Workers / workers / runtime-apis
TCP sockety
Workers runtime poskytuje connect() API pro vytváření odchozích Připojení TCP ↗ z Workers.
Mnoho protokolů aplikační vrstvy je postaveno na protokolu Transmission Control Protocol (TCP). Tyto protokoly aplikační vrstvy, mezi než patří SSH, MQTT, SMTP, FTP, IRC a většina databázových protokolů, včetně MySQL, PostgreSQL a MongoDB, vyžadují ke svému fungování podkladové TCP socket API.
connect()
connect() funkce vrací TCP socket obsahující jak čitelný a zapisovatelný stream dat. To umožňuje průběžně číst a zapisovat data, dokud zůstává spojení otevřené.
connect() je zadáno jako Runtime API, a přistupuje se k němu importováním connect funkce z cloudflare:sockets. Tento postup je podobný importu vestavěných modulů v Node.js. Příklad vytvoření TCP socketu, zápisu do něj a vrácení čitelné strany socketu jako odpovědi najdete v následujícím bloku kódu:
import { connect } from 'cloudflare:sockets';
export default {
async fetch(req): Promise<Response> {
const gopherAddr = { hostname: "gopher.floodgap.com", port: 70 };
const url = new URL(req.url);
try {
const socket = connect(gopherAddr);
const writer = socket.writable.getWriter()
const encoder = new TextEncoder();
const encoded = encoder.encode(url.pathname + "\r\n");
await writer.write(encoded);
await writer.close();
return new Response(socket.readable, { headers: { "Content-Type": "text/plain" } });
} catch (error) {
return new Response("Socket connection failed: " + error, { status: 500 });
}
}
} satisfies ExportedHandler;connect(address: SocketAddress | string, options?: optional SocketOptions):Socketconnect()přijímá buď řetězec URL, neboSocketAddresspro definici názvu hostitele a čísla portu, ke kterým se má připojit, a volitelný konfigurační objektSocketOptions. Vrací instanciSocket.
SocketAddress
-
hostnamestring- Název hostitele, ke kterému se připojit. Příklad:
cloudflare.com.
- Název hostitele, ke kterému se připojit. Příklad:
-
portnumber- Číslo portu, ke kterému se má připojit. Příklad:
5432.
- Číslo portu, ke kterému se má připojit. Příklad:
SocketOptions
-
secureTransport"off" | "on" | "starttls", výchozí hodnota jeoff- Určuje, zda se má použít TLS ↗ při vytváření TCP soketu.
off: nepoužívat TLS.on: použít TLS.starttls, Do not use TLS initially, but allow the socket to be upgraded to use TLS by callingstartTls().
-
allowHalfOpenboolean: Výchozí hodnota jefalse- Definuje, zda se zapisovatelná strana TCP socketu automaticky uzavře při konci souboru (EOF). Když je nastaveno na
false, zapisovací strana TCP socketu se při EOF automaticky uzavře. Pokud je nastaveno natrue, zapisovací strana TCP socketu zůstane při EOF otevřená. - Tato možnost je podobná té, kterou nabízí Node.js
netmodul ↗ a umožňuje interoperabilitu s kódem, který ho využívá.
- Definuje, zda se zapisovatelná strana TCP socketu automaticky uzavře při konci souboru (EOF). Když je nastaveno na
SocketInfo
-
remoteAddressstring | null- Adresa vzdáleného protějšku, ke kterému je socket připojen. Nemusí být vždy nastavena.
-
localAddressstring | null- Adresa místního síťového koncového bodu pro tento socket. Nemusí být vždy nastavena.
Socket
-
readable: ReadableStream- Vrátí čtecí stranu socketu TCP.
-
writable: WritableStream- Vrátí zapisovací stranu socketu TCP.
-
WritableStreamvrácená přijímá pouze bloky o velikostiUint8Arraynebo jeho zobrazení.
-
openedPromise<SocketInfo>- Tento promise je resolved ve chvíli, kdy se naváže socket connection, a je rejected, pokud u socketu dojde k chybě.
-
closedPromise<void>- Tento promise je resolved ve chvíli, kdy se socket uzavře, a je rejected, pokud u socketu dojde k chybě.
-
close()Promise<void>- Zavře soket TCP. Čtecí i zapisovací datové proudy budou vynuceně uzavřeny.
-
startTls(): Socket- Převede nezabezpečený socket na zabezpečený, který používá TLS, a vrátí nový Socket. Vezměte na vědomí, že pro volání
startTls(), musíte nastavitsecureTransportnastarttlspři počátečním voláníconnect()pro vytvoření soketu.
- Převede nezabezpečený socket na zabezpečený, který používá TLS, a vrátí nový Socket. Vezměte na vědomí, že pro volání
Oportunní TLS (StartTLS)
Mnoho systémů založených na TCP, včetně databází a e-mailových serverů, vyžaduje, aby klienti používali oportunistické TLS (jinak známé jako StartTLS ↗) při připojování. V tomto vzoru klient nejprve vytvoří nezabezpečený TCP socket bez TLS a poté ho upgraduje na zabezpečený TCP socket, který používá TLS. connect() API to zjednodušuje tím, že poskytuje metodu startTls(), která vrací nový Socket instance, která používá TLS:
import { connect } from "cloudflare:sockets"
const address = {
hostname: "example-postgres-db.com",
port: 5432
};
const socket = connect(address, { secureTransport: "starttls" });
const secureSocket = socket.startTls();startTls()lze volat pouze tehdy, pokudsecureTransportje nastaveno nastarttlspři vytváření počátečního TCP soketu.- Jakmile
startTls()je volána, počáteční socket se uzavře a nelze z něj dále číst ani do něj zapisovat. V uvedeném příkladu kdykoli postartTls()je volána, použijete nově vytvořenýsecureSocket. Any existing readers and writers based off the original socket will no longer work. You must create new readers and writers from the newly createdsecureSocket. startTls()by měl být volán pouze jednou na existujícím socketu.
Zpracování chyb
Chcete-li zpracovat chyby při vytváření nového TCP socketu, čtení ze socketu nebo zápisu do socketu, obalte tato volání do try...catch ↗ blocích příkazů. Následující příklad otevře spojení s Google.com, zahájí HTTP request a vrátí odpověď. Pokud se to nezdaří a dojde k výjimce, vrátí 500 odpověď:
import { connect } from 'cloudflare:sockets';
const connectionUrl = { hostname: "google.com", port: 80 };
export interface Env { }
export default {
async fetch(req, env, ctx): Promise<Response> {
try {
const socket = connect(connectionUrl);
const writer = socket.writable.getWriter();
const encoder = new TextEncoder();
const encoded = encoder.encode("GET / HTTP/1.0\r\n\r\n");
await writer.write(encoded);
await writer.close();
return new Response(socket.readable, { headers: { "Content-Type": "text/plain" } });
} catch (error) {
return new Response(`Socket connection failed: ${error}`, { status: 500 });
}
}
} satisfies ExportedHandler<Env>;Zavřete připojení TCP
Připojení TCP můžete uzavřít voláním close() na socketu. Tím se uzavře čtecí i zapisovací strana socketu.
import { connect } from "cloudflare:sockets"
const socket = connect({ hostname: "my-url.com", port: 70 });
const reader = socket.readable.getReader();
socket.close();
// After close() is called, you can no longer read from the readable side of the socket
const reader = socket.readable.getReader(); // This failsCo zvážit
- Odchozí sokety TCP na Rozsahy IP adres Cloudflare ↗ jsou blokovány.
- TCP sockety nelze vytvářet v globálním rozsahu a sdílet mezi požadavky. Vždy je vytvářejte uvnitř handleru (např.
fetch(),scheduled(),queue()) neboalarm(). - Každý otevřený TCP socket se počítá do maximálního počtu otevřená připojení které mohou být otevřené současně.
- Pokud je otevřený TCP socket vytvořen uvnitř Durable Object, udržuje daný Durable Object v paměti a způsobuje mu účtování poplatků za dobu běhu, a to až 15 minut na jedno připojení. Po 15 minutách socket přestane Durable Object udržovat naživu (samotný socket dál funguje) a standardní pravidla vyřazování z paměti obnovit.
- Ve výchozím nastavení nemohou Workers vytvářet odchozí TCP připojení na portu
25pro odesílání e-mailů na servery SMTP. Cloudflare Email Workers poskytuje rozhraní API pro zpracování a přeposílání e-mailů. - Podpora zpracování příchozích TCP připojení je již brzy ↗. V současnosti není možné navázat příchozí připojení TCP k vašemu Workeru, například pomocí
CONNECTmetoda HTTP.
Řešení potíží
Přečtěte si popisy běžných chybových zpráv, se kterými se můžete setkat při práci se sockety TCP, co znamenají a jak je vyřešit.
proxy request failed, cannot connect to the specified address
Váš socket se připojuje k adrese, která je zakázaná. Mezi zakázané adresy patří například IP adresy Cloudflare, localhost, a IP adresy soukromých sítí.
Pokud se potřebujete připojit k adresám na portu 80 nebo 443 k odesílání HTTP požadavků použijte fetch.
TCP Loop detected
Váš socket se připojuje zpět k Workeru, který odchozí připojení inicioval. Jinými slovy, Worker se připojuje sám k sobě. To v současné době není podporováno.
Connections to port 25 are prohibited
Váš socket se připojuje k adrese na portu 25. Toto je obvykle port používaný pro SMTP poštovní servery. Workers nemohou vytvářet odchozí připojení na portu 25. Zvažte použití Cloudflare Email Workers místo toho.