Bisakah dua aplikasi mendengarkan port yang sama?

283

Bisakah dua aplikasi pada mesin yang sama mengikat ke port dan alamat IP yang sama? Melangkah lebih jauh, dapatkah satu aplikasi mendengarkan permintaan yang datang dari IP tertentu dan yang lainnya ke IP jarak jauh lainnya? Saya tahu saya dapat memiliki satu aplikasi yang dimulai dari dua utas (atau garpu) untuk memiliki perilaku yang sama, tetapi dapatkah dua aplikasi yang tidak memiliki kesamaan melakukan hal yang sama?

nadiv
sumber
2
Untuk jawaban terinci yang baik tentang penggunaan kembali alamat / port dengan beberapa soket: stackoverflow.com/questions/14388706/…
Bjarke Freund-Hansen

Jawaban:

248

Jawabannya berbeda tergantung pada OS apa yang dipertimbangkan. Secara umum:

Untuk TCP, tidak. Anda hanya dapat memiliki satu aplikasi mendengarkan pada port yang sama sekaligus. Sekarang jika Anda memiliki 2 kartu jaringan, Anda dapat meminta satu aplikasi mendengarkan pada IP pertama dan yang kedua pada IP kedua menggunakan nomor port yang sama.

Untuk UDP (Multicast), beberapa aplikasi dapat berlangganan ke port yang sama.

Sunting: Sejak Linux Kernel 3.9 dan yang lebih baru, dukungan untuk beberapa aplikasi yang mendengarkan port yang sama ditambahkan menggunakan SO_REUSEPORTopsi. Informasi lebih lanjut tersedia di artikel lwn.net ini.

Chris Dail
sumber
22
"satu aplikasi mendengarkan pada satu port" itulah alasan mengapa port ada - untuk memungkinkan beberapa aplikasi berbagi jaringan tanpa konflik.
S.Lott
46
Satu pendengar per port per alamat IP. Menambahkan antarmuka jaringan lain adalah cara untuk mendapatkan alamat IP kedua. Platform Anda mungkin mendukung antarmuka virtual yang merupakan cara lain untuk mendapatkan dua alamat IP dengan satu kartu jaringan fisik.
John M
7
Meskipun saya berpendapat sama sampai sekarang, ternyata saya bisa mengikat dua proses berbeda ke ip dan TCP port yang sama! Ini dimungkinkan jika Anda mengatur ServerSocket.setReuseAddress (true) di Java sebelum mengikatnya. Perilaku yang benar-benar tak terduga.
Eugen
7
(1) Arti sebenarnya dari jawaban Anda adalah 'Untuk TCP, ya, asalkan ...' (2) Multicast bukan prasyarat untuk berbagi port UDP, tetapi SO_REUSEADDR adalah.
Marquis of Lorne
12
Untuk UDP (Multicast), beberapa aplikasi dapat berlangganan ke port yang sama. Jika satu paket telah tiba dari klien, aplikasi mana yang menerimanya?
Yang Juven
123

Ya (untuk TCP) Anda dapat meminta dua program mendengarkan pada soket yang sama, jika program dirancang untuk melakukannya. Ketika soket dibuat oleh program pertama, pastikan SO_REUSEADDRopsi sudah diatur pada soket sebelum Anda bind(). Namun, ini mungkin bukan yang Anda inginkan. Apa yang dilakukan adalah koneksi TCP yang masuk akan diarahkan ke salah satu program, bukan keduanya, sehingga tidak menggandakan koneksi, itu hanya memungkinkan dua program untuk melayani permintaan yang masuk. Misalnya, server web akan memiliki beberapa proses yang semuanya mendengarkan pada port 80, dan O / S mengirim koneksi baru ke proses yang siap menerima koneksi baru.

SO_REUSEADDR

Mengizinkan soket lain ke bind()port ini, kecuali jika sudah ada soket mendengarkan aktif yang terikat ke port. Ini memungkinkan Anda untuk menghindari pesan-pesan kesalahan "Alamat yang sudah digunakan" ketika Anda mencoba untuk me-restart server Anda setelah crash.

