📜  UDP Server-Client在C中的实现

📅  最后修改于: 2021-05-28 04:38:25             🧑  作者: Mango

在主机之间进行通信的主要传输层协议有两种: TCPUDP 。在上一篇文章中讨论了创建TCP服务器/客户端。

先决条件:创建TCP服务器/客户端

理论
在UDP中,客户端不像TCP中那样与服务器建立连接,而是仅发送数据报。同样,服务器不需要接受连接,而只是等待数据报到达。到达的数据报包含发送方的地址,服务器用来将数据发送到正确的客户端。
UDP客户端/服务器功能调用

整个过程可以分为以下步骤:
UDP服务器:

  1. 创建UDP套接字。
  2. 将套接字绑定到服务器地址。
  3. 等到数据报包从客户端到达。
  4. 处理数据报包,并向客户端发送回复。
  5. 返回步骤3。

UDP客户端:

  1. 创建UDP套接字。
  2. 发送消息到服务器。
  3. 等待直到收到服务器的响应。
  4. 处理答复,并在必要时返回步骤2。
  5. 关闭套接字描述符并退出。

必要功能:

int socket(int domain, int type, int protocol)
Creates an unbound socket in the specified domain.
Returns socket file descriptor.

参数:
域–指定通信
域(用于IPv4的AF_INET /用于IPv6的AF_INET6)
type –要创建的套接字类型
(TCP的SOCK_STREAM / UDP的SOCK_DGRAM)
protocol –套接字使用的协议。
0表示对地址系列使用默认协议。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
Assigns address to the unbound socket.

参数:
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)
Send a message on the socket

参数:
sockfd –套接字的文件描述符
buf –包含要发送的数据的应用程序缓冲区
len – buf应用程序缓冲区的大小
标志–标志的按位或运算以修改套接字行为
dest_addr –包含目标地址的结构
addrlen – dest_addr结构的大小

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                 struct sockaddr *src_addr, socklen_t *addrlen)
Receive a message from the socket.

参数:
sockfd –套接字的文件描述符
buf –在其中接收数据的应用程序缓冲区
len – buf应用程序缓冲区的大小
标志–标志的按位或运算以修改套接字行为
src_addr –返回包含源地址的结构
addrlen –返回src_addr结构大小的变量

int close(int fd)
Close a file descriptor

参数:
fd –文件描述符

在下面的代码中,显示了服务器和客户端之间的一个hello消息交换,以演示该模型。

UDPServer.c
// Server side implementation of UDP client-server model
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
  
#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] = '\0';
    printf("Client : %s\n", buffer);
    sendto(sockfd, (const char *)hello, strlen(hello), 
        MSG_CONFIRM, (const struct sockaddr *) &cliaddr,
            len);
    printf("Hello message sent.\n"); 
      
    return 0;
}


UDPClient.c
// Client side implementation of UDP client-server model
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
  
#define PORT     8080
#define MAXLINE 1024
  
// Driver code
int main() {
    int sockfd;
    char buffer[MAXLINE];
    char *hello = "Hello from client";
    struct sockaddr_in     servaddr;
  
    // 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));
      
    // Filling server information
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(PORT);
    servaddr.sin_addr.s_addr = INADDR_ANY;
      
    int n, len;
      
    sendto(sockfd, (const char *)hello, strlen(hello),
        MSG_CONFIRM, (const struct sockaddr *) &servaddr, 
            sizeof(servaddr));
    printf("Hello message sent.\n");
          
    n = recvfrom(sockfd, (char *)buffer, MAXLINE, 
                MSG_WAITALL, (struct sockaddr *) &servaddr,
                &len);
    buffer[n] = '\0';
    printf("Server : %s\n", buffer);
  
    close(sockfd);
    return 0;
}


输出 :

$ ./server
Client : Hello from client
Hello message sent.
$ ./client
Hello message sent.
Server : Hello from server

想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。