TCP/IP 协议栈 -- 编写UDP客户端注意细节

上节我们说到了TCP 客户端编写的主要细节, 本节我们来看一下UDP client的几种情况,测试代码如下:
server:

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#define PORT 6666
int main()
{int serverfd = socket(AF_INET, SOCK_DGRAM, 0);if(serverfd < 0)return -1;struct sockaddr_in serveraddr;serveraddr.sin_port = htons(PORT);serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);bind(serverfd, (const struct sockaddr *)&serveraddr, sizeof(serveraddr));char buff[256] = {0};struct sockaddr_in clientaddr;socklen_t len = sizeof(clientaddr);while(1){recvfrom(serverfd, buff, 256, 0, (struct sockaddr *)&clientaddr, &len);printf("RECV:  %s\n", inet_ntoa( clientaddr.sin_addr));printf("TEXT: %s\n", buff);memset(buff, 0, 256);sendto(serverfd, "recvd hello", 20, 0, (const struct sockaddr*)&clientaddr, sizeof(clientaddr));}return 0;
}

client:

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#define PORT 6666
int main(int argc, char *argv[])
{if(argc != 2){fprintf(stderr, "+++ IPaddress\n");return -1;}int clientfd = socket(AF_INET, SOCK_DGRAM, 0);if(clientfd < 0)return -1;struct sockaddr_in serveraddr;serveraddr.sin_port = htons(PORT);serveraddr.sin_family = AF_INET;char *buff = "hello world";size_t n = strlen(buff);char rebuff[256] = {0};if(inet_pton(AF_INET, argv[1], (void *)&serveraddr.sin_addr) == 0){printf("IP address error\n");return -1;}socklen_t len = sizeof(serveraddr);while(1){sleep(2);sendto(clientfd, buff, n, 0, (const struct sockaddr *)&serveraddr, len);recvfrom(clientfd, rebuff, 256, 0, NULL, NULL);printf("SERVER :%s\n", rebuff);}return 0;
}

UDP 无连接 不可靠的协议 它并不会向TCP一样会建立连接后再发送数据。
1.server 进程没有打开

Desktop# tcpdump -i lo  -A -e -nn 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes
12:43:03.656237 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 53: 127.0.0.1.46066 > 127.0.0.1.6666: UDP, length 11
E..'..@.@.#$...........
...&hello world
12:43:03.656275 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 81: 127.0.0.1 > 127.0.0.1: ICMP 127.0.0.1 udp port 6666 unreachable, length 47
E..C%p..@.V.................E..'..@.@.#$...........
...&hello world

这里 以127地址 做实验 这里可以看到 若主机server进程没有打开,则client会阻塞在recvfrom处 这里可以在sendto和 recvfrom 之间插入printf进行测试。 这就是UDP的特性, ICMP其实是sendto造成的它是一个异步错误 但是这个ICMP并没有返回到应用程序, client 并不知道。 这里的解决方案就是用connect 这里的connect与TCP里的connect建立三次握手差别很大, 对于UDP它就是为了收取这个内核接到的这个ICMP错误。 内核只是检查是否存在立即可知的错误,记录对端的IP地址和端口号,然后立即返回到调用进程。那么这里就要注意到connect里面传入server的ip和port,那么这里的sendto和recvfrom就不要在传入iP和port, 那么就可以用read和write来代替。 这里还有一点就是因为UDP是无连接的, connect并不会像tcp一样会发送SYN, TCP发送SYN时,若server进程没有开启那么会立即受到RST, 但对于UDP来说 当write 后才会收到主机的ICMP错误。
这里写图片描述

2.server 主机不存在。

Desktop# tcpdump -i eth0  -A -e -nn host 15.15.12.13
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
13:11:25.331059 00:0c:29:61:1a:9b > 00:1e:2a:67:f3:2e, ethertype IPv4 (0x0800), length 53: 192.168.1.2.44646 > 15.15.12.13.6666: UDP, length 11
.f.'".@.@.;........
....hello world
13:11:25.331233 00:0c:29:61:1a:9b > 00:1e:2a:67:f3:2e, ethertype IPv4 (0x0800), length 60: 192.168.1.2.44646 > 15.15.12.13.6666: UDP, length 11
.f.'".@.@.;........
....hello world.......

这里可以看到一直阻塞在recvfrom这里 这里的解决方案就是在recvfrom添加超时中断,alarm 或者 select检测fd是否可读 设立超时。

