Unix网络编程-UDP客户端服务器示例(1)

UDP客户端/服务器示例

一个简单的UDP客户端/服务器程序示例,这个简单的例子执行如下步骤的一个回射服务器:

1) 客户端从标准输入读入一行文本,并写给服务端

2) 服务端从网络输入读入一行文本,并回射给客户端

3) 客户端从网络输入读入这行回射的文件,并显示在标准输出上。

下图描述了这个简单的客户/服务器:

UDP回射服务器程序

UDP服务器回射函数

1) 我们通过将socket函数的第二个参数指定为SOCK_DGRAM创建一个UDP套接字。像TCP服务器程序一样,用bind的服务器IPV4被指定为INADDR_ANY,并且指定一个总所周知的端口。

2) 通过一个简单的循环,他使用recvfrom读入下一个到达服务器端口的数据报,再使用sendto把他发送给发送者。

尽管这个回射函数很简单,不过也有许多细节问题需要考虑。

1) 该函数永不终止,因为UDP是一个无连接的协议,他没有像TCP中EOF之类的东西。

2) 该函数提供的是一个迭代服务器(iterative server),而不是像TCP服务器那样可以提供一个并发服务器。其中没有对fork的调用,因此单个服务器进程就得处理所有客户。一般来说,大多数TCP服务器是并发的,而大多数UDP服务器是迭代的。

3) 对于本套接字,UDP层中隐含有排队发生。事实上每个UDP套接字都有一个接收缓冲区,到达该套接字的每个数据报以FIFO(先入先出)顺序返回给进程。这样,在进程能够读该套接字中任何已排好的数据报之前,如果有多个数据报到达该套接字,那么相继到达的数据报仅仅加到该套接字的接收缓冲区中。然而这个缓冲区的大小是有限的。可以使用SO_RCVBUF套接字选项讨论这个大小以及如何增大他。

UDP和TCP服务端接收客户端连接情况

TCP

UDP

UDP客户端程序

UDP客户端回射函数

我们的客户未请求内核给他的套接字指派一个临时端口。(对于TCP客户而言,我们说过connect调用正是这种指派发生之处。)对于一个UDP套接字,如果其进程首次调用sendto时他没有绑定一个本地端口,那么内核就在此时为他选择一个临时端口。跟TCP一样,客户可以显示的调用bind,不过很少这样做。

注意,调用recvfrom指定的第五和第六个参数是空指针。这告诉我们不关心应答数据报由谁发送。这样做有一个风险:任何进程都可以向本客户的IP地址和端口发送数据报,这些数据报将被客户读入并被认为是服务的应答。