1. 基本介绍
UDP是一种无连接不可靠的协议,客户端无需与服务器连接起来便可以直接向服务器发送数据,对于不需要发送大量数据的客户端比如DNS等,是比较方便。但是方便也意味着容易出问题,比如可靠性、安全性等,比如另一台PC就可以伪装成服务器向客户端发送错误的信息,我对这方面还不了解,所以就不讨论了。
虽然说UDP是一种无连接的协议,但也是可以通过connect函数进行“伪连接”的。所谓“伪连接”就是只是connect的一端在维护对端的信息而已。
2. 函数
UDP相关的函数主要有:
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags,
struct sockaddr *from, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buff, size_t nbytes, int flags,
truct sockaddr *to,socklen_t addrlen);
其中ssize_t数据类型用来表示所写数据的长度。
对于recvfrom函数,我们可以看成是TCP中accept函数和read函数的结合,前三个参数是read的参数,后两个参数是accept的参数。由于对TCP是可靠连接,只需要accept一次就行,所以不需要在read的时候加上对端的地址。而UDP是无连接的,如果我们想要知道数据来源,则可以通过调用recvfrom后最后两个参数的结果获取。当然我们也可以将from参数设置为NULL,此时addrlen也必须是一个空指针,表示我们不关心数据者的协议地址。如果我们只接受来自某个地址的数据,则就必须要加上这个地址了,因为需要通过这个参数来进行源地址的手动过滤,虽然我们也可以用connect函数实现,但二者的原理似乎是不太一样的,后者是内核帮我们进行了过滤。
对于sendto函数,则可以看成是TCP中connect函数和send函数的结合,前三个参数是send的参数,后两个参数则是connect的参数。TCP是可靠连接,只需要connect一次就行,所以send的时候不需要指定对端的地址。而UDP是不可靠的,每次sendto必须要指定对端的地址。
对于简单的UDP程序,一般将flags参数设置成0。
下面是UNP中一个简单的UDP程序。
/* unpudpcli.c */
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
void
dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
{
int n;
char sendline[MAXLINE], recvline[MAXLINE + 1];
while ( fgets(sendline, MAXLINE, fp) != NULL ) {
sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);
n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
recvline[n] = '\0';
fputs(recvline, stdout);
}
}
int
main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
if ( argc != 2 ) {
err_quit("usage: udpcli <IPaddress&g