JNewton
sumber
1
TCP + UDP sekarang berfungsi (diberi kernel yang cukup baru). Lihat tautan yang saya tambahkan ke jawabannya.
dpb
3
Jawaban ini tidak benar kecuali semua soket terikat ke alamat IP yang berbeda yang tidak ada yang INADDR_ANY, atau kecuali Anda berada di Windows, di mana hasilnya tidak ditentukan.
Marquis of Lorne
1
Bisakah Anda memperluas bagaimana data masuk ke aplikasi tertentu pada port yang sama? Apakah ada masalah keamanan yang perlu dipikirkan ketika aplikasi menggunakan SO_REUSEADDR atau SO_REUSEPORT?
trusktr
@ EJP Bisakah Anda melihat komentar saya sebelumnya?
trusktr
3
SO_REUSEADDRtentu saja tidak membiarkan Anda memiliki dua soket TCP dalam kondisi mendengarkan pada saat yang sama, setidaknya di Unix. Ini dimaksudkan untuk berkeliling TIME_WAIT state: unixguide.net/network/socketfaq/4.5.shtml . Ini mungkin bekerja pada Windows, tetapi Anda tidak dijamin bahwa permintaan akan mencapai server yang benar).
Bruno
48

Iya.

  1. Beberapa soket TCP yang mendengarkan, semuanya terikat ke port yang sama, dapat hidup berdampingan, asalkan semuanya terikat ke alamat IP lokal yang berbeda. Klien dapat terhubung ke mana pun mereka perlu. Ini tidak termasuk 0.0.0.0( INADDR_ANY).

  2. Beberapa soket yang diterima dapat hidup berdampingan, semua diterima dari soket pendengaran yang sama, semua menunjukkan nomor port lokal yang sama dengan soket pendengaran.

  3. Beberapa soket UDP semua terikat pada port yang sama dapat semuanya hidup berdampingan dengan ketentuan yang sama seperti pada (1) atau semuanya memiliki SO_REUSEADDRopsi yang ditetapkan sebelum mengikat.

  4. Port TCP dan port UDP menempati ruang nama yang berbeda, sehingga penggunaan port untuk TCP tidak menghalangi penggunaannya untuk UDP, dan sebaliknya.

Referensi: Stevens & Wright, Illustrated TCP / IP, Volume II.

Marquis dari Lorne
sumber
apakah Anda memiliki tautan? Peluang koeksistensi TCP-UDP adalah pertanyaan saya. Terima kasih sebelumnya :)
Wolf
1
@ Serigala Coba saja. Itu semua bukti yang benar-benar Anda butuhkan. Kutipan saya adalah Stevens & Wright: Anda tidak bisa menjadi lebih baik dari itu.
Marquis of Lorne
1
Terima kasih atas tanggapannya, saya perlu membaca lebih penuh perhatian. Anda sudah menulis bahwa UDP dan TCP dapat hidup berdampingan .
Wolf
47

Pada prinsipnya tidak.

Itu tidak ditulis dalam batu; tapi begitulah cara semua API ditulis: aplikasi membuka port, menanganinya, dan OS memberitahukannya (melalui pegangan itu) ketika koneksi klien (atau paket dalam kasus UDP) tiba.

Jika OS mengizinkan dua aplikasi untuk membuka port yang sama, bagaimana ia tahu mana yang harus diberitahukan?

Tapi ... ada beberapa cara mengatasinya:

  1. Seperti yang dicatat Jed , Anda bisa menulis proses 'master', yang akan menjadi satu-satunya yang benar-benar mendengarkan di port dan memberi tahu orang lain, menggunakan logika apa pun yang ingin memisahkan permintaan klien.
    • Di Linux dan BSD (setidaknya) Anda dapat mengatur aturan 'remapping' yang mengarahkan paket dari port 'terlihat' ke yang berbeda (di mana aplikasi mendengarkan), sesuai dengan kriteria terkait jaringan apa pun (mungkin jaringan asal, atau beberapa bentuk sederhana dari load balancing).
