在UDP套按字上调用Connect建立连接

Qt UDP通信聊天程序(单播、广播、组播) UDP是轻量的、不可靠的、面向数据报、无连接的协议,它可以用于对可靠性要求不高的场合,与TCP通信不同,无需建立持久的socket连接。QUdpSocket用于实现UDP通信,与QTcpSocket主要区别是,QUdpSocket以数据报传输数据,而不是以连续的数据流。发送数据使用writeDatagram(),数据报的长度一般少于512字节,每个数据报包含发送者和接收者的IP地址和端口等信息。要进行UDP通信,首先需要bind函数绑定一个端口,用于接收传入的手机不能。 阅读详情
标准的udp客户端开了套接口后,一般使用sendto和recvfrom函数来发数据,最近看到mobilygen的代码里面是使用send函数直接法的,就分析了一下,原来udp发送数据有两种方法供大家选用的,顺便把udp的connect用法也就解释清楚了。
方法一:
socket----->sendto()或recvfrom()
方法二:
socket----->connect()----->send()或recv()

首先从这里看出udp中也是可以使用connect的,但是这两种方法到底有什么区别呢?首先把这四个发送函数的定义列出来:
int send(int s, const void *msg, size_t len, int flags);
int sendto(int s, const void *msg, size_t len, int flags,
const struct sockaddr *to, socklen_t tolen);

int recv(int s, void *buf, size_t len, int flags);
int  recvfrom(int  s, void *buf, size_t len, int flags,
struct sockaddr *from,  socklen_t *fromlen);
从他们的定义可以看出,sendto和recvfrom在收发时指定地址,而send和recv则没有,那么他们的地址是在那里指定的呢,答案就在于connect.
int  connect(int  sockfd,  const  struct sockaddr *serv_addr, socklen_t
addrlen);
在udp编程中,如果你只往一个地址发送,那么你可以使用send和recv,在使用它们之前用connect把它们的目的地址指定一下就可以了。connect函数在udp中就是这个作用,
用它来检测udp端口的是否开放是没有用的。下面是mobilygen中的代码
struct sockaddr_in sa_dest;
bzero((char *) sa_dest, sizeof(*sa_dest));
sa_dest->sin_family=AF_INET;
if(StuffNetAddr(&(sa_dest->sin_addr),host))
return 1;

sa_dest->sin_port=htons(port);

if (connect(usd,(struct sockaddr *)&sa_dest,sizeof(sa_dest))==-1)
{perror("connect");return 1;}

return 0;



=================================

除非套接口已连接,否则异步错误是不会返回到UDP套接口的,我们确实可以给UDP套接口调用connect,然而这样做的结果却与TCP连接大相径庭:没有三路握手过程。

相反内核只是检查是否存在立即可知的错误(例如一个显然不可达的目的地),记录对端的IP地址和端口号(取自传递给connect的套接口地址结构),然后立即返回到调用进程。

对于已连接UDP套接口,与缺省的未连接套接口相比,发生了三个变化:
1 我们再也不能给输出操作指定宿IP和端口号,也就是说我们不使用sendto,而改用write或send,写到已连接UDP套接口上的任何内容都自动发送到由connect指定的协议地址(例如IP地址和端口号)
2 我们不必使用recvfrom以获悉数据报的发送者,而改用read,recv或recvmsg,在一个已连接UDP套接口上由内核为输入操作返回的数据 报仅仅是那些来自connect所指定协议地址的数据报。目的地为这个已连接UDP套接口的本地协议地址,发源地却不是该套接口早先connect到的协 议地址的数据报,不会投递到该套接口。这样就限制了一个已连接UDP套接口而且仅能与一个对端交换数据报。
3 由已连接的UDP套接口引发的异步错误返回给他们所在的进程。

相反我们说过未连接UDP套接口不接收任何异步错误给一个UDP套接口多次调用connect拥有一个已连接UDP套接口的进程可以为下列2个目的之一:
a.指定新的IP地址和端口号;
b.断开套接口

