UNP学习笔记3——基本UDP套接字编程
1 概述
TCP和UDP网络编程存在一些本质的差异,主要是由于传输层的差别:UDP是无连接的不可靠的数据报协议,而TCP是面向连接的字节流协议。
下图是典型的UDP客户端和服务器之间的通信流程。客户不与服务器建立连接,而是只管使用sendto函数。服务器不接受来自客户的连接,而是只管调用recvfrom函数,等待某个客户的数据到达。
本章学习用于UDP套接字的两个新函数recvfrom和sendto,并使用UDP重写ECHO程序。还将学习connect函数在UDP套接字中的用法,同时理解异步错误的概念
2 recvfrom和sendto函数
这两个函数类似标准的read、write函数,不过需要额外的三个参数。
#include <sys/socket.h> ssize_t recvfrom(int sockfd, void *buf, size_t nbytes, int flags, struct sockaddr *from, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buf, size_t nbytes, int flags, const struct sockaddr *to, socklen_t addrlen);
/*以上函数返回:成功返回读或写到的字节数,出错返回-1*/
前三个参数sockfd、buff和nbytes分别代表:描述符、指向输入或写出缓冲区的指针和读写的字节数。
flags参数在讨论recv、send、recvmsg和sendmsg函数时再介绍,这里默认设置为0。
sendto的to参数指向一个含有数据报接受者的协议地址(IP地址及端口号)的套接字地址结构,其大小由addrlen指定。recvfrom的from参数指向一个含有数据报发送者的协议地址(IP地址及端口号)的套接字地址结构,其大小由addrlen指定。注意sendto的最后一个参数是一个整数值,而recvfrom的最后一个参数是一个指向整形的指针(即值-结果函数)。
写一个长度位(0)的数据报是可行的(TCP不允许),这会发送一个只有IP首部和UDP首部,没有数据的数据报。类似的,recvfrom返回0值也是可以的(TCP则代表对端已关闭连接)。如果recvfrom的from参数是一个空指针,相应的addrlen为0,说明我们不关心发送者的协议地址。recvfrom和sendto函数都可以用于TCP,尽管通常不这么做。
3 最原始的UDP Echo程序
udp_echo_server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h> void echo_server(int sockfd, struct sockaddr *p_client_addr, socklen_t cli_len) { int n;
socklen_t len;
char buf[]; while() {
len = cli_len;
n = recvfrom(sockfd, buf, , , p_client_addr, &len);
sendto(sockfd, buf, n, , p_client_addr, len);
}
} int main(int argc, char **argv) { int sockfd;
struct sockaddr_in server_addr, client_addr; sockfd=socket(AF_INET, SOCK_DGRAM, );
memset(&server_addr, , sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(); if(bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr))<)
perror("bind error!"); echo_server(sockfd, (struct sockaddr *)&client_addr, sizeof(client_addr)); }
该程序存在一些问题:
- 函数永远不会终止,因为UDP是一个无连接的协议,没有像TCP中EOF之类的东西
- 该函数提供的是一个迭代服务器,而不是并发服务。因此单个服务器进程就得处理所有客户
- 对于本套接字,UDP层隐含有排队的发生
udp_echo_client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h> void echo_client(FILE *fp, int sockfd, const struct sockaddr *p_server_addr, socklen_t serv_len) { int n;
char send[], recv[];
while(fgets(send, , fp) !=NULL) {
sendto(sockfd, send, strlen(send), , p_server_addr, serv_len);
n=recvfrom(sockfd, recv, , , NULL, NULL);
recv[n]='\0';
fputs(recv, stdout);
}
} int main(int argc, char **argv) {
int sockfd;
struct sockaddr_in server_addr; if(argc!=) {
printf("usage: udp_client <IP Address>\n");
exit();
} sockfd=socket(AF_INET, SOCK_DGRAM, );
memset(&server_addr, , sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons();
inet_pton(AF_INET, argv[], &server_addr.sin_addr); echo_client(stdin, sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
}
该程序也隐含一个问题:
- 客户端尚未请求内核给它的套接字指派一个临时端口
- recvfrom第5个和第6个参数是空指针,表示不关心数据是由谁发送。因此任何进程的数据包都会被当成是服务器的应答。
- UDP是不可靠的。如果一个数据报丢失,客户将永远阻塞在recvfrom函数上。
假设在服务器不启动的情况下启动客户端,数据报由客户发出,服务器主机响应一个端口不可达的ICMP消息,而这个ICMP消息不返回给客户进程,客户将永远阻塞于recvfrom调用,等待服务器的应答。我们称这个错误为异步错误(asynchronous error)。该错误由sendto引起,但sendto本身却成功返回。UDP输出成功仅仅代表在接口队列中有存放IP数据报的空间。改ICMP直到后来才返回,这就是称其为异步的原因。
4 UDP程序例子小结
UNP学习笔记3——基本UDP套接字编程的更多相关文章
- UNP学习笔记1——基本TCP套接字编程
1 套接字地址结构 大多数套接字函数都需要一个指向套接字地址结构的指针作为参数.每个协议族都定义了自己的套接字结构.这些套接字的结构以sockaddr_开头,以每个协议族唯一的后缀名结尾. 1.1 I ...
- 《Unix 网络编程》08:基本UDP套接字编程
基本UDP套接字编程 系列文章导航:<Unix 网络编程>笔记 UDP 概述 流程图 recvfrom 和 sendto #include <sys/socket.h> ssi ...
- 【Python网络编程】利用Python进行TCP、UDP套接字编程
之前实现了Java版本的TCP和UDP套接字编程的例子,于是决定结合Python的学习做一个Python版本的套接字编程实验. 流程如下: 1.一台客户机从其标准输入(键盘)读入一行字符,并通过其套接 ...
- 探索UDP套接字编程
UDP和TCP处于同一层网络模型中,也就是运输层,基于二者之上的应用有很多,常见的基于TCP的有HTTP.Telnet等,基于UDP有DNS.NFS.SNMP等.UDP是无连接,不可靠的数据协议服务, ...
- 【转】 探索UDP套接字编程
UDP和TCP处于同一层网络模型中,也就是运输层,基于二者之上的应用有很多,常见的基于TCP的有HTTP.Telnet等,基于UDP有DNS.NFS.SNMP等.UDP是无连接,不可靠的数据协议服务, ...
- JavaTCP和UDP套接字编程
在我们刚开始入门Java后端的时候可能你会觉得有点复杂,包含了很多杂七杂八的知识,例如文件上传下载,监听器,JDBC,请求重定向,请求转发等等(当然也没有很多),但是我们自己真正的去开发一个小型网站( ...
- 计算机网络实验 UDP套接字编程
这是个傻瓜式操作教程 西科大计算机网络实验 UDP套接字编程 我用自己的Ubuntu16.04来举例,实验室的是虚拟机,差不多 只针对第三个题目,修改服务器来通过响应客户端发送的GetTime并发送给 ...
- UDP套接字编程 返回系统时间
计算机网络实验 简单UDP套接字编程 这是学校老师自己改进了一点的题目.我预习了好久才搞明白,同学来问的时候,一大堆简单问题实在是不想回答...所以,这时候我觉得博客是个好东西! 我的任务是做客户端和 ...
- 【Unix网络编程】chapter8基本UDP套接字编程
chapter8基本UDP套接字编程 8.1 概述 典型的UDP客户端/服务端的函数调用 8.2 recvfrom和sendto函数 #include <sys/socket.h> ssi ...
随机推荐
- hust 1570 Lazy. Lazy. Laaaaaaaaaaaazy!
链接 1570 - Lazy. Lazy. Laaaaaaaaaaaazy! 题意 给出三种按键,caplock,shift,nomal(像正常键盘操作一样) ,输入三串字符串,s1,s2,txt, ...
- 10件5G能实现,但4G不能做的事情
10件5G能实现,但4G不能做的事情 从三星Galaxy S10 5G手机到OnePlus 7 Pro 5G手机以及更高版本,首批5G手机现已上市.5G网络时代的开启是从小范围内,如果你居住在可以使用 ...
- 理解Faster-RCNN 中的Anchor
先上图看一下Faster R-CNN操作流程: 图片说明:Faster R-CNN=Fast R-CNN+RPN,其中Fast R-CNN结构不变:RPN负责生成proposals,配合最后一层的f ...
- 洛谷P2678 跳石头
简简单单二分答案,n和m不要写反 Code: #include<cstdio> #include<algorithm> using namespace std; const i ...
- 洛谷P1540 机器翻译 水题 模拟
注意一下细节,尤其是更新minv时不要更新错. Code: #include<vector> #include<iostream> #include<cstdio> ...
- OpenGL中着色器,渲染管线,光栅化
https://www.zhihu.com/question/29163054 光栅(shan一声)化(Rasterize/rasteriztion).这个词儿Adobe官方翻译成栅格化或者像素化 ...
- webstorm + babel
网上有很多关于如何设置babel的.我学习着设置,但总差那么几步,没能满足我的需求. 我使用的是webStorm2017.1版本. babel安装准备 使用webStorm自带的filewatcher ...
- P1421 小玉买文具
... 题目描述 班主任给小玉一个任务,到文具店里买尽量多的签字笔.已知一只签字笔的价格是1元9角,而班主任给小玉的钱是a元b角,小玉想知道,她最多能买多少只签字笔呢. 输入输出格式 输入格式: 输入 ...
- 2019-03-28 SQL Server select 1
select 1 是比select *更有效率的写法 因为它不返回具体的数据记录,而是返回n行的1 select 1 from studentsselect class,count(1) as pax ...
- 你必须搞清楚的String,StringBuilder,StringBuffer
String,StringBuilder 以及 StringBuffer 这三个类的关系与区别一直是 Java 的经典问题,这次就来讲一下关于这三个类的一些知识 一. 简单对比 String : 字符 ...