Javier
sumber
37
iptables -m statistic --mode random --probability 0.5menyenangkan.
Jed Smith
1
Apa yang sebenarnya menandakan "Membuka porta"? Saya mengerti kalimatnya tetapi apakah Anda tahu persis apa yang dilakukan sistem ketika membuka port dan menanganinya? Saya tahu bahwa ketika Anda ingin membuka port dengan TCP, Anda mendapatkan aliran dan aliran itu adalah koneksi Anda dengan remote tetapi saya mencari di web dan tidak menemukan penjelasan yang sangat bagus.
Samuel
4
@Samuel: membuka port (dalam mode server) berarti mendapatkan deskriptor file, dan ketika sistem mendapatkan paket SYN ke nomor port itu, merespons dengan SYN + ACK dan menghasilkan acara pada deskriptor file terkait. aplikasi merespons peristiwa itu dengan panggilan accept (), yang membuat deskriptor file baru yang terkait dengan aliran spesifik, membiarkan deskriptor server asli bebas untuk mendapatkan koneksi baru dari klien
Javier
7
Jawaban ini tidak dapat dianggap benar. Itu sepenuhnya mengabaikan keberadaan SO_REUSEADDR dan SO_REUSEPORT.
Marquis of Lorne
@ Javier Tidak, tidak. Membuka port dari sudut pandang aplikasi server terjadi ketika Anda mengikat soket mendengarkan, atau lebih tepatnya mengikat soket yang akan Anda gunakan listen(). Lebih mungkin pertanyaannya adalah tentang membukanya di firewall. Terlalu banyak kesalahan di sini, dan semuanya tidak diperbaiki dalam 7 tahun. Jawaban juga menghilangkan kasus pengikatan ke alamat lokal yang berbeda dengan nomor port yang sama. Ini sebenarnya sama sekali tidak benar.
Marquis of Lorne
27

Ya pasti . Sejauh yang saya ingat Dari kernel versi 3.9 (Tidak yakin pada versi) dan seterusnya dukungan untuk SO_REUSEPORTdiperkenalkan. SO_RESUEPORTmemungkinkan pengikatan ke port dan alamat yang sama persis, Selama server pertama menetapkan opsi ini sebelum mengikat soketnya.

Ini berfungsi untuk TCP dan UDP . Lihat tautan untuk detail lebih lanjut: SO_REUSEPORT

Catatan : Jawaban yang diterima tidak lagi berlaku menurut pendapat saya.

piyush
sumber
2
Sepenuhnya benar. Jika itu tidak benar, bagaimana Wireshark bisa bekerja?
Staszek
5
@Staszek Wireshark tidak mendengarkan port. Ini beroperasi pada tingkat paket.
Marquis of Lorne
Oh, itu masuk akal. Bagaimanapun, mendengarkan dua port dengan 2 aplikasi tentu saja mungkin.
Staszek
18

Tidak. Hanya satu aplikasi yang dapat mengikat ke port pada satu waktu, dan perilaku jika ikatan dipaksa tidak dapat ditentukan.

Dengan soket multicast - yang kedengarannya sama sekali tidak seperti yang Anda inginkan - lebih dari satu aplikasi dapat mengikat ke port selama SO_REUSEADDR diatur di setiap opsi soket.

Anda bisa menyelesaikan ini dengan menulis proses "master", yang menerima dan memproses semua koneksi, kemudian menyerahkannya ke dua aplikasi Anda yang perlu mendengarkan pada port yang sama. Ini adalah pendekatan yang diambil oleh server Web dan semacamnya, karena banyak proses perlu mendengarkan 80.

Di luar ini, kami sedang membahas spesifik - Anda menandai TCP dan UDP, yang mana? Juga, platform apa?

