基本UDP套接字编程

7.1 概述

TCP和UDP网络编程存在一些本质的差异,主要是由于传输层的差别:UDP是无连接的不可靠的数据报协议,而TCP是面向连接的字节流协议。

下图是典型的UDP客户端和服务器之间的通信流程。客户不与服务器建立连接,而是只管使用sendto函数。服务器不接受来自客户的连接,而是只管调用recvfrom函数,等待某个客户的数据到达。

image

7.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);

recvfrom的参数说明如下。

  • socket:创建的套接字描述符
  • buffer:指向输入缓冲区的指针
  • length:缓冲区大小
  • flags:在本文中,可以将 flags 置为0即可
  • src_addr:指向客户套接字地址的指针
  • src_len:地址长度
  • recvfrom的返回值为读入数据的长度。

ssize_t sendto(int sockfd, const void *buf, size_t nbytes, int flags, const struct sockaddr *to, socklen_t addrlen);
/*以上函数返回:成功返回读或写到的字节数,出错返回-1*/

sendto函数的参数说明如下:

  • socket:创建的套接字描述符
  • buffer:输出缓冲区的指针
  • length:缓冲区大小
  • flags:正常应用中,flags一般设置为0
  • dest_addr:指向服务器套接字地址的指针
  • dest_len:地址长度

前三个参数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,尽管通常不这么做。

7.3 UDP套接字编程流程

  1. 创建套接字
  2. 命名套接字
  3. 在服务器端,等待客户的消息
  4. 在客户端,发送客户消息
  5. 关闭套接字
7.3.1 创建套接字

可以使用系统调用socket来创建一个套接字并返回该套接字的文件描述符。

#include <sys/socket.h>

int socket(int domain, int type, int protocol);
7.3.2 命名套接字

要想让创建的套接字可以被其他进程使用,那必须给该套接字命名。对套接字命名的意思是指将该套接字关联一个IP地址和端口号,可以使用系统调用bind来实现。

#include <sys/socket.h>

int bind(int socket, const struct sockaddr *address, size_t address_len);

bind系统调用把参数address中的地址分配给与文件描述符socket关联的套接字,地址结构的长度由参数address_len传递。

7.3.3 接收/发送消息

不同于TCP提供的面向连接的可靠字节流协议,UDP 是无连接不可靠的数据报协议。服务器不接收来自客户的连接,而只管调用recvfrom系统调用,等待客户的数据到达。recvfrom的声明如下:

#include <sys/socket.h>

int recvfrom(int socket, void *buffer, size_t length, int flags, struct sockaddr *src_addr, socklen_t *src_len);

UDP是无连接的,故客户可以直接向服务器发送消息而不需要建立连接。客户使用sendto系统调用向服务器发送消息:

#include <sys/socket.h>

int sendto(int socket, const void *buffer, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len);
7.3.4 关闭套接字

操作系统为每个套接字分配了一个文件描述符,为了让操作系统回收该文件描述符,可以使用 close 系统调用:

close(fd);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值