Bagikan melalui


Gambaran umum TCP

Penting

Kelas Socket ini sangat direkomendasikan untuk pengguna tingkat lanjut, bukan TcpClient dan TcpListener.

Untuk bekerja dengan Protokol Kontrol Transmisi (TCP), Anda memiliki dua opsi: gunakan Socket untuk kontrol dan performa maksimum, atau gunakan kelas dan TcpListener pembantuTcpClient. TcpClient dan TcpListener dibangun di atas System.Net.Sockets.Socket kelas dan mengurus detail transfer data untuk kemudahan penggunaan.

Kelas protokol menggunakan kelas yang mendasar Socket untuk menyediakan akses sederhana ke layanan jaringan tanpa overhead mempertahankan informasi status atau mengetahui detail penyiapan soket khusus protokol. Untuk menggunakan metode asinkron Socket , Anda dapat menggunakan metode asinkron yang disediakan oleh NetworkStream kelas . Untuk mengakses fitur kelas yang Socket tidak diekspos oleh kelas protokol, Anda harus menggunakan Socket kelas .

TcpClient dan TcpListener mewakili jaringan menggunakan NetworkStream kelas . Anda menggunakan metode GetStream untuk mengembalikan aliran jaringan, lalu memanggil metode NetworkStream.ReadAsync dan NetworkStream.WriteAsync aliran. NetworkStream tidak memiliki soket dasar kelas protokol, jadi menutupnya tidak memengaruhi soket.

Gunakan TcpClient dan TcpListener

Kelas TcpClient meminta data dari sumber daya internet menggunakan TCP. Metode dan properti TcpClient abstrak detail untuk membuat Socket untuk meminta dan menerima data menggunakan TCP. Karena koneksi ke perangkat jarak jauh direpresentasikan sebagai aliran, data dapat dibaca dan ditulis dengan teknik penanganan aliran .NET Framework.

Protokol TCP menetapkan koneksi dengan titik akhir jarak jauh, lalu menggunakan koneksi tersebut untuk mengirim dan menerima paket data. TCP bertanggung jawab untuk memastikan bahwa paket data dikirim ke titik akhir dan dirakit dalam urutan yang benar ketika tiba.

Membuat titik akhir IP

Saat bekerja dengan System.Net.Sockets, Anda mewakili titik akhir jaringan sebagai IPEndPoint objek. IPEndPoint dibangun dengan IPAddress dan nomor port yang sesuai. Sebelum dapat memulai percakapan melalui Socket, Anda membuat pipa data antara aplikasi dan tujuan jarak jauh.

TCP/IP menggunakan alamat jaringan dan nomor port layanan untuk mengidentifikasi layanan secara unik. Alamat jaringan mengidentifikasi tujuan jaringan tertentu; nomor port mengidentifikasi layanan tertentu pada perangkat tersebut untuk disambungkan. Kombinasi alamat jaringan dan port layanan disebut titik akhir, yang diwakili dalam .NET oleh EndPoint kelas . Keturunan EndPoint didefinisikan untuk setiap keluarga alamat yang didukung; untuk keluarga alamat IP, kelasnya adalah IPEndPoint.

Kelas ini Dns menyediakan layanan nama domain ke aplikasi yang menggunakan layanan internet TCP/IP. Metode ini GetHostEntryAsync meminta server DNS untuk memetakan nama domain yang mudah digunakan (seperti "host.contoso.com") ke alamat Internet numerik (seperti 192.168.1.1). GetHostEntryAsyncTask<IPHostEntry> mengembalikan yang ketika ditunggu berisi daftar alamat dan alias untuk nama yang diminta. Dalam kebanyakan kasus, Anda dapat menggunakan alamat pertama yang dikembalikan dalam larik AddressList. Kode berikut mendapatkan alamat IP yang IPAddress berisi untuk server host.contoso.com.

IPHostEntry ipHostInfo = await Dns.GetHostEntryAsync("host.contoso.com");
IPAddress ipAddress = ipHostInfo.AddressList[0];

Tip

Untuk tujuan pengujian dan penelusuran kesalahan manual, Anda biasanya dapat menggunakan GetHostEntryAsync metode dengan nama host yang dihasilkan dari Dns.GetHostName() nilai untuk menyelesaikan nama localhost ke alamat IP. Perhatikan cuplikan kode berikut:

var hostName = Dns.GetHostName();
IPHostEntry localhost = await Dns.GetHostEntryAsync(hostName);
// This is the IP address of the local machine
IPAddress localIpAddress = localhost.AddressList[0];

Internet Assigned Numbers Authority (IANA) menentukan nomor port untuk layanan umum. Untuk informasi selengkapnya, lihat IANA: Nama Layanan dan Registri Nomor Port Protokol Transportasi). Layanan lain dapat memiliki nomor port terdaftar dalam kisaran 1.024 hingga 65.535. Kode berikut menggabungkan alamat IP untuk host.contoso.com dengan nomor port untuk membuat titik akhir jarak jauh untuk koneksi.

IPEndPoint ipEndPoint = new(ipAddress, 11_000);