Jed Smith
sumber
keduanya menarik bagi saya. Platform ini adalah windows, tetapi jika jawabannya adalah berbeda untuk Linux, akan menyenangkan untuk mengetahui
nadiv
8
Tidak ada yang namanya soket multicast. Ada soket UDP. Multicast bukan prasyarat untuk SO_REUSEADDR.
Marquis of Lorne
3

Anda dapat memiliki satu aplikasi mendengarkan pada satu port untuk satu antarmuka jaringan. Karena itu Anda dapat memiliki:

  1. httpd mendengarkan pada antarmuka yang dapat diakses dari jarak jauh, mis 192.168.1.1:80
  2. daemon lain mendengarkan 127.0.0.1:80

Contoh use case bisa digunakan httpdsebagai load balancer atau proxy.

Tomas Tomecek
sumber
3

Cara lain adalah menggunakan program mendengarkan dalam satu port yang menganalisis jenis lalu lintas (ssh, https, dll) yang dialihkan secara internal ke port lain di mana layanan "nyata" mendengarkan.

Misalnya, untuk Linux, sslh: https://github.com/yrutschle/sslh

Mitchbcn
sumber
Apakah ada program seperti itu di windows? Saya perlu memiliki server IIS lokal saya dan broker ActiveMQ mendengarkan pada port 443
Harvey Lin
3

Saat Anda membuat koneksi TCP, Anda meminta untuk terhubung ke alamat TCP tertentu, yang merupakan kombinasi dari alamat IP (v4 atau v6, tergantung pada protokol yang Anda gunakan) dan port.

Ketika server mendengarkan koneksi, ia dapat memberitahu kernel bahwa ia ingin mendengarkan alamat IP dan port tertentu, yaitu, satu alamat TCP, atau pada port yang sama pada masing-masing alamat IP host (biasanya ditentukan dengan alamat IP 0.0.0.0), yang secara efektif mendengarkan banyak "alamat TCP" yang berbeda (mis 192.168.1.10:8000. 127.0.0.1:8000,, dll.)

Tidak, Anda tidak dapat memiliki dua aplikasi yang mendengarkan "alamat TCP" yang sama, karena ketika sebuah pesan masuk, bagaimana kernel tahu aplikasi mana yang memberikan pesan?

Namun, Anda di sebagian besar sistem operasi, Anda dapat mengatur beberapa alamat IP pada satu antarmuka (misalnya, jika Anda memiliki 192.168.1.10pada suatu antarmuka, Anda juga dapat mengatur 192.168.1.11, jika tidak ada orang lain di jaringan yang menggunakannya), dan dalam kasus tersebut Anda dapat memiliki aplikasi terpisah mendengarkan pada port 8000pada masing-masing dua alamat IP tersebut.

cjs
sumber
2

Jika setidaknya salah satu IP jarak jauh sudah dikenal, statis dan didedikasikan untuk berbicara hanya dengan salah satu aplikasi Anda, Anda dapat menggunakan aturan iptables (tabel nat, chain PREROUTING) untuk mengarahkan lalu lintas incomming dari alamat ini ke port lokal "shared" ke port lain di mana aplikasi yang sesuai benar-benar mendengarkan.

Stemar
sumber
1

Iya dan tidak. Hanya satu aplikasi yang dapat secara aktif mendengarkan pada port. Tetapi aplikasi itu dapat mewariskan koneksinya ke proses lain. Jadi Anda bisa memiliki beberapa proses yang bekerja pada port yang sama.

rajesh
sumber
@trusktr, saya pikir dia maksud ini
warvariuc
1

Iya.

Dari artikel ini:
https://lwn.net/Articles/542629/

Opsi soket baru memungkinkan beberapa soket pada host yang sama untuk mengikat ke port yang sama

pengguna6169806
sumber
1
Tautan yang bagus, namun jangan baris ini ditulis di sana - Opsi SO_REUSEPORT tidak standar
Sahil Singh
0

