Sunucu hangi istemci portuna gönderileceğini nasıl bulur?


26

Anladığım kadarıyla, bir müşteri bir bağlantı isteği yaptığında ne olur:

  1. Sunucu belirli bir port numarasına bağlı olacaktır. Port numarası daima bir dinleme işlemine bağlıdır. Yalnızca sunucu gelen bağlantıları dinliyor olduğundan, istemci tarafında bağlanmamız gerekmez.
  2. Sunucu bu port numarasını dinlemeye devam edecektir.
  3. Müşteri bir connect()istek gönderecek .
  4. Sunucu, isteği kullanarak kabul eder accept(). En kısa sürede sunucu istemci isteği, daha ileri için sunucu için rasgele bir port numarası çekirdek ayırır kabul etmesi send()ve receive()sunucuda aynı port numarası dinleme yanı sıra göndermek için kullanılamaz çünkü, ve önceki limanda hala yeni bağlantılar için dinleme

Tüm bunlar göz önüne alındığında, sunucu müşterinin hangi bağlantı noktasını aldığını nasıl öğrenir? İstemcinin bir kaynak portu ve hedef portu olan TCP segmentleri göndereceğini biliyorum, bu yüzden sunucu bu segmentin kaynak portunu hedef portu olarak kullanacak, fakat sunucu bu portu bulmak için hangi işlevi çağırıyor? Öyle mi accept()?


Yanıtlar:


33

Paketteki TCP (veya UDP vb.) Başlığının bir parçasıdır. Böylece sunucu bunu anlar çünkü müşteri bunu söyler. Bu, istemcinin IP adresini (IP başlığının bir parçası olan) nasıl bulduğuna benzer.

Örneğin, her TCP paketi bir IP başlığı içerir (en azından kaynak IP, hedef IP ve protokol [TCP] ile). Sonra bir TCP başlığı var (kaynak ve hedef portu ile artı daha fazlası).

Çekirdek 10.11.12.13'lük bir uzak IP'ye (IP başlığında) ve 12345 uzak bir bağlantı noktasına (TCP başlığında) sahip bir SYN paketi (TCP bağlantısının başlangıcı) aldığında, uzak IP ve bağlantı noktasını bilir. . Bir SYN | ACK geri gönderir. Bir ACK geri alırsa, listençağrı bu bağlantı için ayarlanmış yeni bir soket döndürür.

Bir TCP soketi, dört değerle (uzak IP, yerel IP, uzak bağlantı noktası, yerel bağlantı noktası) benzersiz olarak tanımlanır. Bunlardan en az biri farklı olduğu sürece, birden fazla bağlantıya / sokete sahip olabilirsiniz.

Genellikle, yerel bağlantı noktası ve yerel IP, bir sunucu işlemine yapılan tüm bağlantılar için aynı olacaktır (örneğin, sshd'ye yapılan tüm bağlantılar yerel-ip: 22'de olacaktır). Bir uzak makine birden çok bağlantı yaparsa, her biri farklı bir uzak bağlantı noktası kullanır. Öyleyse uzaktaki bağlantı noktası dışındaki her şey aynı olacak, ama sorun değil - dördünden sadece biri farklı olmalı.

Paketi görmek için, örneğin, wirehsark'ı kullanabilirsiniz, ve sizin için tüm verileri etiketleyecektir. Vurgulanan kaynak portu aşağıdadır (kodun altındaki pakette ve altta bulunan altıgen boşaltmada vurgulandığına dikkat edin):

Bir TCP SYN paketi gösteren Wireshark


> Açıklama için teşekkürler. Kabul etmeden sonra elde edilen yeni sunucu soketi tanımlayıcısının (örn. Tuple), müşteri portu ve müşteri adres detaylarına sahip olacağını ve bu yeni soket tanımlayıcı sunucusunu kullanarak verileri gönderip aldığını ve client.New soket dosya tanımlayıcısında çekirdek, sunucu ip, istemci ip ve istemci portu tarafından atanan yeni bir sunucu port numarası olacak. Doğru mu?
Subi Suresh,