Setelah menentukan alamat perangkat jarak jauh dan memilih port yang akan digunakan untuk koneksi, aplikasi dapat membuat koneksi dengan perangkat jarak jauh.

Membuat TcpClient

Kelas ini TcpClient menyediakan layanan TCP pada tingkat abstraksi yang lebih tinggi daripada Socket kelas . TcpClient digunakan untuk membuat koneksi klien ke host jarak jauh. Mengetahui cara mendapatkan IPEndPoint, mari kita asumsikan Anda memiliki untuk dipasangkan dengan nomor port yang IPAddress Anda inginkan. Contoh berikut menunjukkan pengaturan TcpClient untuk menyambungkan ke server waktu di port TCP 13:

var ipEndPoint = new IPEndPoint(ipAddress, 13);

using TcpClient client = new();
await client.ConnectAsync(ipEndPoint);
await using NetworkStream stream = client.GetStream();

var buffer = new byte[1_024];
int received = await stream.ReadAsync(buffer);

var message = Encoding.UTF8.GetString(buffer, 0, received);
Console.WriteLine($"Message received: \"{message}\"");
// Sample output:
//     Message received: "📅 8/22/2022 9:07:17 AM 🕛"

Kode C# sebelumnya:

  • IPEndPoint Membuat dari port dan yang diketahuiIPAddress.
  • Membuat instans objek baru TcpClient .
  • Menyambungkan client ke server waktu TCP jarak jauh pada port 13 menggunakan TcpClient.ConnectAsync.
  • NetworkStream Menggunakan untuk membaca data dari host jarak jauh.
  • Mendeklarasikan buffer 1_024 byte baca.
  • Membaca data dari stream ke dalam buffer baca.
  • Menulis hasilnya sebagai string ke konsol.

Karena klien tahu bahwa pesan kecil, seluruh pesan dapat dibaca ke dalam buffer baca dalam satu operasi. Dengan pesan yang lebih besar, atau pesan dengan panjang yang tidak ditentukan, klien harus menggunakan buffer dengan lebih tepat dan membaca dalam perulangan while .

Penting

Saat mengirim dan menerima pesan, Encoding harus diketahui sebelumnya ke server dan klien. Misalnya, jika server berkomunikasi menggunakan ASCIIEncoding tetapi klien mencoba menggunakan UTF8Encoding, pesan akan salah bentuk.

Membuat TcpListener

Jenis ini TcpListener digunakan untuk memantau port TCP untuk permintaan masuk lalu membuat Socket atau TcpClient yang mengelola koneksi ke klien. Metode Start ini mengaktifkan mendengarkan, dan metode Stop menonaktifkan mendengarkan pada port. Metode ini AcceptTcpClientAsync menerima permintaan koneksi masuk dan membuat TcpClient untuk menangani permintaan, dan AcceptSocketAsync metode menerima permintaan koneksi masuk dan membuat Socket untuk menangani permintaan.

Contoh berikut menunjukkan pembuatan server waktu jaringan menggunakan TcpListener untuk memantau port TCP 13. Ketika permintaan koneksi masuk diterima, server waktu merespons dengan tanggal dan waktu saat ini dari server host.

var ipEndPoint = new IPEndPoint(IPAddress.Any, 13);
TcpListener listener = new(ipEndPoint);

try
{    
    listener.Start();

    using TcpClient handler = await listener.AcceptTcpClientAsync();
    await using NetworkStream stream = handler.GetStream();

    var message = $"📅 {DateTime.Now} 🕛";
    var dateTimeBytes = Encoding.UTF8.GetBytes(message);
    await stream.WriteAsync(dateTimeBytes);

    Console.WriteLine($"Sent message: \"{message}\"");
    // Sample output:
    //     Sent message: "📅 8/22/2022 9:07:17 AM 🕛"
}
finally
{
    listener.Stop();
}

Kode C# sebelumnya:

  • IPEndPoint Membuat dengan IPAddress.Any dan port.
  • Membuat instans objek baru TcpListener .
  • Start Memanggil metode untuk mulai mendengarkan di port.
  • TcpClient Menggunakan dari AcceptTcpClientAsync metode untuk menerima permintaan koneksi masuk.
  • Mengodekan tanggal dan waktu saat ini sebagai pesan string.
  • NetworkStream Menggunakan untuk menulis data ke klien yang tersambung.
  • Menulis pesan terkirim ke konsol.
  • Terakhir, memanggil Stop metode untuk berhenti mendengarkan di port.

Kontrol TCP terbatas dengan Socket kelas

Baik TcpClient dan TcpListener secara internal mengandalkan Socket kelas, yang berarti apa pun yang dapat Anda lakukan dengan kelas-kelas ini dapat dicapai menggunakan soket secara langsung. Bagian ini menunjukkan beberapa TcpClient dan TcpListener kasus penggunaan, bersama dengan rekan mereka Socket yang setara secara fungsional.

Membuat soket klien

TcpClientKonstruktor default mencoba membuat soket tumpukan ganda melalui konstruktor Socket(SocketType, ProtocolType). Konstruktor ini membuat soket tumpukan ganda jika IPv6 didukung, jika tidak, konstruktor ini akan kembali ke IPv4.

