典型的UDP客户/服务器程序的函数调用如下:

1、缓冲区

发送缓冲区用虚线表示,任何UDP套接字都有发送缓冲区,不过该缓冲区仅能表示写到该套接字的UDP数据报的上限。如果应用进程写一个大于套接字缓冲区大小的数据报,将会返回该进程一个EMSGSIZE错误。从写一个UDP套接字的write调用成功返回,表示所写的数据报或其所有的片段已被加入到数据链路层的输出队列。如果该队列没有足够的空间存放该数据报或它的某个片段,内核通常会返回一个ENOBUFS错误给它的应用进程。

2、相关函数

  • recvfrom()和sendto()
ssize_t sendto (int sockfd, void *buf, size_t bytes,
               int flags, const struct sockaddr* to,
               socklen_t *addrlen);
ssize_t recvfrom (int sockfd, void *buf, size_t nbytes,
             int flags, struct sockaddr* from,
             socklen_t *addrlen);
  • recvfrom():
    • from:指向一个将由该函数在返回时填写数据报发送者协议地址的套接字地址结构
    • addrlen:在from指向的套接字结构中的填写的字节数。
  • sendto():
    • to:指向一个含有数据报接收者的协议地址的套接字地址结构
    • addrlen:to指向的套接字地址结构大小。

recvfrom()的from参数可以是一个空指针,那么相应的长度参数也应该是一个空指针,表示不在意数据发送者的协议地址。写一个长度为0的数据报是可行的,在UDP情况下,这会形成一个只包含一个IP首部(对于IPv4是20字节,对于IPv6而言是40字节)和一个8字节UDP首部而没有数据的IP数据报。意味着对于数据报协议,recvfrom返回0值是可以接受的,不像TCP套接字上read返回0值那样表示对端已关闭连接。既然UDP是无连接的,因此也就没有诸如关闭一个UDP连接之类的事情

接收缓冲:UDP中隐有排队现象发生。事实上每个UDP套接字都有一个接受缓冲区,到达该套接字的每个数据报都进入这个套接字接受缓冲区 。当进程调用recvfrom的时候,缓冲区的下一个数据报以FIFO的顺序回传给进程。这样,在进程能够读该套接字中任何已排好队的数据报之前,如果有多个数据报到达该套接字,那么相继到达的数据报仅仅加到该套接字的接收缓冲区中。这个缓冲区的大小是有限的。

对于一个UDP套接字,如果其进程首次调用sendto的时候,它没有绑定一个本地端口,那么内核就在此时为它选择一个临时端口。

上图中的圆点指明了客户发送UDP数据报的时候,必须指定或选择的四个值

  • 客户必须给sendto调用指定的服务器的IP地址和端口
  • 客户的IP地址和端口号可以指定也可以不指定。
    • 如果客户没有捆绑具体的IP和端口号,内核会自动选择
      • IP地址却可以随客户发送的每个UDP数据报而变动
      • 临时端口是在第一次调用sendto时一次性选定,不能改变
    • 如果客户绑定了一个IP地址
      • 在这种情况下,如果内核决定外出数据报必须从另一个数据链路发出,IP数据报将会包含一个不同于外出链路IP地址的源IP地址

在一个未绑定端口号和IP地址的UDP套接字上调用connect的时候,会给套接字指派一个IP地址和临时端口

TCP和UDP服务器指定获取源IP,源端口号,目的IP和目的端口号的方法:

来自客户端的IP数据报 TCP服务端 UDP服务端
源IP地址 accept recvfrom
源端口号 accept recvfrom
目的IP地址 getsockname recvmsg
目的端口号 getsockname getsockname
  • 非连接状态下,同一套接字可以给多个服务器发送数据报
  • 服务器上的同一个套接字可以从若干不同客户端接收数据

2、连接的UDP套接字

#include <sys/socket.h>
itn connect(itn sockfd, const struct sockaddr*servaddr,socklen_t addrlen);
  • sockfd,客户端套接字描述符
  • servaddr,包含服务器IP地址和端口号的套接字地址结构
  • addrlen,套接字地址结构的大小

给UDP套接字调用connect并不会像TCP一样出发三次握手,内核只是检查是否存在立即可知的错误,记录对端的IP地址和端口号,然后立即返回

已连接的UDP套接字和未连接的UDP套接字存在3个不同:

  • 限制了一个已连接套接字能且仅能与一个对端交换数据
    • 不能再给输出操作指定目的IP地址和端口号,即不使用sendto而改用write或send
    • 不必使用recvfrom以获悉数据报的发送者,而改用read、recv或recvmsg
  • 接收异步错误
    • 由已连接UDP套接字引发的异步错误会返回给它们所在的进程。未连接时不接收任何异步错误

一个拥有已连接UDP套接字的进程,可出于下列2个目的再次调用connect:

  • 指定新的IP地址和端口号
  • 断开套接字:调用connect时,把套接字地址结构的地址族成员设置为AF_UNSPEC。

TCP要再次调用connect必须先close套接字然后再重新调用socket创建套接字描述符。

连接与不连接的性能:当应用进程在一个未连接的UDP套接字上调用sendto时,源自Berkeley的内核暂时连接该套接字,发送数据报,然后断开该连接。因此,当应用进程要给同一目的地址发送多个数据报时,使用连接套接字可以获得更高的效率