3.client 正在发送数据, server 进程被kill掉

13:17:29.059557 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 62: 127.0.0.1.6666 > 127.0.0.1.57718: UDP, length 20
E..0r.@.@............
.v.../recvd hello.......;4
13:17:31.059842 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 53: 127.0.0.1.57718 > 127.0.0.1.6666: UDP, length 11
E..'s.@.@............v.
...&hello world
13:17:31.059922 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 81: 127.0.0.1 > 127.0.0.1: ICMP 127.0.0.1 udp port 6666 unreachable, length 47
E..C....@.............qs....E..'s.@.@............v.
...&hello world

这里可以看到client也收到了ICMP 解决方案同1.

4.client 正在发生数据, server 断电。

13:17:29.059557 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 62: 127.0.0.1.6666 > 127.0.0.1.57718: UDP, length 20
E..0r.@.@............
.v.../recvd hello.......;4
13:17:31.059842 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 53: 127.0.0.1.57718 > 127.0.0.1.6666: UDP, length 11
E..'s.@.@............v.
...&hello world

同样这里也会一直阻塞在recvfrom这里 解决方案同2 给recvfrom添加超时 或 select 检查fd的可读是否超时。时间可稍微长一些。

转载于:https://www.cnblogs.com/MaAce/p/7755697.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/468931.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RuntimeError: Address already in use

问题描述&#xff1a;Pytorch用多张GPU训练时&#xff0c;会报地址已被占用的错误。其实是端口号冲突了。 因此解决方法要么kill原来的进程&#xff0c;要么修改端口号。 在代码里重新配置 torch.distributed.init_process_group()dist_init_method tcp://{master_ip}:{mast…

Windows环境下的安装gcc

Windows具有良好的界面和丰富的工具&#xff0c;所以目前linux开发的流程是&#xff0c;windows下完成编码工作&#xff0c;linux上实现编译工作。 为了提高工作效率&#xff0c;有必要在windows环境下搭建一套gcc,gdb,make环境。 MinGW就是windows下gcc的版本。 下载地址ht…

RuntimeError: NCCL error in:XXX,unhandled system error, NCCL version 2.7.8

项目场景&#xff1a; 分布式训练中遇到这个问题&#xff0c; 问题描述 大概是没有启动并行运算&#xff1f;&#xff1f;&#xff1f;&#xff08; 解决方案&#xff1a; &#xff08;1&#xff09;首先看一下服务器GPU相关信息 进入pytorch终端&#xff08;Terminal&#x…

一张倾斜图片进行矫正 c++_专业性文章:10分钟矫正骨盆前倾

如今&#xff0c;骨盆前倾(又称“下交叉综合征”)非常多&#xff0c;大部分是由于以下两个原因而变得越来越突出&#xff1a;经常久坐不良的运动习惯后面我们讲到纠正骨盆前倾的四个基本步骤&#xff0c;让你快速解决&#xff0c;提高生活质量知识型和系统型的内容&#xff0c;…

TypeError: can‘t convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory

项目场景&#xff1a; 运行程序&#xff0c;出现报错信息 TypeError: cant convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.。 Traceback (most recent call last):File "tools/demo.py", line 97, in <module>vi…

Secure CRT 自动记录日志

配置自动log操作如下&#xff1a; 1.options ---> Global Options 2、General->Default Session->Edit Default Settings 3、Terminal->Log File 设置如图上所示 点击 日志 &#xff0c;在选项框中 Log file name中填入路径和命名参数&#xff1a; E:\Log\%Y_%M_…

java 异步调用方法_乐字节Java编程之方法、调用、重载、递归

一、概述方法是指人们在实践过程中为达到一定目的和效果所采取的办法、手段和解决方案。所谓方法&#xff0c;就是解决一类问题的代码的有序组合&#xff0c;是一个功能模块。编程语言中的方法是组合在一起来执行操作语句的集合。例如&#xff0c;System.out.println 方法&…

git clone 从GitHub上下载项目到服务器上运行+创建虚拟环境

1. 基础的Linux命令 可先进入需要放置文件的路径之下 pwd # 可看当前路径 cd …/ #返回上一层目录 cd ./xx/ #进入当前路径下的下一个文件2. GitHub项目clone到服务器上运行 # 复制GitHub页面的链接&#xff0c;在服务器后台输入git clone 命令即可 git clone https://githu…

java 调用python_Java平台如何调用Python平台?