第一个目的(即给一个已连接UDP套接口指定新的对端)不同于TCP套接口中connect的使用:对于TCP套接口,connect只能调用一次。

为了断开一个已connect的UDP套接口连接,我们再次调用connect时把套接口地址结构的地址簇成员(sin_family)设置为AF_UNSPEC。
这么做可能返回一个EAFNOSUPPORT错误,不过没有关系。
使得套接口断开连接的是在已连接UDP套接口上调用connect的进程。



=================================

有如下的一些好处:
1)选定了对端,内核只会将帮定对象的对端发来的数据报传给套接口,因此在一定环境下可以提升安全性;
2)会返回异步错误,如果对端没启动,默认情况下发送的包对应的ICMP回射包不会给调用进程,如果用了connect,嘿嘿
3)发送两个包间不要先断开再连接,提升了效率。


做个实验测试下吧

先弄个UDP回射服务器,把所有收到的数据报回射回去:
a@a-desktop:~/d/lab$ cat rollbackserver.cpp
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
using namespace std;
int main()
{
int sockListener,nMsgLen;
char szBuf[1024];
struct sockaddr_in addrListener;
socklen_t addrLen;
addrLen=sizeof(struct sockaddr_in);
bzero(&addrListener,sizeof(addrListener));
addrListener.sin_family=AF_INET;
addrListener.sin_port=htons(8000);

if((sockListener=socket(AF_INET,SOCK_DGRAM,0))==-1)
{
perror("error in getting a socket");
exit(1);
}

if(bind(sockListener,(struct sockaddr*)&addrListener,sizeof(addrListener))==-1)
{
perror("bind a listener for a socket");
exit(2);
}

struct sockaddr_in addrClient;
cout<<"callback server begin to listen"<<endl;
while(true)
{
nMsgLen=recvfrom(sockListener,szBuf,1024,0,(struct sockaddr*)&addrClient,&addrLen);
if(nMsgLen>0)
{
szBuf[nMsgLen]='/0';
cout<<"send back:"<<szBuf<<endl;
sendto(sockListener,szBuf,nMsgLen,0,(struct sockaddr*)&addrClient,addrLen);
}
}

}


再写个客户端,绑定个端口,再连接服务器端。随时接受键盘输入并发送到服务器端,随时接受端口到来的数据并打印。如果没有连接 ,发送到此端口的数据会被接受,但是调用connect后会怎样呢?
a-desktop:~/d/lab$ cat udpclient.cpp
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/select.h>
using namespace std;
int main()
{
int sockClient,nMsgLen,nReady;
char szRecv[1024],szSend[1024],szMsg[1024];
struct sockaddr_in addrServer,addrClient,addrLocal;
socklen_t addrLen;
fd_set setHold,setTest;

sockClient=socket(AF_INET,SOCK_DGRAM,0);
addrLen=sizeof(struct sockaddr_in);
bzero(&addrServer,sizeof(addrServer));
addrServer.sin_family=AF_INET;
addrServer.sin_addr.s_addr=inet_addr("127.0.0.1");
addrServer.sin_port=htons(8000);

addrLocal.sin_family=AF_INET;//bind to a local port
addrLocal.sin_addr.s_addr=htonl(INADDR_ANY);
addrLocal.sin_port=htons(9000);
if(bind(sockClient,(struct sockaddr*)&addrLocal,sizeof(addrLocal))==-1)
{
perror("error in binding");
exit(2);
}

if(connect(sockClient,(struct sockaddr*)&addrServer,sizeof(addrServer))==-1)
{
perror("error in connecting");
exit(1);
}

FD_ZERO(&setHold);
FD_SET(STDIN_FILENO,&setHold);
FD_SET(sockClient,&setHold);
cout<<"you can type in sentences any time"<<endl;
while(true)
{
setTest=setHold;
nReady=select(sockClient+1,&setTest,NULL,NULL,NULL);
if(FD_ISSET(0,&setTest))
{
nMsgLen=read(0,szMsg,1024);
write(sockClient,szMsg,nMsgLen);
}
if(FD_ISSET(sockClient,&setTest))
{
nMsgLen=read(sockClient,szRecv,1024);
szRecv[nMsgLen]='/0';
cout<<"read:"<<szRecv<<endl;
}

}

}
最后来个“第三者”,向第二个的端口发数据报。看她会不会成为忠贞的感情守护人:
a@a-desktop:~/d/lab$ cat clienta.cpp
#include<string.h>
#include<iostream>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
using namespace std;
int main()
{
socklen_t addrLen=sizeof(struct sockaddr_in);
struct sockaddr_in addrServer;
char szMsg[1024];
int sockClient;

addrServer.sin_family=AF_INET;
addrServer.sin_addr.s_addr=inet_addr("127.0.0.1");
addrServer.sin_port=htons(9000);

sockClient=socket(AF_INET,SOCK_DGRAM,0);
while(true)
{
static int id=0;
snprintf(szMsg,sizeof(szMsg),"this is %d",id++);
sendto(sockClient,szMsg,strlen(szMsg),0,(struct sockaddr*)&addrServer,sizeof(addrServer));
sleep(1);
}
}