Jika dengan aplikasi yang Anda maksud beberapa proses maka ya tetapi umumnya TIDAK. Misalnya server Apache menjalankan beberapa proses pada port yang sama (umumnya 80). Hal ini dilakukan dengan menunjuk salah satu proses untuk benar-benar mengikat ke port dan kemudian menggunakan proses itu untuk melakukan penyerahan ke berbagai proses yang menerima koneksi.

nitinsh99
sumber
0

Anda dapat membuat dua aplikasi mendengarkan port yang sama pada antarmuka jaringan yang sama.

Hanya ada satu soket pendengar untuk antarmuka dan port jaringan yang ditentukan, tetapi soket itu dapat dibagi antara beberapa aplikasi.

Jika Anda memiliki soket pendengaran dalam proses aplikasi dan Anda forkproses itu, soket akan diwarisi, jadi secara teknis sekarang akan ada dua proses mendengarkan port yang sama.

warvariuc
sumber
0

Saya sudah mencoba yang berikut ini, dengan socat:

socat TCP-L:8080,fork,reuseaddr -

Dan meskipun saya belum membuat koneksi ke soket, saya tidak bisa mendengarkan dua kali pada port yang sama, terlepas dari reuseaddr opsi.

Saya mendapatkan pesan ini (yang saya harapkan sebelumnya):

2016/02/23 09:56:49 socat[2667] E bind(5, {AF=2 0.0.0.0:8080}, 16): Address already in use
aDoN
sumber
0

Hanya untuk membagikan apa yang @jnewton sebutkan. Saya memulai nginx dan proses tomcat tertanam pada mac saya. Saya bisa melihat kedua proses runninng di 8080.

LT<XXXX>-MAC:~ b0<XXX>$ sudo netstat -anp tcp | grep LISTEN
tcp46      0      0  *.8080                 *.*                    LISTEN     
tcp4       0      0  *.8080                 *.*                    LISTEN   
Amit Parashar
sumber
-2

Jawaban singkat:

Pergi dengan jawaban yang diberikan di sini . Anda dapat memiliki dua aplikasi mendengarkan pada alamat IP yang sama, dan nomor port, begitu lama salah satu port adalah port UDP, sementara yang lain adalah port TCP.

Penjelasan:

Konsep port relevan pada lapisan transport dari TCP / IP stack, sehingga selama Anda menggunakan protokol transport layer yang berbeda dari stack, Anda dapat memiliki banyak proses mendengarkan pada <ip-address>:<port> kombinasi yang .

Satu keraguan yang dimiliki orang adalah jika dua aplikasi berjalan pada <ip-address>:<port>kombinasi yang sama , bagaimana klien yang berjalan pada mesin jarak jauh membedakan antara keduanya? Jika Anda melihat header paket lapisan IP ( https://en.wikipedia.org/wiki/IPv4#Header ), Anda akan melihat bahwa bit 72 hingga 79 digunakan untuk mendefinisikan protokol, ini adalah bagaimana perbedaan dapat dibuat.

Namun jika Anda ingin memiliki dua aplikasi pada <ip-address>:<port>kombinasi TCP yang sama , maka jawabannya adalah tidak (Latihan yang menarik akan meluncurkan dua VM, berikan mereka alamat IP yang sama, tetapi alamat MAC yang berbeda, dan lihat apa yang terjadi - Anda akan memperhatikan bahwa beberapa kali VM1 akan mendapatkan paket, dan lain kali VM2 akan mendapatkan paket - tergantung pada penyegaran cache ARP).

Saya merasa bahwa dengan membuat dua aplikasi berjalan pada saat yang sama <op-address>:<port> Anda ingin mencapai semacam penyeimbangan beban. Untuk ini, Anda dapat menjalankan aplikasi pada port yang berbeda, dan menulis aturan tabel IP untuk membagi dua lalu lintas di antara mereka.

Juga lihat jawaban @ user6169806.

Sahil Singh
sumber