(UNIX网络编程学习笔记):UDP概述、recvfrom和sendto函数及案例
目录
概述
recvfrom和sendto函数
UDP回射服务器程序示例
UDP回射客户端程序示例
概述
- UDP应用:DNS(域名系统)、NFS(网络文件系统)和SNMP(简单网络管理协议)
【UDP客户/服务器程序的函数调用】
- 客户端不与服务器建立连接,而是只管使用sendto函数给服务器发送数据报,其中必须指定目的地(即服务器)的地址作为参数。
- 服务器不接受来自客户的连接,而是只管调用recvfrom函数,等待来自某个客户的数据到达。
- recvfrom将与所接收的数据报一道返回客户的协议地址,因此服务器可以把响应发送给正确的客户。
recvfrom和sendto函数
- 类似于标准的read和write函数,不过需要三个额外的参数。
#include <sys/socket.h>ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags, struct sockaddr *from, socklen_t *addrlen);ssize_t sendto(int sockfd, const void *buff, size_t nbytes, int flags, const struct sockaddr *to, socklen_t *addrlen);
- 返回值:若成功则为读或写的字节数,若出错则为-1。
- 参数:
- sockfd、buff和nbytes:描述符、指向读入或写出缓冲区的指针和读写字节数。
- flags一般置为0。
- recvfrom的from参数指向一个将由该函数在返回时填写数据报发送者的协议地址的套接字地址结构,而在该套接字地址结构中填写的字节数则放在addrlen参数所指的整数中返回给调用者。
- sendto的to参数指向一个含有数据报接收者的协议地址(例如IP地址及端口号)的套接字地址结构,其大小由addrlen参数指定。
- 注意:
- sendto的最后一个参数是一个整数值,而recvfrom的最后一个参数是一个指向整数值的指针(即值-结果参数)。
- recvfrom的最后两个参数类似于accept的最后两个参数:
- 返回时其中套接字地址结构的内容告诉我们是谁发送了数据报(UDP)或是谁发起了连接(TCP)。
- sendto的最后两个参数类似于connect的最后两个参数:
- 调用时其中套接字地址结构被我们填入数据报将发往(UDP)或与之建立连接(TCP)的协议地址。
- 这两个函数都把所读写数据的长度作为函数返回值。在recvfrom使用数据报协议的典型用途中,返回值就是所接收数据报中的用户数据量。
- 写一个长度为0的数据报是可行的。在UDP情况下,这会形成一个只包含一个IP首部(对于IPv4通常为20个字节,对于IPv6通常为40个字节)和一个8字节UDP首部而没有数据的IP数据报。
- 如果recvfrom的from参数是一个空指针,那么相应的长度参数(addrlen)也必须是一个空指针,表示我们并不关心数据发送者的协议地址。
UDP回射服务器程序示例
【示例】
#define SERV_PORT 9877 #define MAXLINE 4096void dg_echo(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen) {int n;socklen_t len;char mesg[MAXLINE];for ( ; ; ) {len = clilen;n = Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);Sendto(sockfd, mesg, n, 0, pcliaddr, len);} }int main(int argc, char **argv) {int sockfd;struct sockaddr_in servaddr, cliaddr;sockfd = Socket(AF_INET, SOCK_DGRAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);Bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));dg_echo(sockfd, (struct sockaddr *) &cliaddr, sizeof(cliaddr)); }
- socket函数的第二个参数指定为SOCK_DGRAM(IPv4协议中的数据报套接字)创建一个UDP套接字。(TCP:bind的服务器IPv4地址被指定为INADDR_ANY)
- 调用函数dg_echo来执行服务器的处理工作。
- 使用recvfrom读入下一个到达服务器端口的数据报,再使用sendto把它发送回发送者。该函数永不终止,因为UDP是一个无连接的协议,它没有像TCP中EOF之类的东西。
- 该函数提供的是一个迭代服务器(iterative server),而不是像TCP服务器那样可以提供一个并发服务器。
- 其中没有对fork的调用,因此单个服务器进程就得处理所有客户。
- 一般来说,大多数TCP服务器是并发的,而大多数UDP服务器是迭代的。
- main函数是协议相关的(它创建一个AF_INET协议的套接字,分配并初始化一个IPv4套接字地址结构),而dg_echo函数是协议无关的。
【注意】
- UDP层中隐含有排队发生。
- 每个UDP套接字都有一个接收缓冲区,到达该套接字的每个数据报都进入这个套接字接收缓冲区。
- 当进程调用recvfrom时,缓冲区中的下一个数据报以FIFO(先入先出)顺序返回给进程。
- 在进程能够读该套接字中任何已排好队的数据报之前,如果有多个数据报到达该套接字,那么相继到达的数据报仅仅加到该套接字的接收缓冲区中(这个缓冲区的大小是有限的)。
- 其中只有一个服务器进程,它仅有的单个套接字用于接收所有到达的数据报并发回所有的响应。
- 该套接字有一个接收缓冲区用来存放所到达的数据报。
UDP回射客户端程序示例
- 把服务器的IP地址和端口号填入一个IPv4的套接字地址结构。该结构将传递给dg_cli函数,以指明数据报将发往何处。
#define MAXLINE 4096void dg_cli(FILE *fp, int sockfd, const struct sockaddr *pservaddr, socklen_t servlen) {int n;char sendline[MAXLINE], recvline[MAXLINE + 1];while (Fgets(sendline, MAXLINE, fp) != NULL) {Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);recvline[n] = 0; Fputs(recvline, stdout);} }int main(int argc, char **argv) {int sockfd;struct sockaddr_in servaddr;if (argc != 2)err_quit("usage: udpcli <IPaddress>");bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SERV_PORT);Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);sockfd = Socket(AF_INET, SOCK_DGRAM, 0);dg_cli(stdin, sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));exit(0); }
- 客户处理循环中有四个步骤:
- 使用fgets从标准输入读入一个文本行。
- 使用sendto将该文本行发送给服务器。
- 使用recvfrom读回服务器的回射。
- 使用fputs把回射的文本行显示到标准输出。
- 客户尚未请求内核给它的套接字指派一个临时端口。(对于TCP客户而言,我们说过connect调用正是这种指派发生之处。)
- 对于一个UDP套接字,如果其进程首次调用sendto时它没有绑定一个本地端口,那么内核就在此时为它选择一个临时端口。
- 跟TCP一样,客户可以显式地调用bind,不过很少这样做。
- 注意:
- 调用recvfrom指定的第五和第六个参数是空指针。这告知内核我们并不关心应答数据报由谁发送。
- 这样做存在一个风险:任何进程不论是在与本客户进程相同的主机上还是在不同的主机上,都可以向本客户的IP地址和端口发送数据报,这些数据报将被客户读入并被认为是服务器的应答。
(UNIX网络编程学习笔记):UDP概述、recvfrom和sendto函数及案例相关推荐
- UNIX网络编程学习笔记(代码超详细解析)(持续更新)
1. 其他函数准备 1. TCP 回射服务器程序: str_echo 函数 #include "unp.h"void str_echo(int sockfd) {ssize_t n ...
- Unix网络编程学习笔记之第11章 名字与地址转换
一. 域名系统(DNS) 1. 简介 DNS主要用于主机名和IP地址之间的映射. 主机名可以是简单的名字ljm,也可以是全限定域名ljm.localdomainbaidu.com等. 2.资源记录 D ...
- 2021版!万字UNIX网络编程学习笔记(套接字篇)
目录 1.一个简单的时间获取服务器的程序 2.套接字篇 2.1 套接字简介 2.2 套接字中常用的函数 2.3 基本TCP套接字编程 2.3.1.socket函数 2.3.2 connect函数 2. ...
- 网络编程学习笔记(UDP的connect函数)
对于已连接的UDP套接口,发生了三个变化: 1.再也不能给输出操作指定目的IP地址和端口,也就是说,不能再调用 sendto,而使用send或者write.写到已连接UDP套接口上的任何东西都自动发送 ...
- [Linux网络编程学习笔记]索引
一.Linux基本知识 [学习笔记]Linux平台的文件I/O操作 [学习笔记]Linux平台的文件,目录及操作 [Linux学习笔记]标准输入输出 [Linux学习笔记]进程概念及控制 [Linux ...
- 15Java网络编程学习笔记
Java网络编程学习笔记 文章目录 1 网络基础 1.1 网络通信 1.2 网络 1.3 IP地址 1.5 域名 1.6 端口号 1.7 网络通信协议 1.8 TCP协议 1.9 UDP协议 2 In ...
- java 网络编程学习笔记
java 网络编程学习笔记 C/S模式:客户端和服务器 客户端创建流程 1 1.建立Socket端点 2 3 Socket s = new Socket(绑定地址, 绑定端口); 2.确认源数据方式和 ...
- 编程开发:Linux网络编程学习笔记
非常全面.通俗易懂.值得借鉴的Linux网络编程学习笔记.关键字:linux linux编程 网络编程 linux网络编程 下载地址:点我下载 特别说明:本资源收集于网络,版权归原作者及版权商所有,仅 ...
- UNIX网络编程--读书笔记
会集中这段时间写UNIX网络编程这本书的读书笔记,准备读三本,这一系类的文章会不断更新,一直会持续一个月多,每篇的前半部分是书中讲述的内容,每篇文章的后半部分是自己的心得体会,文章中的红色内容是很重要 ...
- python网络编程学习笔记(二)
python网络编程学习(四) 多用途客户端协议 一.ftp 功能:上传下载文件,删除命名文件,建立删除目录,自动压缩,保存目录 1.代码: #coding=utf-8 '''连接远程ftp服务器,显 ...
最新文章
- 在C#里怎样获得当前Windows操作系统的语言种类?以及如何知道当前Windows版本?...
- 查询各个年级的平均分_二年级数学:期中考试前精心准备一下,会有意想不到的收获哦!...
- Centos系统更改yum源为163
- 万豪数据泄漏门再敲警钟 酒店集团7步安全建议
- python实现excel数据透视_在pywin32中创建Excel数据透视缓存
- 23-新建maven 项目
- [Android] Android RxJava2+Retrofit2+OkHttp3 的使用(一) --基础篇 Retrofit2 的使用
- blade利刃出鞘】一起进入移动端webapp开发吧
- 智能门锁电路图_科技生活|网传“小黑盒”刷开智能锁,人脸识别系统“翻脸不认人”?...
- 2011年八大赚钱爆发点
- 刀塔自走棋无限寻找服务器怎么办,刀塔自走棋无法连接服务器怎么办_刀塔自走棋无法连接服务器解决办法_玩游戏网...
- 【历史上的今天】1 月 19 日:苹果推出 Lisa;RIM 发布第一款黑莓手机;计算机先驱诞生日
- 2012服务器更改temp位置,如何更改windows的temp目录位置
- 内网安全(四)---横向渗透:PTHPTKPTT
- matlab怎么存盘,matlab怎么保存成word
- 微型计算机原理与应用课件,微机原理与应用课件
- “应用程序无法正常启动(oxc000007b)”解决方案
- JZOJ 6276.树【扫描线】【线段树】
- 5.5 jmeter组件—取样器
- uuuuuuuuuu