udp中的connect()&bind()

2023-05-16

connect()&bind()的作用

udp

udp connect()

 #include <sys/types.h>         
 #include <sys/socket.h>
 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

udp connect()描述

  1. connect系统调用将sockfd关联的套接字连接到addr指定的地址,如果sockfd是SOCK_DGRAM类型的,那么这个地址就是唯一数据报发送和接收地址
  2. 有链接的协议一般只能成功connect()一次,而无连接的协议可以多次connect()来改变sockfd与addr的联系

返回值

  1. 0,返回成功
  2. EACCES ,EPERM 用户试图链接到一个广播地址,但是相应的socket broadcast flag没有设置,或者是因为有本地防火墙
  3. EADDRINUSE 地址已经被使用
  4. EAFNOSUPPORT 传参的地址中的address family 与sa_family不匹配
  5. EBADF 文件描述符sockfd非法
  6. EINTR connect被signal中断

udp connect()特殊的一些地方

经试验发现,若发送端(客户端)不调用connect(),则发送异步错误时,进程很难知道发送了什么。若是调用connect(),其实际作用也与tcp中有较大不同。

  1. 调用connect()不会发包,内核只是检查是否有立即可知的错误,记录对端的ip&port,于是立即返回。但是这样一个socket就只能与一个ip进行交互(此处包括广播ip)
  2. connect()后,异步错误会被返回,在write()到一个不可达的进程时,对方将发送icmp,我方udp收到这个报文,并在下次准备read()这个套接字时,返回connection refused
  3. 一般而言,无连接的udp在发送数据时,内核中也是会做链接操作的,等数据发送完毕然后断开连接。这样其实效率较低,若是发送进程明确知道自己将于某个进程长时间通信,可以调用connect()来提高效率。【Partridge和Pink 1993】指出,临时链接的UDP套接字会耗费每个UDP传输1/3的开销

广播/多播(组播)

什么是多播

组播通过把224.0.0.0-239.255.255.255的D类地址作为目的地址,有一台源主机发出目的地址是以上范围组播地址的报文,在网络中,如果有其他主机对于这个组的报文有兴趣的,可以申请加入这个组,并可以接受这个组,而其他不是这个组的成员是无法接受到这个组的报文的。

局域网内多播时发生了什么

若局域网中有一个接收进程启动,并通过setsockopt()加入到某多播组。ipv4层内部会保存以上信息,并告知数据链路层接收特定目的地址以太网帧(通过组播ip到以太网地址的映射)。但是接口卡做的是不完备过滤,即接口卡也可能会接收目的地址为其他地址的以太网帧。但是ip层是完备的,它会比较目的ip。

有了以上内容,我们就知道若是某个组播成员(假设是A机)进程关闭了接收,或者他根本就没加入过组播。那么当发送进程再次发生组播时,A机实际上会忽略这个组播数据,既然忽略了,也不会发送icmp了。若是这个A机上有多个进程都加入了这个多播组,那单个套接字成员关系上的抹除,不影响A机继续作为该多播组的成员,直到最后一个套接字也离开该多播组。这种情况下调用connect,应该是connect到一个组播地址。

如何加入到组播

int setsockopt(int sockfd,int level,int optname,void* optval,socklen_t optlen)

optnamedataTypefunction
IP_ADD_MEMBERSHIPstruct ip_mreqenter a group
IP_ADD_SOURCE_MEMBERSHIPstruct ip_mreq_sourceenter a SSM
IP_BLOCK_SOURCEstruct ip_mreq_sourceblock a source