Pertimbangkan kode klien TCP berikut:

using var client = new TcpClient();

Kode klien TCP sebelumnya secara fungsional setara dengan kode soket berikut:

using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

Konstruktor TcpClient(AddressFamily)

Konstruktor ini hanya menerima tiga AddressFamily nilai, jika tidak, konstruktor ini akan melemparkan ArgumentException. Nilai yang valid adalah:

Pertimbangkan kode klien TCP berikut:

using var client = new TcpClient(AddressFamily.InterNetwork);

Kode klien TCP sebelumnya secara fungsional setara dengan kode soket berikut:

using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

Konstruktor TcpClient(IPEndPoint)

Setelah membuat soket, konstruktor ini juga akan mengikat lokal yang disediakan . IPEndPoint Properti IPEndPoint.AddressFamily digunakan untuk menentukan keluarga alamat soket.

Pertimbangkan kode klien TCP berikut:

var endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5001);
using var client = new TcpClient(endPoint);

Kode klien TCP sebelumnya secara fungsional setara dengan kode soket berikut:

// Example IPEndPoint object
var endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5001);
using var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(endPoint);

Konstruktor TcpClient(String, Int32)

Konstruktor ini akan mencoba membuat dual-stack yang mirip dengan konstruktor default dan menyambungkannya ke titik akhir DNS jarak jauh yang hostname ditentukan oleh pasangan dan port .

Pertimbangkan kode klien TCP berikut:

using var client = new TcpClient("www.example.com", 80);

Kode klien TCP sebelumnya secara fungsional setara dengan kode soket berikut:

using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
socket.Connect("www.example.com", 80);

Sambungkan ke server

Semua Connectkelebihan beban TcpClient , ConnectAsync, BeginConnect dan EndConnect secara fungsional setara dengan metode yang Socket sesuai.

Pertimbangkan kode klien TCP berikut:

using var client = new TcpClient();
client.Connect("www.example.com", 80);

Kode di atas TcpClient setara dengan kode soket berikut:

using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
socket.Connect("www.example.com", 80);

Membuat soket server

Sama seperti TcpClient instans yang memiliki kesetaraan fungsional dengan mitra mentah Socket mereka, bagian ini memetakan TcpListener konstruktor ke kode soket yang sesuai. Konstruktor pertama yang perlu dipertimbangkan TcpListener(IPAddress localaddr, int port)adalah .

var listener = new TcpListener(IPAddress.Loopback, 5000);

Kode pendengar TCP sebelumnya secara fungsional setara dengan kode soket berikut:

var ep = new IPEndPoint(IPAddress.Loopback, 5000);
using var socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

Mulai mendengarkan di server

Metode ini Start() adalah pembungkus yang menggabungkan Socketfungsionalitas Bind dan Listen() .

Pertimbangkan kode pendengar TCP berikut:

var listener = new TcpListener(IPAddress.Loopback, 5000);
listener.Start(10);

Kode pendengar TCP sebelumnya secara fungsional setara dengan kode soket berikut:

var endPoint = new IPEndPoint(IPAddress.Loopback, 5000);
using var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(endPoint);
try
{
    socket.Listen(10);
}
catch (SocketException)
{
    socket.Dispose();
}

Menerima koneksi server

Di bawah tenda, koneksi TCP masuk selalu membuat soket baru saat diterima. TcpListener dapat menerima Socket instans secara langsung (melalui AcceptSocket() atau AcceptSocketAsync()) atau dapat menerima TcpClient (melalui AcceptTcpClient() dan AcceptTcpClientAsync()).

Pertimbangkan kode berikut TcpListener :

var listener = new TcpListener(IPAddress.Loopback, 5000);
using var acceptedSocket = await listener.AcceptSocketAsync();

// Synchronous alternative.
// var acceptedSocket = listener.AcceptSocket();

Kode pendengar TCP sebelumnya secara fungsional setara dengan kode soket berikut:

var endPoint = new IPEndPoint(IPAddress.Loopback, 5000);
using var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
using var acceptedSocket = await socket.AcceptAsync();

// Synchronous alternative
// var acceptedSocket = socket.Accept();

Membuat NetworkStream untuk mengirim dan menerima data

Dengan TcpClient Anda perlu membuat instans NetworkStream dengan GetStream() metode untuk dapat mengirim dan menerima data . Dengan Socket, Anda harus melakukan NetworkStream pembuatan secara manual.

Pertimbangkan kode berikut TcpClient :

using var client = new TcpClient();
using NetworkStream stream = client.GetStream();

Yang setara dengan kode soket berikut:

using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

// Be aware that transferring the ownership means that closing/disposing the stream will also close the underlying socket.
using var stream = new NetworkStream(socket, ownsSocket: true);

Tip

Jika kode Anda tidak perlu bekerja dengan Stream instans, Anda dapat mengandalkan Socketmetode Kirim/Terima (Send, SendAsync, Receive dan ReceiveAsync) secara langsung alih-alih membuat NetworkStream.

Lihat juga