[英]udp socket sendto implicit bind
我在這里查看udp客戶端示例: http : //www.linuxhowtos.org/data/6/client_udp.c
片段:
/* UDP client in the internet domain */
struct sockaddr_in server, from;
//...snipped
sock= socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) error("socket");
server.sin_family = AF_INET;
hp = gethostbyname(argv[1]);
if (hp==0) error("Unknown host");
bcopy((char *)hp->h_addr,
(char *)&server.sin_addr,
hp->h_length);
server.sin_port = htons(atoi(argv[2]));
length=sizeof(struct sockaddr_in);
//... snipped
n=sendto(sock,buffer,
strlen(buffer),0,(const struct sockaddr *)&server,length);
if (n < 0) error("Sendto");
n = recvfrom(sock,buffer,256,0,(struct sockaddr *)&from, &length);
if (n < 0) error("recvfrom");
//... snipped
我試圖了解它如何知道從何處接收消息。 我知道何時調用sendto
時,會選擇一個可用端口並將其嵌入udp消息中,服務器應用程序可以讀取並回復它。 客戶端代碼如何知道在該端口上接收消息?
這個答案: https : //stackoverflow.com/a/48245273/2748602表示在調用sendto
函數時存在某種隱式綁定。 它是如何工作的? 實際上,它是一個具有隨機可用端口號的綁定,該端口號是否永久不變,就像我曾叫過bind
一樣? 似乎存在永久性的某些方面。 只對更多細節感興趣。
有一個隱含的綁定,如果未綁定套接字,因為所有的數據包必須攜帶兩個源端口。 因此,API假定,如果您對端口預先綁定的端口並不十分在意,則可以將套接字綁定到隨機端口。 不幸的是,盡管我不知道sendto
的實現細節,但我可以提供一些官方文檔。
對於Linux,請從udp手冊頁 :
創建UDP套接字時,未指定其本地和遠程地址。 可以使用sendto(2)或sendmsg(2)(以有效的目標地址作為參數)立即發送數據報。 在套接字上調用connect(2)時,將設置默認目標地址,並且現在可以使用send(2)或write(2)發送數據報,而無需指定目標地址。 通過將地址傳遞給sendto(2)或sendmsg(2),仍然可以發送到其他目標。 為了接收數據包,可以先使用bind(2)將套接字綁定到本地地址。 *否則,套接字層將自動分配超出/ proc / sys / net / ipv4 / ip_local_port_range定義的范圍的空閑本地端口,並將套接字綁定到INADDR_ANY 。
對於Windows,請參閱Winsock 2 sendto文檔中的摘錄:
如果套接字未綁定,則系統會將唯一值分配給本地關聯,然后將套接字標記為bound 。 如果已連接套接字,則可以使用getsockname函數來確定與套接字關聯的本地IP地址和端口。
...調用sendto函數時,存在一種隱式綁定。 它是如何工作的? 實際上,它是一個具有隨機可用端口號的綁定,該端口號是否永久不變,就像我曾叫過bind一樣?
ip_local_port_range (since Linux 2.2)
This file contains two integers that define the default local
port range allocated to sockets that are not explicitly bound
to a port number—that is, the range used for ephemeral ports.
An ephemeral port is allocated to a socket in the following
circumstances:
* the port number in a socket address is specified as 0 when calling bind(2);
* listen(2) is called on a stream socket that was not previously bound;
* connect(2) was called on a socket that was not previously bound;
* sendto(2) is called on a datagram socket that was not previously bound.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.