以源特定组播为例

  1. 假设组播IP是GROUP

  2. 按惯例,建立socket,填充好port,sin_family.

  3. inet_aton(GROUP,&serv.sin_addr);
    inet_aton(GROUP,&mreq.imr_multiaddr);
    inet_aton(yourInterfaceIP,&(mreq.imr_interface));
    inet_aton(sourceIP,&(mreq.imr_sourceaddr));
    setsockopt(sockfd,SOL_IP,IP_ADD_SOURCE_MEMBERSHIP,&mreq,sizeof(mreq))
  4. 第一条语句的意思是接收进程的地址要设置成组播IP,第二至第四条语句的意思是要填充一个 struct ip_mreq_source结构。这个结构三个成员,分别是组播地址,本机一个接口的IP,以及多播发送方的IP

  5. setsockopt第三个参数指明这是加入源特定组播,第四个是上面说的结构体指针,第五个是它的长度

  6. 当optname是IP_ADD_MEMBERSHIP时,填充struct ip_mreq,这个结构体没有imr_sourceaddr成员

connect到多播ip的一个事实

UNP1上说可以connect到一个多播ip,我在把cli发送进程做了这样的设置。但是令人奇怪的是,我的发送程序再也收不到来自接收ser的任何信息。后来仔细翻UNP,发现上面说“目的地为为这个已连接UDP套接字的本地协议地址,发源地却不是该套接字早先connect到的协议地址的数据报,不会投递到该套接字,这样就限制了已连接套接字能且仅能与一个对端交换数据”。这个事实印证了这个说法。udp调用connect()需要付出这样的代价。

bind()以及REUSE_ADDR、REUSE_PORT功能

见下,非常详细

http://blog.csdn.net/yaokai_assultmaster/article/details/68951150

有待解决

此次试验在一台机子上进行,多播试验,发送端未做特殊设置,接收端设置IP_ADD_MEMBERSHIP。一开始观察到发送进程未bind()时,接收可以收到数据,但是却显示源地址是0.0.0.0。后发送端加上bind(),接收端依旧显示源地址是0.0.0.0。

后改变接收端设置,变为IP_ADD_SOURCE_MEMBERSHIP,并填上多播的源地址192.168.1.136。此时再测试,发现接收端依旧显示源地址是0.0.0.0。后发现当第二次启动发送端程序发送多播时,接收端显示源地址是192.168.1.136。于是我修改发送端程序,让他不再recv 接收端的回复,而是只发送数据。我发现第一次发生数据时,接收端总是不能得到发送端的源地址,但是第二次发送数据后,接收端就能知道源地址了。

TCP

三路握手

  1. tcp的稳定连接靠的是三路握手,而三路握手由connect(),accept()完成
  2. 服务器必须准备好接受外来的连接,这通常通过调用socket,bind,listen来完成
  3. 客户通过调用connect发起主动连接,这导致客户发送一个syn分节,它告诉服务器客户将发送的数据的初始序列号。
  4. 服务器则必须确认这个SYN,并发送ACK,同时自己也要发送一个SYN,这个SYn含有服务器发送数据的初始序列号,当这个ACK/SYN到达客户端时,connect()返回
  5. 客户发送对服务器发来的SYN的ACK,服务器收到这个ack后即从accept返回
  6. 三路握手完成

TCP连接终止

  1. TCP终止一个链接需要4个分节,因为终止是双边的,每一边两个分节,也就是说TCP可以存在半关闭状态
  2. 某进程先调用close(),他是主动关闭方,它将发送一个fin分节,这仅仅表示这个进程告诉对方他的数据已经发送完毕,不代表这个进程不能继续收数据
  3. 若另外一边也认为他的数据发送完毕,则也会调用close()发送fin分节
  4. 每个fin分节都需要被ACK

TIME_WAIT

  1. TIME_WAIT是主动执行关闭的那端的最后一个网络状态。停留在这个状态的时间是2MSL
  2. 这个状态存在有两个必要的理由,可靠的实现全双工连接的终止,让老的分组在网络中消逝
  3. 对于第一个理由,假设主动发起关闭的那端在收到被动关闭端来的fin后,发送对这个fin的ACK,然而这个ACK丢失了。则被动关闭方会重传一个FIN,这时,若是没有TIME_WAIT状态,主动关闭方在发完最后一个ACK后就不再维护状态信息,则此时被动关闭方重发的FIN到达,则主动关闭方将对这个FIN分节回应一个RST,这将被被动关闭方解释为一个错误。
  4. 对于第二个理由,若是一个链接终止后,但是网络上还有这个链接没有到达的分组,此时若是快速的启动一个新的链接,他的ip和port都和旧的一样,那万一这个旧的分组在此时到达,则会被新的连接误收。所以为了让旧的分组消逝,有必要等待一个较长的时间。

