C中的UDP服务器-客户端实现
添加时间:2022-02-27 15:56:23
来源:
添加时间:2022-02-27 15:56:23
防伪码:CMSEASYyGCGSM4kbrKxxzn770
主机之间通信有两种主要的传输层协议:TCP和UDP。创建 TCP Server/Client 已在上一篇文章中讨论过。
先决条件:创建 TCP 服务器/客户端
理论
在 UDP 中,客户端不会像 TCP 那样与服务器形成连接,而只是发送数据报。同样,服务器不需要接受连接,只是等待数据报到达。到达时的数据报包含服务器用来向正确客户端发送数据的发送者地址。
UDP 客户端/服务器函数调用
整个过程可以分解为以下步骤:
UDP服务器:
创建一个 UDP 套接字。
将套接字绑定到服务器地址。
等到数据报包从客户端到达。
处理数据报包并向客户端发送回复。
返回第 3 步。
UDP客户端:
创建一个 UDP 套接字。
向服务器发送消息。
等到收到来自服务器的响应。
如有必要,处理回复并返回步骤 2。
关闭套接字描述符并退出。
必要功能:
int socket(int domain, int type, int protocol)
在指定域中创建一个未绑定的套接字。
返回套接字文件描述符。
参数:
domain –指定通信
域(AF_INET 代表 IPv4/AF_INET6 代表 IPv6)
类型 –要创建的套接字类型
(SOCK_STREAM 代表 TCP / SOCK_DGRAM 代表 UDP)
协议 –套接字使用的协议。
0 表示使用地址族的默认协议。
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
将地址分配给未绑定的套接字。
参数:
sockfd -要绑定的套接字的文件描述符
addr -指定要绑定到 的地址的结构
addrlen - addr结构 的大小
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen)
在套接字上发送消息
参数:
sockfd –套接字的文件描述符
buf –包含要发送的数据 的应用程序缓冲区
len – buf应用程序缓冲区 的大小
flags –修改套接字行为的标志位或
dest_addr –包含目标地址的结构
addrlen – dest_addr的大小结构体
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
结构 sockaddr *src_addr, socklen_t *addrlen)
从套接字接收消息。
参数:
sockfd –套接字的文件描述符
buf –接收数据 的应用程序缓冲区
len – buf应用程序缓冲区 的大小
flags –修改套接字行为的标志位或
src_addr –返回包含源地址的结构
addrlen –大小的变量返回src_addr结构
整数关闭(int fd)
关闭文件描述符
论据:
fd -文件描述符
在下面的代码中,显示了服务器和客户端之间交换一条 hello 消息来演示该模型。
文件名:UDPServer.c
// Server side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define MAXLINE 1024
// Driver code
int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from server";
struct sockaddr_in servaddr, cliaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
// Bind the socket with the server address
if ( bind(sockfd, (const struct sockaddr *)&servaddr,
sizeof(servaddr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
int len, n;
len = sizeof(cliaddr); //len is value/resuslt
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, ( struct sockaddr *) &cliaddr,
&len);
buffer[n] = '