实验结果:
现运行第一个程序,再运行第三个程序,然后运行第二个程序。
服务器端:

a@a-desktop:~/d/lab$ ./rollback
callback server begin to listen
send back:xinheblue likes playing

send back:and listenning to music


第二个程序:
a@a-desktop:~/d/lab$ ./udpclient
you can type in sentences any time
xinheblue likes playing
read:xinheblue likes playing

and listenning to music
read:and listenning to music


实现结果证明,第二个程序调用connect后,不甩第三个程序发来的数据包。
UDP连接调用connect()函数 UDP是一个无连接的协议,它没有像TCP中EOF之类的东西。 8.11 UDP的connect函数 除非套接字已连接,否则异步错误是不会反悔到UDP套接字的。我们确实可以给UDP套接字调用connect,然而这样做的结果却与TCP连接不同的是没有三路握手过程。内核只是检查是否存在立即可知的错误,记录对端的IP地址和端口号,然后立即返回调用进程。 对于已连接UDP套接字,与默认 阅读详情

相关推荐

TCP/UDP与connect系统调用

一、TCP与UDP区别        TCP保证数据正确性,UDP可能丢包;TCP保证数据顺序,UDP不保证。        TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。        UDP---用户数

fengqiaojiangshui的专栏 1096

UDP中的Connect方法

上一篇文章中,我发现了UDP也是有这connect方法的,这使我非常不理解,下面为大家讲解一下这个connect方法。 我们知道UDP是无连接的,它可以给多个IP发送数据包,包括广播地址或者多播通信的实现,而这些是TCP/IP无法实现的。 但是UDP提供了这样的一个connect()方法,它有两种使用方式,当使用了这个方法之后,那么就限定了这个socket的使用范围: 只允许从这个指定的SocketAddress 上获得数据包和向这个指定的SocketAddress 发送数据包, 当你一旦通过这个socke

awangdea99的博客 3038

UDP-Connect

我们都知道TCP 是面向连接的,因此再传输数据之前必须要建立连接,也就是客户端调用connect(),服务端accept(),完成三次握手,建立连接。 我们也知道UDP是面向无连接的,它传输数据之前是不需要建立连接的,那么对于UDP通信编程,我们是否需要调用connect了?如果可以,什么时候调用了?调用了有什么好处了? 一、发送接收函数 首先回顾下,传输数据的两组函数 1、tcp

yixianfeng41的专栏 1207

udp 使用connect优点_udp调用connect有什么作用(转)

原文链接如下:整理一下.1:UDP中可以使用connect系统调用2:UDP中connect操作与TCP中connect操作有着本质区别。TCP中调用connect会引起三次握手,client与server建立连结.UDP中调用connect内核仅仅把对端ip&port记录下来.3:UDP中可以多次调用connect,TCP只能调用一次connect.UDP多次调用connect有两种用途...

