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[1024];while(1) {len = cli_len;n = recvfrom(sockfd, buf, 1024, 0, p_client_addr, &len);sendto(sockfd, buf, n, 0, 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, 0);memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family=AF_INET;server_addr.sin_addr.s_addr=htonl(INADDR_ANY);server_addr.sin_port=htons(12345);if(bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr))<0)perror("bind error!");echo_server(sockfd, (struct sockaddr *)&client_addr, sizeof(client_addr));}

该程序存在一些问题:

  1. 函数永远不会终止,因为UDP是一个无连接的协议,没有像TCP中EOF之类的东西
  2. 该函数提供的是一个迭代服务器,而不是并发服务。因此单个服务器进程就得处理所有客户
  3. 对于本套接字,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[1024], recv[1024];while(fgets(send, 1024, fp) !=NULL) {sendto(sockfd, send, strlen(send), 0, p_server_addr, serv_len);n=recvfrom(sockfd, recv, 1024, 0, NULL, NULL);recv[n]='\0';fputs(recv, stdout);}
}int main(int argc, char **argv) {int sockfd;struct sockaddr_in server_addr;if(argc!=2) {printf("usage: udp_client <IP Address>\n");exit(0);}sockfd=socket(AF_INET, SOCK_DGRAM, 0);memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family=AF_INET;server_addr.sin_port=htons(12345);inet_pton(AF_INET, argv[1], &server_addr.sin_addr);    echo_client(stdin, sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
}

该程序也隐含一个问题:

  1. 客户端尚未请求内核给它的套接字指派一个临时端口
  2. recvfrom第5个和第6个参数是空指针,表示不关心数据是由谁发送。因此任何进程的数据包都会被当成是服务器的应答。
  3. UDP是不可靠的。如果一个数据报丢失,客户将永远阻塞在recvfrom函数上。

假设在服务器不启动的情况下启动客户端,数据报由客户发出,服务器主机响应一个端口不可达的ICMP消息,而这个ICMP消息不返回给客户进程,客户将永远阻塞于recvfrom调用,等待服务器的应答。我们称这个错误为异步错误(asynchronous error)。该错误由sendto引起,但sendto本身却成功返回。UDP输出成功仅仅代表在接口队列中有存放IP数据报的空间。改ICMP直到后来才返回,这就是称其为异步的原因。

4 UDP程序例子小结

转载于:https://www.cnblogs.com/alwayswangzi/p/6595310.html

UNP学习笔记3——基本UDP套接字编程相关推荐

  1. UNP学习笔记-第三章套接字编程

    套接字地址结构 地址转换函数 地址转换函数在地址的文本表达和存放在套接字地址结构中的二进制值之间进行转换. 例如IPv4中inet_addr, inet_ntoa .新函数:inet_pton,ine ...

  2. 【Linux网络编程】UDP 套接字编程

    [Linux网络编程]UDP 套接字编程 [1]用户数据报协议(UDP) UDP是一个简单的传输层协议,不保证UDP数据报会到达其最终目的地,不保证各个数据报的先后顺序跨网络后保持不变,也不保证每个数 ...

  3. 《网络编程》基本 UDP 套接字编程

    在前面文章中介绍了<UDP 协议>和<套接字数据传输>.UDP 协议和 TCP 协议不同,它是一种面向无连接.不可靠的传输层协议.在基于 UDP 套接字编程中,数据传输可用函数 ...

  4. 计算机网络实验二:UDP套接字编程实现多人聊天

    一.实验目的 1. 实现一个能够在局域网中进行点对点聊天的实用程序. 2. 熟悉c++.Java等高级编程语言网络编程的基本操作. 3. 基本了解对话框应用程序的编写过程. 4. 实现UDP套接字编程 ...

  5. Linux IPv6 UDP套接字编程示例

    udp ipv6套接字编程和ipv4接口类似,参数略有不同,流程都包括创建套接字.绑定地址.发送等. 下面是一个udp ipv6 demo, 包括创建ipv6套接字.绑定地址和发送数据等. 首先先在l ...

  6. linux udp套接字编程获取报文源地址和源端口(二)

    之前项目中涉及udp套接字编程,其中一个要求是获取客户端发过来报文的端口和ip地址,功能很简单,只是对这一块不很熟.之前使用的方法是通过调用recvmsg这个接口,并通过参数msg里面的msg_nam ...

  7. TCP和UDP套接字编程

    一.Socket简单介绍 如果要在应用层调用传输层的服务,进行相关程序的设计,就要涉及到套接字编程.套接字也称之为Socket,本质上它就是利用传输层提供的一系列Api来进行网络应用程序的设计. 网络 ...

  8. 网络编程---TCP/UDP套接字编程原理

    本篇介绍的是Linux下的网络编程,故有些接口是不适用于Windows的,但是具体概念和实现方法是大体一致的 本篇重在讲解原理,具体实现请戳这里->UDP套接字编程实现 介绍 网络编程套接字(s ...

  9. UDP套接字编程——Python语言描述

    首先,回顾一下.在我们使用Socket编程之前的一些网络的概念. IP:它是用来标识处于Internet之中的端系统的. MAC:它是用于在同一局域网中标识不同的计算机的. 端口号:它是用来标识同一台 ...

最新文章

  1. 中科院院士「修正」了麦克斯韦方程?研究发材料期刊,两度热搜,两极评价...
  2. asp.net core 3.0 中使用 swagger
  3. 高版本(3.9版本)python在anaconda安装opencv库及skimage库(scikit_image库)诸多问题解决办法
  4. Vue学习笔记之14-Vue-CLI脚手架
  5. 无法初始化主类 flink.learn.bounded.WordCountJob
  6. 关于在ubuntu14.04下firefox升级后refresh插件不好用
  7. 白杨SEO:SEM和SEO有什么区别呢?
  8. 基于SSM的高校后勤管理系统Java项目
  9. 密码破解---实验八:Windows本地破解用户口令
  10. 日记 [2007年11月19日]...
  11. 国内最新Unity3D视频教程合辑
  12. 资产证券化为什么需要区块链技术?专访趣链科技揭开“区块链+ABS”迷雾
  13. 软件测试需要学习哪些技能?
  14. [NOI2008]糖果雨
  15. 任务调度的合理性 (25 分)
  16. 在指定数据的前面加“0“
  17. 2020美赛D题原文及翻译
  18. 搭建nodejs+express服务器
  19. mysql MMM架构
  20. oracle授予数据库所有权限,oracle创造新用户及授予常用权限

热门文章

  1. 基于MySQL和JavaFX的学生管理系统
  2. python selenium不启动浏览器 爬取数据的方法
  3. opencv学习笔记02
  4. map函数的用法python,详解Python map函数及Python map()函数的用法
  5. python学习——正则表达项目
  6. vba循环通过键盘某个按键按下退出循环_默纳克3000+最新系统小键盘的使用方法...
  7. python 函数中参数的传递方式(三分钟读懂)
  8. python程序加密_Python简单的加密程序:如何循环Z回到A
  9. leetcode 273场周赛 Problem-C
  10. Problem F. Grab The Tree博弈