Unix网络编程之UDP实例

首先先看一下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,但是通常并不这么做。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值