<unix网络编程>UDP套接字编程的更多相关文章

  1. 《Unix 网络编程》08:基本UDP套接字编程

    基本UDP套接字编程 系列文章导航:<Unix 网络编程>笔记 UDP 概述 流程图 recvfrom 和 sendto #include <sys/socket.h> ssi ...

  2. 【Unix网络编程】chapter8基本UDP套接字编程

    chapter8基本UDP套接字编程 8.1 概述 典型的UDP客户端/服务端的函数调用 8.2 recvfrom和sendto函数 #include <sys/socket.h> ssi ...

  3. 【Python网络编程】利用Python进行TCP、UDP套接字编程

    之前实现了Java版本的TCP和UDP套接字编程的例子,于是决定结合Python的学习做一个Python版本的套接字编程实验. 流程如下: 1.一台客户机从其标准输入(键盘)读入一行字符,并通过其套接 ...

  4. 探索UDP套接字编程

    UDP和TCP处于同一层网络模型中,也就是运输层,基于二者之上的应用有很多,常见的基于TCP的有HTTP.Telnet等,基于UDP有DNS.NFS.SNMP等.UDP是无连接,不可靠的数据协议服务, ...

  5. 【转】 探索UDP套接字编程

    UDP和TCP处于同一层网络模型中,也就是运输层,基于二者之上的应用有很多,常见的基于TCP的有HTTP.Telnet等,基于UDP有DNS.NFS.SNMP等.UDP是无连接,不可靠的数据协议服务, ...

  6. 初探网络编程--TCP套接字编程演示

    今天看了一下<计算机网络:自顶向下方法>,也就是计算机网络的教材的应用层一章,决定实现以下后面的Java C/S应用程序的例子,用来演示TCP和UDP套接字编程. 程序流程如下: 1.一台 ...

  7. JavaTCP和UDP套接字编程

    在我们刚开始入门Java后端的时候可能你会觉得有点复杂,包含了很多杂七杂八的知识,例如文件上传下载,监听器,JDBC,请求重定向,请求转发等等(当然也没有很多),但是我们自己真正的去开发一个小型网站( ...

  8. TCP和UDP套接字编程 (java实现)

    在了解网络编程之前,我们先了解一下什么叫套接字 套接字即指同一台主机内应用层和运输层之间的接口 由于这个套接字是建立在网络上建立网络应用的可编程接口 因此也将套接字称为应用程序和网络之间的应用程序编程 ...

  9. 计算机网络实验 UDP套接字编程

    这是个傻瓜式操作教程 西科大计算机网络实验 UDP套接字编程 我用自己的Ubuntu16.04来举例,实验室的是虚拟机,差不多 只针对第三个题目,修改服务器来通过响应客户端发送的GetTime并发送给 ...

随机推荐

  1. elementUI vue 编辑中的input的验证残留清除

    当使用编辑的时候, 假如上次的验证没通过, 报红了, 下次再点击编辑的时候还会报红,因此要清除验证残留, 方式有两种: this.$refs["from"].resetFields ...

  2. CF607B Zuma(区间dp)

    题意 题目链接 Sol 裸的区间dp,转移的时候判一下两个字符是否相等即可 #include<bits/stdc++.h> #define Pair pair<int, int> ...

  3. finally知识讲解

    finally语句一定会执行吗,很多人认为一定会,其实未必,只有与 finally 相对应的 try 语句块得到执行的情况下,finally 语句块才会执行.假如在try语句之前执行了return操作 ...

  4. Android studio 下的SDK Manager只显示已安装包的情况

    原因是连接不上Google的更新服务器: 解决方法: 选择第三个Options: 修改Http Proxy Server: mirrors.neusoft.edu.cn Http Proxy Port ...

  5. Android为TV端助力 handler传递消息机制

    当工作线程给主线程发送消息时,因为主线程是有looper的,所以不需要初始化looper,注意给谁发消息就关联谁的handler,此时用的就是主线程的handler handler会把消息发送到Mes ...

  6. NoHttp封装--06 NoHttp之队列、队列优先级

    public class Main { /** * 程序入口 */ public void start() { // 第一种,先进先出的队列 // YolandaLinkedQueue queue = ...

  7. JAVA设计模式——代理(静态代理)

    定义 为其它的对象提供一种代理,以控制这个对象的访问 使用场景 当不想直接访问某个对象的时候,就可以通过代理 1.不想买午餐,同事帮忙带 2.买车不用去厂里,去4s店 3.去代理点买火车票,不用去车站 ...

  8. Hive内部表与外部表的区别

    1.未被external修饰的是内部表[managed table],被external修饰的为外部表[external table]. 2.内部表数据由Hive自身管理,外部表数据由HDFS管理. ...

  9. Scala视图界定

    package big.data.analyse.dataSet /** * 视图界定 * Created by zhen on 2018/11/29. */ /*class Pair_NotPerf ...

  10. java----鲁棒性

    所谓“鲁棒性”,是指控制系统在一定(结构,大小)的参数摄动下,维持其它某些性能的特性. Java鲁棒性的特点如下: Java在编译和运行程序时都要对可能出现的问题进行检查,以防止错误的产生. Java ...