weixin_39559333的博客 489

socket 编程TCP,UDP建立连接过程详解

1,TCP是面向连接的协议,建立的过程使用三次握手协议,大概过程是客户机发送数据请求给服务机,告诉服务机,我有数据需要发送,服务机收到请求,发送一个确认请求回复,告诉客户机你发的请求我已经收到,客户机收到该请求也向服务机发送一个确认请求回复,告诉服务机我收到了。具体的socket编程流程如下所示: 服务器端: socket()       建立socket连接,生成一个socket文件描述符,

sophiazhu0218的专栏 4996

udp 调用connect 后切换网络会出现什么情况

Udp client端快速感知服务端异常如挂掉,udp 调用connect 后切换网络会出现什么情况背景正题 最近有点想法,有点像溜溜球的赶脚,来回总结了一下,发现以前忙忙碌碌地学习,学的也不少但是能记住不多,平时做的笔记也比较随意,很散,现在梳理感觉有点吃力,莫名的感觉到一味地瞎搞没有认真总结是一种非常不明智做法,效率真心不高。从此刻无论如何只要有新知识必须上了梳理一波,想变强必须严格要求,别懒死啊,兄弟~~~注意学习方法,积累知识,进入正题。。。 背景 最近和一个兄弟在搞可靠udp相关开发,具体实现仿

u012605068的博客 822

udp通讯中的connect()和bind()函数

udp是一个基于无连接的通讯协议,通讯基本模型如下: 可以看出,不论是在客户端还是服务器,connect()似乎用不上,bind()在客户端也用不上,但是事实并非如此。1. udp客户端使用connect()函数udp客户端建立了socket后可以直接调用sendto()函数向服务器发送数据,但是需要在sendto()函数的参数中指定目的地址/端口,但是可以调用connect()函数先指明目的地

echo_bright_的博客 5万+

Linux/Unix网络编程之UDP的connect函数

对于linux网络编程,我们都知道UDP是发送数据报,而且,我们只要在sendto函数中指定你要发送的端口和IP地址就可以了,我们不用绑定端口和IP。但是,如果对UDP进行connect函数的调用,会发生什么现象呢?有了这个能力,我们可以分为两个种:1,未连接的UDP,新创建的UDP套接字就是这样的。2,已连接的UDP,调用connect函数就是这样的。其中,已连接的毕未连接的多了三个变化:1,我们再也不能给输出操作指定目的IP和目的端口。也就是说,我们不能调用sendto,而是用write或者send。写

飞在天空的鱼 4917

UDP中调用connect以及使用send的好处

udp调用connect有什么作用 整理一下.1:UDP中可以使用connect系统调用2:UDP中connect操作与TCP中connect操作有着本质区别。TCP中调用connect会引起三次握手,client与server建立连结.UDP中调用connect内核仅仅把对端ip&port记录下来.3:UDP中可以多次调用connect,TCP只能调用一次connect. &nb...

ZR 2432

udp使用connect建立连接与普通udp连接区别

UDP中connect操作与TCP中connect操作有着本质区别.TCP中调用connect会引起三次握手,client与server建立连结.UDP中调用connect内核仅仅把对端ip&port记录下来 使用connect建立的udp连接相比于普通udp连接有两个优势: 一: 提高发送效率 1.在普通udp连接上发送两个报文,在内核操作如下: a) 建立连接;...

技术联盟 3275

【驭风计划 机器学习】实验6 基于集成学习的 Amazon 用户评论质量预测

¶随着电商平台的兴起,以及疫情的持续影响,线上购物在我们的日常生活中扮演着越来越重要的角色。在进行线上商品挑选时,评论往往是我们十分关注的一个方面。然而目前电商网站的评论质量参差不齐,甚至有水军刷好评或者恶意差评的情况出现,严重影响了顾客的购物体验。因此,对于评论质量的预测成为电商平台越来越关注的话题,如果能自动对评论质量进行评估,就能根据预测结果避免展现低质量的评论。本案例中我们将基于集成学习的方法对 Amazon 现实场景中的评论质量进行预测。