@SubiSuresh evet, demet, o dosya tanımlayıcısıyla ilişkilendirilmiş olan çekirdek içinde saklanır.
derobert

> Teşekkürler derobert.Yani yeni sunucu soketi tanımlayıcısının, sunucunun kabul etmekten aldığı müşteri portu ve müşteri adresi olacağı sonucuna varıyorum () Anlayışım doğru mu?
Subi Suresh,

@SubiSuresh Evet, doğru. Bir uygulama açısından, genellikle umursamıyorsunuz (günlük kaydı dışında). Çekirdek, sizin write(vb.) Verilerin doğru yere gitmesini sağlar.
derobert

> yardımın için teşekkürler ve sanırım bir şey anladım. ;-)
Subi Suresh

2

"Connect isteği (istemci programının connect()sistem çağrısı, genellikle) üç yollu bir el sıkışmasına neden olur. 3 yollu el sıkışmasının ilk paketi (istemciden sunucuya) SYN bayrağına sahiptir ve istemci programın TCP port numarasını içerir. çekirdek ona atar.

Bunu Nmap vs Natural SYN paketleri hakkındaki bir makalede görebilirsiniz . Nmap SYN paket kod çözme işlemi "source.60058> dest.22" cümlesine sahiptir. "Meşru SYN paketi" kod çözme içinde "kaynak.35970> dest.80" ibaresi vardır. İki SYN paketi, uzak çekirdeğe paketlerin sırasıyla TCP580058 ve 35970 numaralı portlardan olduklarını söyler.


> Ama arka uçta Bruce var.Ama benim sunucu aslında istemci sunucu programlarında bağlantı noktası numarası gibi ayrıntıları gerçekten alıyor, ancak istemci bağlantı noktası ve istemci adresini almak için herhangi bir işlev görmedim
Subi Suresh

Sistem çağrısı getpeername(), herhangi bir açık sokette yapmanıza izin vermelidir. accept()Sunucu kodu istemciye geri iletişim kurmak için bir soket dosya tanımlayıcısı almak için kullanmak zorunda olduğu sistem çağrısı müstakbel müşterinin IP adresini ve TCP port numarasını içerir (adamım sayfalarında "sockaddr") bir parametre var.
Bruce Ediger

> Lütfen unutursam sakıncası yoksa. Aldığım tüm girdilerden, kabul etmenin () yapının sockaddr_in yapısına sahip olduğunu ve kabul edildikten sonra döndürülen yeni sunucu soketi tanımlayıcısının otomatik olarak istemci bağlantı noktasına ve adrese sahip olacağını anladım. Bu yüzden send (yeni sunucu soketi tanımlayıcısı) kullanarak göndermeyi başarabiliyoruz. Umarım, noktaya değindim mi? Bu sadece anladığım şeyin doğru olduğundan emin olmak için.
Subi Suresh,

@ SuiSures - Ben doğru yazdığına inanıyorum.
Bruce Ediger

1

TCP soketi, akış yönelimli bir sokettir. İki soket tanımlayıcısı (size ve eşinize ait) güvenilir bir şekilde bağlanmıştır. Yani müşterinin portu hakkında endişelenmenize gerek yok - sadece soket tanımlayıcınızı yazın!

Ayrıca, gerçekten bilmek istiyorsanız (belki günlüğe kaydetme için) getsockname (2) 'yi kullanmaktan çekinmeyin.


0

Bağlantı bir tuple ile tanımlanır (kaynak IP, kaynak bağlantı noktası, hedef IP, hedef bağlantı noktası). Cevaplar tam tersi.


@ vondrand Bu noktayı von anlıyorum. Fakat hangi fonksiyondan sunucu istemci port numarası hakkında bilgi edinmeye başlıyor? Liman ?
Subi Suresh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.