C语言实现UDP通信

yizhihongxing

下面是C语言实现UDP通信的完整攻略。

1. 确定需要使用的库和头文件

首先需要引入的头文件有:

#include <stdio.h>      //标准输入输出库
#include <stdlib.h>     //标准库
#include <string.h>     //字符串处理库
#include <unistd.h>     //Unix标准函数库
#include <sys/types.h>  //Unix/Linux系统基本类型定义
#include <sys/socket.h> //套接字函数库
#include <netinet/in.h> //IP地址和端口号定义

2. 创建UDP套接字

在准备使用UDP套接字之前,需要先调用 socket() 方法创建一个套接字。该方法接受三个参数:

int socket(int domain, int type, int protocol);

其中:

  • domain:协议域(通常是 AF_INET,表示TCP/IP协议);
  • type:套接字类型(通常是 SOCK_DGRAM,表示UDP套接字);
  • protocol:协议类型,通常为 0,表示默认协议。

创建UDP套接字的代码示例如下:

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

3. 套接字绑定地址和端口号

在创建UDP套接字后,需要将其绑定到一个本地地址和端口号上,以便于其他进程能够发送数据到该端口。可使用 bind() 方法进行绑定,该方法接受两个参数:

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

其中:

  • sockfd:创建好的套接字;
  • addr:要绑定的地址和端口号;
  • addrlen:地址和端口号的长度。

代码示例如下:

struct sockaddr_in addr;
addr.sin_family = AF_INET;              //协议域
addr.sin_port = htons(PORT);            //端口号
addr.sin_addr.s_addr = htonl(INADDR_ANY);//IP地址(在本机的任何一个IP上都能够接收到信息)

if(bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
    printf("Bind Error.\n");
    return 0;
}

4. 发送UDP数据

在UDP通信中,发送数据时使用 sendto()方法。该方法接受四个参数:

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

其中:

  • sockfd:创建好的套接字;
  • buf:发送的数据内容;
  • len:发送的数据长度;
  • flags:调用操作方式,通常为 0
  • dest_addr:目标地址和端口号;
  • addrlen:目标地址和端口号的长度。

代码示例如下:

char sendbuf[1024] = "hello, this is a message from client.";
int sendbytes = sendto(sockfd, sendbuf, strlen(sendbuf), 0, (struct sockaddr *)&addr, sizeof(struct sockaddr));

5. 接收UDP数据

在UDP通信中,接收数据时使用 recvfrom() 方法。该方法接受五个参数:

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

其中:

  • sockfd:创建好的套接字;
  • buf:接收到的数据内容;
  • len:接收数据的最大长度;
  • flags:调用操作方式,通常为 0
  • src_addr:发送方的地址和端口号;
  • addrlen:发送方的地址和端口号的长度。

代码示例如下:

char recvbuf[1024] = "";
struct sockaddr_in fromaddr;
socklen_t fromlen = sizeof(fromaddr);
int recvbytes = recvfrom(sockfd, recvbuf, 1024, 0, (struct sockaddr *)&fromaddr, &fromlen);
printf("Received message: %s\n", recvbuf);

示例说明

以下是一个简单的UDP客户端和服务器示例,可以直接运行在Linux上:

服务器

服务器会监听一个指定的端口,等待客户端发送信息。每当接收到客户端发来的信息时,会将消息打印出来,并向客户端回复一条信息。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 8888

int main(int argc, char *argv[]) {
    int sockfd;
    if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        printf("Socket Error.\n");
        return 0;
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;              //协议域
    addr.sin_port = htons(PORT);            //端口号
    addr.sin_addr.s_addr = htonl(INADDR_ANY);//IP地址(在本机的任何一个IP上都能够接收到信息)

    if(bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
        printf("Bind Error.\n");
        return 0;
    }
    printf("======Waiting for client's request======\n");

    char sendbuf[1024] = "";
    char recvbuf[1024] = "";
    struct sockaddr_in fromaddr;
    socklen_t fromlen = sizeof(fromaddr);
    while(1) {
        //receieve the message
        int recvbytes = recvfrom(sockfd, recvbuf, 1024, 0, (struct sockaddr *)&fromaddr, &fromlen);
        if(recvbytes == -1) {
            printf("Receive Error.\n");
            break;
        }
        recvbuf[recvbytes] = 0;

        char *client_ip = inet_ntoa(fromaddr.sin_addr);
        printf("[Received From %s:%u]> %s\n", client_ip, ntohs(fromaddr.sin_port), recvbuf);

        //send back to client
        sprintf(sendbuf, "Your message has been received.");
        int sendbytes = sendto(sockfd, sendbuf, strlen(sendbuf), 0, (struct sockaddr *)&fromaddr, fromlen);
        if(sendbytes == -1) {
            printf("Send Error.\n");
            break;
        }
    }

    close(sockfd);
    return 0;
}

客户端

客户端会向服务器发送一条信息,并等待服务器回复。当收到服务器的回复时,会将消息打印出来。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 8888

struct sockaddr_in addr;