bind()

如果SO_REUSEADDR选项没有被设置,处于TIME_WAIT阶段的socket任然被认为是绑定在原来那个地址和端口上的。直到该socket被完全关闭之前(结束TIME_WAIT阶段),任何其他企图将一个新socket绑定该该地址端口对的操作都无法成功。这一等待的过程可能和延迟等待的时间一样长。所以我们并不能马上将一个新的socket绑定到一个刚刚被关闭的socket对应的地址端口对上。在大多数情况下这种操作都会失败。

然而,如果我们在新的socket上设置了SO_REUSEADDR选项,如果此时有另一个socket绑定在当前的地址端口对且处于TIME_WAIT阶段,那么这个已存在的绑定关系将会被忽略。事实上处于TIME_WAIT阶段的socket已经是半关闭的状态,将一个新的socket绑定在这个地址端口对上不会有任何问题。这样的话原来绑定在这个端口上的socket一般不会对新的socket产生影响。但需要注意的是,在某些时候,将一个新的socket绑定在一个处于TIME_WAIT阶段但仍在工作的socket所对应的地址端口对会产生一些我们并不想要的,无法预料的负面影响。但这个问题超过了本文的讨论范围。而且幸运的是这些负面影响在实践中很少见到。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

udp中的connect()&bind() 的相关文章

  • Android 上的 UDP 视频流

    我有一个 Android 项目 需要构建一个客户端应用程序来接收 UDP 或 RTP 单播视频流并播放它们 不幸的是 我似乎无法使其正常工作 并且已经广泛搜索了解决方案 我已经在 Xoom Android 3 2 和 Nexus S And
  • 数据报总是被完整接收吗?

    大多数数据报接收函数 例如c的recv或read java的DatagramPacket类或python的SocketServer 都包含找出接收数据量的可能性 c int amount recv sock buf n MSG WAITAL
  • NTP请求包

    我试图弄清楚我需要在 NTP 请求包中发送 客户端 什么才能从服务器检索 NTP 包 我正在 Cortex M3 Stellaris LM3S6965 上使用 LWIP 据我了解 我将收到 UDP 标头 然后收到具有不同时间戳的 NTP 协
  • jQuery:将 ajaxForm 绑定到通过 .load() 加载的页面上的表单

    我正在使用 jQuery 的 ajaxForm 插件在我的 web 应用程序上提交表单 然而 在应用程序的一部分中 我通过 jQuery 的 load 加载一些带有表单的内容 问题在于我无法让 ajaxForm 绑定到通过 ajax 加载的
  • udp数据包被tcpdump捕获,但没有被套接字接收[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我编写了一个 rawudp 程序 通过原始套接字发送 udp 数据包 按照网页http www tenouk com Module43a html h
  • 错误的 UDP 校验和没有效果:为什么?

    我正在尝试测试 UDP 程序 如果它接收到 UDP 校验和错误的数据 会发生什么情况 奇怪的是 它似乎没有任何效果 并且有效负载被成功接收 至少在 OS X 上是通过环回接口成功接收的 下面是一个示例 其中使用以下方式发送数据SOCK RA
  • java: 不使用时绑定异常地址使用错误(如netstat所示)

    我的应用程序使用特定的源端口与服务器建立出站连接 考虑到防火墙问题 强化的系统可能需要提前指定端口 我的问题是我的应用程序最初建立连接 但是 如果连接中断 它将重试 但套接字将收到 BindException 指出 地址正在使用 事实并非如
  • 通过 Internet 发送 UDP 数据包

    我正在尝试了解 P2P 去中心化网络的一些细节 我的问题如下 假设我有两台名为 comp1 和 comp2 的机器 现在 comp1 设置在我的家庭网络中的路由器后面 comp2 位于我的办公室中 也位于路由器后面 我是否可以像这样在 In
  • 为什么UDP服务器上的UDP客户端端口会改变

    我一直在关注一个简 单的 UDP 服务器 客户端教程 发现here http www binarytides com udp socket programming in winsock 我有一个关于客户端连接到服务器的端口的快速问题 仅从代
  • 接收来自 N 个客户端的响应,以回复通过 UDP 的广播请求

    我正在为特定类型的网络多媒体设备实现一种 IP 查找器 我想找出 LAN 中该类型的所有活动设备及其 IP 地址和其他详细信息 设备有自己的设备发现方式 其工作原理如下 客户端通过 UDP 通过 LAN 发送广播请求 目的端口号是固定的 作
  • 如果Service在另一个进程中,如何绑定它?

    显现
  • 如何监听任意端口的广播包?

    使用 NET 如何在任何端口上侦听发送到 255的udp广播数据包 而不需要绑定到特定端口 我自己找到了办法 它是这样工作的 mainSocket new Socket AddressFamily InterNetwork SocketTy
  • 带有 rpi 主站和从站的 Profibus [关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 我的任务是使用 Rpi 和 Rs 485 转换器构建 profibus 主站和从站网络 一个 Rpi 将成为主设备 另一个将成为从设备
  • C# 广播是UDP消息,监听多个回复

    我正在尝试编写一些执行 UDP 广播的代码 然后侦听来自远程服务器的答复 说明它们存在 它用于识别子网上运行服务器应用程序的计算机 因此基本上会发出 谁在那儿 并听取所有答复 我在 Java 中有这个 工作完美 它将 DatagramPac
  • 努力绑定 tkinter 文本小部件中的标签

    我在 tkinter 模块中的文本小部件上遇到了一些困难 我添加了尝试将函数绑定到的标签 无论我如何输入 它都会发生以下两种情况之一 我可以单击文本小部件 但弹出的唯一功能是最后一个项目 无论我单击何处 第二件事是它会自动输出所有功能 对原
  • 与 INADDR_ANY 绑定

    如果我将套接字绑定到 INADDR ANY 我知道它将接受服务器上配置的任何 IP 上的传入连接 假设我在进行 bind 调用时配置了 1 个 IP 然后配置了一个新的 IP bind 是否也会接受向新配置的 IP 发起的连接 还是仅适用于
  • 在 Perl 中如何接受多个 TCP 连接?

    我对 Linux 的 Perl 脚本有疑问 它的主要目的是成为 3 个应用程序之间的中间人 它应该做什么 它应该能够等待 UDP 文本 不带空格 udp port 当它收到 UDP 文本时 它应该将其转发到连接的 TCP 客户端 问题是我的
  • 接收UDP数据包

    假设我的程序通过网络 UDP 发送 1000 字节 它是否保证接收方将 一批 接收 1000 个字节 或者他可能需要执行多次 读取 直到收到完整的消息 如果后者为真 我如何确保同一消息的数据包顺序不会 混淆 按顺序 或者协议可能保证这一点
  • 提高UDP可靠性

    我正在构建一个基于 UDP 的小型服务器 服务器基于 Net并使用它自己的Socket类 我通过 ReceiveMessageFromAsync 和异步发送使用完成端口 我的问题是我失去了大约 5 10 的流量 现在我明白这是正常的 但是有
  • P2P网络游戏/应用程序:类似“战网”匹配服务器的不错选择

    我正在制作一个网络游戏 1v1 游戏中是 p2p 不需要游戏服务器 然而 为了让玩家能够 找到彼此 而不需要在另一种媒介中协调并输入IP地址 类似于网络游戏的现代时代 我需要有一个协调 匹配服务器 我无法使用常规网络托管 因为 客户端将使用

随机推荐