1. 问题描述Java平台要调用Pyhon平台已有的算法&#xff0c;为了减少耦合度&#xff0c;采用Pyhon平台提供Restful 接口&#xff0c;Java平台负责来调用&#xff0c;采用HttpJson格式交互。2. 解决方案2.1 JAVA平台侧2.1.1 项目代码public static String invokeAlgorithm(Strin…

C 实现 删除字符串空白符的函数 strtrim

说在前面的话 字符串操作在很多C语言比赛里面都有涉及&#xff0c;最近公众号里面的C语言比赛&#xff0c;都是两个关于字符串操作的题目&#xff0c;希望大家认真看题目。 直接上代码 /*************************************************************************> Fil…

javascript犀牛书_犀牛书作者:最该忘记的JavaScript特性

作者&#xff1a; 李松峰转发链接&#xff1a;https://mp.weixin.qq.com/s/guAN1Cz2gYfKdBhmUpLyVA前言JavaScript这门语言的第一个演示版差不多就在25年前诞生。没记错的话&#xff0c;25年前的今天&#xff0c;1995年5月10日&#xff0c;星期三&#xff0c;我刚刚过了创造Jav…

Weblogic(4)—— Linux环境Weblogic12c配置节点管理(nodemanage.properties)来开启应用服务器(server)及线程池配置...

Linux环境搭建weblogic12c服务器&#xff0c;用来进行weblogic服务器项目部署&#xff0c;刚创建weblogic服务器会默认存在AdminServer管理服务器。但是项目应用一般是不能挂在这个服务器上的&#xff0c;需要自己单独创建应用服务器。 使用root权限登录 服务器&#xff1a; 输…

IDEA与Maven安装+IDEA中利用maven自动下载第三方Jar包

Maven详细安装教程_慕之寒的博客-CSDN博客_maven安装一、安装apache官网下载需要的版本&#xff0c;然后解压缩&#xff0c;解压路径尽量不要有空格和中文Maven – Download Apache Mavenhttps://maven.apache.org/download.cgi二、配置环境变量新建 系统变量变量名&#xff1a…

Web前端学习笔记:Bootstrap

转载于:https://www.cnblogs.com/mmgds/p/6681817.html

计算机软件需求规格说明规范_太阳能(光伏)组件安全规范测试简介_丙观科技

太阳能组件的安全规范测试包含• 接地连续性测试(也称为接地电阻测试)• 绝缘测试 (也称为湿漏电流测试&#xff0c;湿绝缘电阻测试)• 耐压测试 (也称为介质耐压试验)测试设备必须满足下列标准中规定的相关测试要求• IEC 61215 地面用晶体硅光伏组件-设计鉴定和定型• IEC 61…

报错FloatingPointError: Loss became infinite or NaN at iteration=88!

项目场景&#xff1a; Traceback (most recent call last): File "/home/yuan/桌面/shenchunhua/CondInst-master/train_net.py", line 255, in <module> args(args,), File "/home/yuan/anaconda3/envs/AdelaiNet/lib/python3.7/site-packages/d…

git commit查找提交的关键字

使用命令 git log --grepaplog 参考&#xff1a; https://stackoverflow.com/questions/1337320/how-to-grep-git-commit-diffs-or-contents-for-a-certain-word

C语言测试n的阶乘和x的n次方

题目描述 输入一个正数x和一个正整数n&#xff0c;求下列算式的值。要求定义两个调用函数&#xff1a;fact(n)计算n的阶乘&#xff1b;mypow(x,n)计算x的n次幂&#xff08;即xn&#xff09;&#xff0c;两个函数的返回值类型是double。 输出保留4位小数。 输入 x n 输出 数列…

自己动手写java虚拟机_自己动手写操作系统(要了解的知识点)

自己动手写操作系统(开篇)自己动手写操作系统(字符显示)说明&#xff1a;Intel 8086 或者不同的处理器&#xff0c;开机寄存器数据可能不一样&#xff0c;但是大致原理差不多了解过计算机启动的同学肯定知道&#xff0c;当计算机启动的时候 BIOS 会加载 MBR 数据 512 字节到 0x…

git入门基础

git基础 参考&#xff1a;官网git基础 git 文件的生命周期 文件的生命周期图&#xff1a; git中的文件可以分为4个阶段. Untracked &#xff1a; 这是目录中没有被跟踪的文件&#xff0c;即不在git项目中&#xff0c;使用 git commit 等命令对文件进行提交时不会提交这样的文件…