Ini mungkin pertanyaan yang sangat mendasar tetapi membingungkan saya.
Bisakah dua soket terhubung yang berbeda berbagi port? Saya sedang menulis sebuah server aplikasi yang seharusnya dapat menangani lebih dari 100k koneksi bersamaan, dan kami tahu bahwa jumlah port yang tersedia pada sistem adalah sekitar 60k (16bit). Soket yang terhubung ditetapkan ke port baru (khusus), jadi itu berarti jumlah koneksi bersamaan dibatasi oleh jumlah port, kecuali beberapa soket dapat berbagi port yang sama. Jadi pertanyaannya.
Terima kasih atas bantuannya sebelumnya!
TCP / HTTP Mendengarkan Pada Port: Bagaimana Banyak Pengguna Dapat Berbagi Port Yang Sama
Jadi, apa yang terjadi ketika server mendengarkan koneksi masuk pada port TCP? Misalnya, Anda memiliki server web pada port 80. Anggaplah komputer Anda memiliki alamat IP publik 24.14.181.229 dan orang yang mencoba menyambung ke Anda memiliki alamat IP 10.1.2.3. Orang ini dapat terhubung dengan Anda dengan membuka soket TCP ke 24.14.181.229:80. Cukup sederhana.
Secara intuitif (dan salah), kebanyakan orang berasumsi bahwa tampilannya seperti ini:
Ini intuitif, karena dari sudut pandang klien, dia memiliki alamat IP, dan terhubung ke server di IP: PORT. Karena klien terhubung ke port 80, maka portnya juga harus 80? Ini adalah hal yang masuk akal untuk dipikirkan, tetapi sebenarnya bukan apa yang terjadi. Jika itu benar, kami hanya dapat melayani satu pengguna per alamat IP asing. Setelah komputer jarak jauh terhubung, maka dia akan memonopoli koneksi port 80 ke port 80, dan tidak ada orang lain yang dapat terhubung.
Tiga hal yang harus dipahami:
1.) Di server, proses sedang mendengarkan di port. Setelah mendapat koneksi, itu menyerahkannya ke utas lain. Komunikasi tidak pernah membebani port mendengarkan.
2.) Koneksi dikenali secara unik oleh OS dengan 5-tuple berikut: (local-IP, local-port, remote-IP, remote-port, protocol). Jika ada elemen dalam tupel yang berbeda, maka ini adalah koneksi yang sepenuhnya independen.
3.) Ketika klien terhubung ke server, ia mengambil port sumber tingkat tinggi acak yang tidak terpakai . Dengan cara ini, satu klien dapat memiliki hingga ~ 64k koneksi ke server untuk port tujuan yang sama.
Jadi, inilah yang sebenarnya dibuat ketika klien terhubung ke server:
Melihat Apa yang Sebenarnya Terjadi
Pertama, mari gunakan netstat untuk melihat apa yang terjadi di komputer ini. Kami akan menggunakan port 500, bukan 80 (karena banyak hal terjadi pada port 80 karena ini adalah port yang umum, tetapi secara fungsional tidak membuat perbedaan).
Seperti yang diharapkan, hasilnya kosong. Sekarang mari kita mulai server web:
Sekarang, inilah hasil dari menjalankan netstat lagi:
Jadi sekarang ada satu proses yang aktif mendengarkan (Status: LISTEN) pada port 500. Alamat lokalnya adalah 0.0.0.0, yang merupakan kode untuk "mendengarkan semua alamat ip". Kesalahan yang mudah dilakukan adalah hanya mendengarkan pada port 127.0.0.1, yang hanya akan menerima koneksi dari komputer saat ini. Jadi ini bukan koneksi, ini hanya berarti bahwa proses diminta untuk mengikat () ke port IP, dan proses tersebut bertanggung jawab untuk menangani semua koneksi ke port tersebut. Ini mengisyaratkan batasan bahwa hanya ada satu proses per komputer yang mendengarkan pada port (ada cara untuk menyiasatinya menggunakan multiplexing, tetapi ini adalah topik yang jauh lebih rumit). Jika server web mendengarkan pada port 80, itu tidak dapat berbagi port itu dengan server web lain.
Jadi sekarang, mari hubungkan pengguna ke mesin kita:
Ini adalah skrip sederhana ( https://github.com/grokit/quickweb ) yang membuka soket TCP, mengirim payload ("Uji payload". Dalam hal ini), menunggu beberapa detik dan memutuskan hubungan. Melakukan netstat lagi saat ini terjadi akan menampilkan berikut ini:
Jika Anda terhubung dengan klien lain dan melakukan netstat lagi, Anda akan melihat yang berikut ini:
... yaitu, klien menggunakan port acak lain untuk koneksi tersebut. Jadi tidak pernah ada kebingungan antara alamat IP.
sumber
Itu intuisi yang umum, tapi itu tidak benar. Soket yang terhubung tidak ditetapkan ke port baru / khusus. Satu-satunya kendala sebenarnya yang harus dipenuhi oleh tumpukan TCP adalah bahwa tupel (local_address, local_port, remote_address, remote_port) harus unik untuk setiap koneksi soket. Dengan demikian server dapat memiliki banyak soket TCP menggunakan porta lokal yang sama, selama masing-masing soket pada port tersebut terhubung ke lokasi jarak jauh yang berbeda.
Lihat paragraf "Pasangan Soket" di: http://books.google.com/books?id=ptSC4LpwGA0C&lpg=PA52&dq=socket%20pair%20tuple&pg=PA52#v=onepage&q=socket%20pair%20tuple&f=false
sumber
bind()
operasi tersebut mendahuluiconnect()
operasi, bahkan secara implisit.bind()
hanya digunakan di sisi serveraccept()?
Jadi sisi klien akan mengikat port tertentu juga?bind()
dapat digunakan di sisi klien sebelumnyaconnect()
.Secara teoritis, ya. Berlatih, tidak. Kebanyakan kernel (termasuk linux) tidak mengizinkan Anda sedetik pun
bind()
ke port yang telah dialokasikan. Itu bukan tambalan yang sangat besar untuk membuat ini diizinkan.Secara konseptual, kita harus membedakan antara soket dan port . Soket adalah titik akhir komunikasi dua arah, yaitu "benda" di mana kita dapat mengirim dan menerima byte. Ini adalah hal yang konseptual, tidak ada bidang seperti itu di header paket bernama "socket".
Port adalah pengenal yang mampu mengidentifikasi soket. Dalam kasus TCP, port adalah 16 bit integer, tetapi ada protokol lain juga (misalnya, pada soket unix, "port" pada dasarnya adalah string).
Masalah utamanya adalah sebagai berikut: jika paket masuk tiba, kernel dapat mengidentifikasi soketnya dengan nomor port tujuannya. Ini adalah cara yang paling umum, tetapi ini bukan satu-satunya kemungkinan:
Karena Anda bekerja pada server aplikasi, itu akan dapat melakukan itu.
sumber
bind()
.bind()
? Saya dapat membayangkannya, ya itu sangat mungkin, tetapi kenyataannya adalah bahwa WinSock dan API Posix menggunakanbind()
panggilan untuk itu, bahkan parametrisasinya secara praktis sama. Bahkan jika API tidak memiliki panggilan ini, bagaimanapun Anda perlu mengatakannya, dari mana Anda ingin membaca byte yang masuk .listen()
/accept()
panggilan API dapat membuat soket dengan cara yang akan dibedakan oleh kernel dengan port masuknya. Pertanyaan tentang OP dapat diinterpretasikan dari cara yang dia minta pada dasarnya. Saya pikir, ini cukup realistis, tetapi bukan ini yang dimaksud dengan pertanyaannya secara harfiah.Tidak. Tidak mungkin berbagi port yang sama pada saat tertentu. Tetapi Anda dapat membuat aplikasi Anda sedemikian rupa sehingga akan membuat akses port pada saat yang berbeda.
sumber