int main(int argc, char *argv[]) {
    int sockfd;
    if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        printf("Socket Error.\n");
        return 0;
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    char sendbuf[1024] = "hello, this is a message from client.";
    char recvbuf[1024] = "";
    int sendbytes = sendto(sockfd, sendbuf, strlen(sendbuf), 0, (struct sockaddr *)&addr, sizeof(struct sockaddr));
    if(sendbytes == -1) {
        printf("Send Error.\n");
        return 0;
    }

    int recvbytes = recvfrom(sockfd, recvbuf, 1024, 0, (struct sockaddr *)&addr, (socklen_t *)&sizeof(struct sockaddr));
    if(recvbytes == -1) {
        printf("Receive Error.\n");
        return 0;
    }
    recvbuf[recvbytes] = 0;

    printf("Receive: %s\n", recvbuf);

    close(sockfd);
    return 0;
}

这样,我们就成功地用C语言实现了UDP通信。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言实现UDP通信 - Python技术站

(1)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • C 共用体

    C语言共用体(Union)完整使用攻略 共用体(Union)是C语言中一种特殊的数据类型,与结构体(Struct)类似,也是一种复合类型。共用体允许不同的数据类型在相同的内存空间里互相转换使用,这意味着在同一时间只能保存相同的数据类型,但可以在不同的时间存储不同的数据类型。 创建共用体 共用体和结构体的方式非常相似,可以使用关键字union来定义共用体,例如…

    C 2023年5月10日
    00
  • 初学C语言基本运算和表达式

    初学C语言基本运算和表达式攻略 C语言是一门计算机编程语言,基本运算和表达式是C语言编程中的基础知识点。在学习这一部分内容时,需要掌握以下知识点: 基本运算符 表达式的运算顺序 数据类型的转换 下面我们来一步步了解这些知识点。 基本运算符 在C语言中,基本运算符包括算术运算符、关系运算符、逻辑运算符和位运算符。 算术运算符 算术运算符包括加(+)、减(-)、…

    C 2023年5月23日
    00
  • C&C++设计风格选择 命名规范

    C/C++设计风格选择 什么是代码风格 代码风格是指编写代码时所遵循的规范和习惯,它涉及到如下几个方面: 命名规则(变量名、函数名、常量名等) 缩进和布局(tab还是空格、括号位置等) 注释规则(注释的格式、位置等) 代码组织(使用头文件、源文件等) 恰当的代码风格可以使程序更加清晰明了,便于日后的维护和修改。 C/C++代码风格 C/C++是一种老牌编程语…

    C 2023年5月23日
    00
  • C语言之如何求三次方根

    C语言之如何求三次方根 在C语言中,求一个数的三次方根可以使用数学库中的pow()函数,但是这会增加程序的复杂度和开销。另一种方法是通过迭代逐步逼近三次方根的解,这种方法效率高,适合在不使用数学库的情况下求解三次方根。 方案原理 设正数n的三次方根为x,则有: $$ x^3 = n $$ 两边同时取平方根,得到: $$ x^2 = \sqrt{n} $$ 继…

    C 2023年5月23日
    00
  • C++实现Dijkstra(迪杰斯特拉)算法

    下面我将为你讲解如何使用C++实现Dijkstra(迪杰斯特拉)算法。 Dijkstra算法简介 Dijkstra算法是解决单源最短路径问题的一种贪心算法。Dijkstra算法最初是由荷兰的计算机科学家Edsger W. Dijkstra于1956年提出的。该算法的思路是从起点开始,依次访问每个相邻节点,确定从起点到该节点的最短路径,并将该节点标记为已访问。…

    C 2023年5月22日
    00
  • 深入数据库通用的连接方式详解

    深入数据库通用的连接方式详解 在使用数据库时,我们需要连接数据库才能操作数据库。下面将介绍一些通用的连接方式,其中包括主流的两种数据库:MySQL和PostgreSQL。 MySQL连接方式 MySQL连接方式主要有三种:使用命令行连接、使用图形化界面连接和使用编程语言连接。下面将对三种连接方式进行介绍。 使用命令行连接 使用命令行连接MySQL需要使用My…

    C 2023年5月22日
    00
  • Win10蓝屏代码0xc0000034怎么办?

    Win10蓝屏代码0xc0000034的解决方法 当Windows10出现蓝屏并显示错误代码0xc0000034时,我们可以按照以下步骤来解决这个问题。 步骤1:检查硬件问题 此错误通常是由于硬件问题引起的。首先,我们需要检查相关硬件是否正常工作,特别是新安装的硬件或故障的硬件。 步骤2:尝试系统修复 在出现蓝屏之后,我们可以尝试使用Windows的自带工具…

    C 2023年5月23日
    00
  • C语言实现绘制绕线画的示例代码

    让我来详细讲解一下“C语言实现绘制绕线画的示例代码”的完整攻略。 简介 绕线画是一种以连续无间断的曲线来填充一定区域的绘画技法,它最早出现在中国画、漫画、素描等领域,现在已经在计算机绘图领域得到了广泛的应用。在本文中,我们将基于C语言实现绘制绕线画的示例代码,向大家展示如何通过编程来实现这一绘画技巧。 准备工作 在开始编写代码前,我们需要了解一些基本知识,包…

    C 2023年5月24日
    00
合作推广
合作推广
分享本页
返回顶部