Mege1的博客 473

UDP也可以有connect连接

根据《TCP/IP,UDP通信——C++实现》文章,知道了:UDP 等于无连接协议。 但是有的时候,UDP又有了connect连接,这是怎么回事呢?以下简单探究一番。 调用 connect 将 UDP 套接字和 IPv4 地址进行了“绑定”,这里 connect 函数的名称有点让人误解,其实可能更好的选择是叫做 setpeername; UDP 套接字调用 connect 函数,但是和 TCP...

优快云的博客 4760

【软件逆向学习记录】x64dbg调试器入门2:主调试窗口功能及字符串搜索功能介绍

在x64dbg中, ​​CPU视图 是调试过程中最核心的界面,通常被称为​​主调试窗口​​或​​调试视图​​,总体分为四个区域,代码区(反汇编),数据区(内存窗口),寄存器区和堆栈区,详细位置如下图:示例数据代码区最左侧为内存地址,第二块区域为程序代码值,原始程序代码经编译和汇编后变为二进制机器码存储在计算机中,调试器将其展示为易于阅读的十六进制,第三块区域是机器码反汇编后的汇编代码,最右侧为代码的注释窗口,有一些原始的注释,也可以自己添加注释PS:汇编和反汇编解释。

tusikong的博客 2923

UDP 调用connect的作用

https://www.cnblogs.com/bleopard/p/4004916.html 标准的udp客户端开了套接口后,一般使用sendto和recvfrom函数来发数据,最近看到ntpclient的代码里面是使用send函数直接法的,就分析了一下,原来udp发送数据有两种方法供大家选用的,顺便把udp的connect用法也就解释清楚了。 方法一:  socket-----&gt;sen...

$firecat利白的代码足迹$ 1281

DroidGuard虚拟机逆向解析:指令集、密钥派生与反调试机制

DroidGuard是Google在Android生态中部署的轻量级定制虚拟机,用于设备完整性校验。其核心原理是通过自解释字节码、多层混淆指令集与动态密钥派生机制,在ART运行时构建静默安全沙箱。技术价值在于规避传统API检测盲区,实现高鲁棒性环境感知;典型应用场景包括金融SDK风控、Play Services可信启动及合规性审计。本文深入拆解其4字节指令编码规则、基于设备指纹的三阶段密钥派生(SHA256→Feistel→AES)、以及五层反调试体系(ptrace快照、时间差分、内存页探测、指令流校验、服

weixin_32736961的博客 587

LabVIEW面向对象编程:操作者框架入门实战

本文是LabVIEW面向对象编程中操作者框架的入门实战指南。针对传统“面条式代码”在复杂项目中的维护难题,文章通过创建操作者、定义消息与处理函数、在主VI中调用等步骤,详细演示了如何利用操作者框架构建模块化、易扩展的应用程序架构,有效管理并行任务。

f0g1h2的博客 590

udp 使用connect优点_udp socket 调用connect的作用是什么

一般udpsocket 是不用调用connect函数的,那么在什么时候需要调用connect呢,或者说connect的作用是什么呢?套接字类型 write/send 不指定目的地址的sendto 指定目的地址的sendtotcp套接字...

weixin_36182916的博客 872

Transformer在CV里太耗算力?手把手拆解Restormer的MDTA与GDFN模块

本文深度解析了CVPR2022最佳论文提名作品Restormer的创新模块MDTA与GDFN,有效解决了Transformer在计算机视觉领域的高计算复杂度问题。通过通道注意力降维和门控前馈网络设计,Restormer在图像恢复重建任务中显著降低计算量,同时保持高性能,为实时图像处理提供了可行方案。

weixin_30258901的博客 445
上一篇: 使用BoundsChecker查找内存泄露
下一篇: linux系统单网卡绑定双IP的方法
萧山夜雨
博客等级 码龄24年 75粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值