UDP,即用户数据报协议,是一种面向无连接的传输层协议。相比于TCP协议,UDP具有以下特点:
- 速度较快:由于UDP不需要建立连接和进行复杂的握手过程,因此在传输数据时速度稍快于TCP协议。
- 适用于简单的请求/应答应用程序:对于一些简单的、对可靠性要求不高的应用程序,如DNS查询和SNMP请求,UDP能够提供高效的传输服务。
- 不适用于海量数据传输:由于UDP不提供可靠的数据传输机制,因此在进行大数据传输时容易出现丢包和乱序的情况,不建议使用UDP进行此类传输。
- 广播和多播应用必须使用UDP:UDP支持广播和多播传输,因此对于需要进行广播和多播的应用,如视频直播和组播通信,必须使用UDP协议。
UDP应用:
UDP协议被广泛应用于各种网络应用中,包括但不限于以下几种:
- DNS(域名解析):DNS使用UDP进行域名解析请求和响应的传输,以提高查询速度。
- NFS(网络文件系统):NFS使用UDP进行文件操作请求和响应的传输,以提高文件访问速度。
- RTP(实时传输协议):RTP使用UDP进行实时音视频数据的传输,以减少延迟。
此外,一些实时性要求较高的应用,如在线游戏和VoIP通话,也会选择使用UDP协议来减少延迟,提高用户体验
Socket,也被称为"套接字",是网络编程中用于实现不同主机上进程间通信的一种技术。它提供了一种将网络通信抽象为文件操作的接口,使得程序员可以通过简单的函数调用来实现复杂的网络通信功能。
Socket的特点
- 文件描述符:Socket是一种文件描述符,它代表了一个通信管道的端点。通过Socket,我们可以像操作文件一样,使用read、write、close等函数来发送和接收网络数据。
- 通信端点:Socket是网络通信的端点,每个Socket都有一个唯一的地址,通过这个地址,我们可以与远程主机上的Socket进行通信。
- 网络数据操作:通过Socket,我们可以方便地进行网络数据的发送和接收。Socket提供了丰富的函数接口,如send、recv、sendto、recvfrom等,用于各种网络数据操作。
- Socket函数:要获得一个Socket,我们需要调用socket()函数。该函数返回一个Socket描述符,用于后续的网络通信操作。
Socket的分类
根据使用的协议和通信方式的不同,Socket可以分为以下几种类型:
- SOCK_STREAM:流式套接字,用于TCP协议。它提供了可靠的、面向连接的通信方式,数据以流的形式传输,可以保证数据的可靠性和顺序性。
- SOCK_DGRAM:数据报套接字,用于UDP协议。它提供了不可靠、无连接的通信方式,数据以数据报的形式传输,不保证数据的可靠性和顺序性。
- SOCK_RAW:原始套接字,用于其他层次的协议操作。它允许直接访问网络层数据,可以用于实现自定义的网络协议。
UDP网络编程流程:
服务器: 创建套接字 socket( )
将服务器的ip地址、端口号与套接字进行绑定 bind( )
接收数据 recvfrom()
发送数据 sendto()
客户端: 创建套接字 socket()
发送数据 sendto()
接收数据 recvfrom()
关闭套接字 close()
特点
- 创建套接字时,系统不会分配端口
- 创建的套接字默认属性是主动的,即主动发起服务的请求;当作为服务器时,往往需要修改为被动的
使用函数创建了一个UDP类型的套接字,并打印出该套接字的文件描述符。如果创建套接字失败,则会输出错误信息并退出程序。
执行结果
在网络编程中经常使用的结构体
头文件:#include <netinet/in.h>
为了使不同格式地址能被传入套接字函数,地址须要强制转换成通用套接字地址结构,原因是因为不同场合所使用的结构体不一样,但是调用的函数却是同一个,所以定义一个通用结构体,当在指定场合使用时,在根据要求传入指定的结构体即可
通用结构体 sockaddr
头文件:#include
在定义源地址和目的地址结构的时候,选用struct sockaddr_in;
例:
struct sockaddr_in my_addr;
当调用编程接口函数,且该函数需要传入地址结构时需要用struct sockaddr进行强制转换
例:
bind(sockfd,(struct sockaddr*)&my_addr,sizeof(my_addr));
功能: 函数用于通过套接字发送数据。
参数:
- :文件描述符,由函数返回。
- :指向要发送数据的缓冲区的指针。
- :要发送的数据的长度。
- :标志位,用于指定发送操作的行为。常见的标志位有:
- :阻塞模式,函数会一直等待直到数据发送完成。
- :非阻塞模式,如果数据不能立即发送,函数会立即返回错误。
- :指向目的网络信息结构体的指针,用于指定数据发送的目标地址。
- :目的网络信息结构体的长度。
返回值:
- 成功:返回发送的字节数。
- 失败:返回-1,并设置以指示错误原因。
函数是网络编程中常用的函数之一,它允许我们向指定的目标地址发送数据。在使用该函数时,我们需要正确地指定目的地址和地址长度,以确保数据能够准确地发送到目标。同时,我们也需要注意选择合适的标志位,以满足不同的发送需求。
我们用一个“网络调试助手”的软件来模拟服务器,给服务器发送消息。
客户端的代码编写
执行结果
UDP网络程序想要收取数据需什么条件?
确定的ip地址
确定的port
怎样完成上面的条件呢?
接收端 使用bind函数,来完成地址结构与socket套接字的绑定,这样ip、port就固定 了 发送端 在sendto函数中指定接收端的ip、port,就可以发送数据了
由于服务器是被动的,客户端是主动的,所以一般先运行服务器,后运行客户端,所以服务 器需要固定自己的信息(ip地址和端口号),这样客户端才可以找到服务器并与之通信,但 是客户端一般不需要bind绑定,因为系统会自动给客户端分配ip地址和端口号
此时我们把刚刚也用到过的网络调试助手作为客户端,ubuntu的程序作为服务器
设置服务器(ubuntu程序)
执行结果
接下来我们就可以自己实现服务器与客户端互发消息了
1、本地IP、本地端口(我是谁)
2、目的IP、目的端口(发给谁)
3、在客户端的代码中,我们只设置了目的IP、目的端口
客户端的本地ip、本地port是我们调用sendto的时候linux系统底层自动给客户端分配 的;分配端口的方式为随机分配,即每次运行系统给的port不一样
1、服务器之所以要bind是因为它的本地port需要是固定,而不是随机的
2、服务器也可以主动地给客户端发送数据
3、客户端也可以用bind,这样客户端的本地端口就是固定的了,但一般不这样做
执行的结果
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/11926.html