您的位置:首页 > 理论基础 > 计算机网络

Unix网络编程之UDP实例

2016-05-10 12:55 573 查看
首先先看一下UDP客户/服务器交互的典型情形,如下图:



由上图可知,客户端程序不需要与服务器端建立连接,只需要调用sendto函数向服务器发送数据,或者调用recvfrom函数从服务器接收数据即可。最明显地特点就是服务器端只是比客户端多调用了一个bind函数来显式绑定一个端口。事实上客户端也可以通过bind来绑定端口,只不过没有那个必要。

实例代码:

//server.c

#include <stdlib.h>

#include <stdio.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <string.h>

int main()

{

    int sockfd;

    struct sockaddr_in servaddr,clientaddr;

    char recv[1024];

    socklen_t len;   

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

   

    memset(&servaddr, '\0', sizeof(servaddr));

    memset(recv, '\0', 1024);

    servaddr.sin_family = AF_INET;

    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    servaddr.sin_port = htons( 5000 );

    bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    for( ; ; )

    {

        recvfrom(sockfd, recv, 1024, 0, (struct sockaddr *)&clientaddr, &len);

        printf("%s\n", recv);

        memset(recv, '\0', 1024);

    }

    close(sockfd);

}

//client.c

#include <string.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/socket.h>

#include <netinet/in.h>

int main()

{

    int sockfd;

    struct sockaddr_in servaddr;

    memset(&servaddr, '\0', sizeof(servaddr));

    servaddr.sin_family = AF_INET;

    servaddr.sin_port = htons( 5000 );

    servaddr.sin_addr.s_addr = inet_addr("192.168.59.129");   

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    sendto(sockfd, "hello", 5, 0, (struct sockaddr *)&servaddr, sizeof(servaddr));

    close(sockfd);

    return 0;

}

基于UDP的服务器的特点:

1.在服务器端,应该提供的是一个迭代服务器,而不是像TCP服务器那样可以提供一个并发服务器。一般来说,大多数TCP服务器是并发的,而大多数UDP服务器是迭代的。

2.每一个UDP套接口都有一个接收缓冲区,到达该套接口的每个数据报都进入这个套接口接收缓冲区。当进程调用recvfrom时,缓冲区中的下一个数据报以FIFO顺序返回给进程。我们可以通过套接口选项来修改缓冲区的大小。

两个重要的函数:

#include <sys/socket.h>

ssize_t recvfrom ( int sockfd, void *buff, size_t nbytes, int flags, struct sockaddr *from, socklen_t *addrlen)

参数说明:

sockfd:标识一个已经打开的套接口描述字

buff:接收数据的缓冲区指针

nbytes:接收缓冲区的大小

flags:通常直接指定为0,也可以是图1.1中列出的一个或多个常值的逻辑或。

from:指向一个由函数返回的数据报发送者的协议地址的套接口地址结构,就是说可以通过这个参数得到发送者的一些信息

addrlen:指向一个整数的指针,该整数表示from所指向的空间的大小,可以通过sizeof来计算

返回值说明:

成功返回读写字节数,失败返回-1,除此之外,函数隐式返回了from,addrlen两个参数。

#include <sys/socket.h>

ssize_t sendto ( int sockfd, void *buff, size_t nbytes, int flags, const struct sockaddr *to, socklen_t addrlen)

参数说明:

sockfd:标识一个已经打开的套接口描述字

buff:发送数据的缓冲区指针

nbytes:发送缓冲区的大小

flags:通常直接指定为0,也可以是图1.1中列出的一个或多个常值的逻辑或。

to:指向一个数据报接收者的协议地址的套接口地址结构,就是说通过这个参数得到接受者的基本信息

addrlen:该整数表示to结构的大小,可以通过sizeof来计算
返回值说明:

成功返回读写字节数,失败返回-1

注意:

1.如果recvfrom的from参数时一个空指针,那么相应的长度参数addrlen也必须是一个空指针,表示我们并不关系数据发送者的协议地址(或者说我们不需要回复任何信息给数据发送者)。

2.recvfrom个sendto都可以用于TCP,但是通常并不这么做。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Unix网络编程