首页 > 其他分享 >UDP双向通信

UDP双向通信

时间:2024-06-10 21:10:54浏览次数:20  
标签:UDP 双向通信 sockfd 服务器 接字 include servaddr 客户端

UDP的双向通信

双向交替通信(Alternating Bidirectional Communication):在这种方式下,通过约定一方作为发送方,一方作为接收方,双方交替发送和接收数据。例如,一方发送数据报给另一方,然后等待对方的回应,对方接收数据报后进行处理,然后发送回应给发送方,交替进行下去。

UDP 客户端-服务器通信代码说明

概述

本文档提供了用 C 语言编写的简单 UDP 客户端-服务器通信系统的概览和使用说明。服务器接收来自客户端的消息,允许用户输入响应,并将其发送回客户端。客户端向服务器发送消息并显示服务器的响应。

  • 服务器代码

服务器代码设置了一个 UDP 套接字,绑定到指定端口,并监听来自客户端的消息。收到消息后,它会提示用户输入回复,然后将回复发送回客户端。

  • 客户端代码

客户端代码建立了一个 UDP 套接字,并向服务器的 IP 地址和端口发送消息。然后,它等待服务器的响应并将其打印出来。

限制和改进

  • 限制:
  1. 阻塞 I/O:客户端和服务器都使用阻塞 I/O 操作(recvfromsendto)。这意味着服务器一次只能处理一个客户端,客户端必须等待服务器的响应才能继续。
  2. 无并发处理:服务器不支持同时处理多个客户端,这限制了其可扩展性。
  3. 硬编码值:IP 地址和端口被硬编码,这降低了灵活性和可重用性。
  4. 缺乏错误处理:网络操作几乎没有错误处理,可能导致崩溃或未定义的行为。
  5. 安全性:代码没有实现任何加密或认证,使其容易受到拦截和未经授权的访问。
  • 改进:
  1. 非阻塞 I/O 或多线程:实现非阻塞 I/O 或使用多线程同时处理多个客户端。
  2. 配置文件:使用配置文件或命令行参数来指定 IP 地址和端口。
  3. 健壮的错误处理:添加全面的错误处理,以优雅地管理网络错误。
  4. 安全增强:集成加密(如 TLS)和认证机制来保护通信。
  5. 用户界面:为服务器开发一个用户友好的界面,以更有效地管理收到的消息和回复。

使用说明

  1. 编译:服务端**gcc UDP_server.c -o server** 客户端 **gcc UDP_client.c -o client**
  2. 首先运行服务器程序,确保它正在监听传入的消息。
  3. 执行客户端程序,向服务器发送消息并接收回复。
  4. 本次所写的代码只能实现1:1的回复。

相关代码

服务端代码

  1. 初始化变量:定义套接字描述符 sockfd,缓冲区 bufferreply,以及服务器和客户端的地址结构 servaddrcliaddr
  2. 创建套接字:调用 socket() 函数创建一个 UDP 套接字。
  3. 设置服务器地址:将服务器地址结构 servaddr 清零,并设置地址族为 IPv4 (AF_INET),IP 地址设置为 INADDR_ANY(接受任何来自本机的 IP 地址),端口号设置为 PORT
  4. 绑定套接字:使用 bind() 函数将 sockfd 绑定到服务器的 IP 地址和端口号。
  5. 处理客户端消息:进入一个无限循环,使用 recvfrom() 函数接收来自客户端的消息,并将其存储在 buffer 中。
  6. 获取并发送回复:提示用户输入回复消息,使用 fgets() 从标准输入读取字符串,然后使用 sendto() 函数将回复发送给客户端。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 12345
#define MAXLINE 1024

int main() {
    int sockfd;
    char buffer[MAXLINE];
    char reply[MAXLINE];
    struct sockaddr_in servaddr, cliaddr;

    // 创建UDP套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    memset(&cliaddr, 0, sizeof(cliaddr));

    // 填充服务器信息
    servaddr.sin_family = AF_INET; // IPv4
    servaddr.sin_addr.s_addr = INADDR_ANY;
    servaddr.sin_port = htons(PORT);

    // 绑定套接字与地址
    if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    while (1) {
        socklen_t len = sizeof(cliaddr);
        int n = recvfrom(sockfd, buffer, MAXLINE, 0, (struct sockaddr *) &cliaddr, &len);
        buffer[n] = '\0'; // null terminate
        printf("Client's message: %s\n", buffer);

        // 获取服务器的回复
        printf("Enter reply message: ");
        fgets(reply, MAXLINE, stdin);

        // 移除换行符
        reply[strcspn(reply, "\n")] = 0;

        // 回复客户端
        sendto(sockfd, reply, strlen(reply), 0, (struct sockaddr *) &cliaddr, len);
        printf("Reply sent to client.\n");
    }

    // 关闭套接字
    close(sockfd);
    return 0;
}

客户端代码

  1. 初始化变量:定义套接字描述符 sockfd,发送和接收缓冲区 sendlinerecvline,以及服务器地址结构 servaddr
  2. 创建套接字:调用 socket() 函数创建一个 UDP 套接字。
  3. 设置服务器地址:将服务器地址结构 servaddr 清零,并设置地址族为 IPv4 (AF_INET),服务器 IP 地址和端口号。
  4. 发送和接收消息:进入一个无限循环,使用 fgets() 函数从标准输入获取消息,然后使用 sendto() 函数发送消息给服务器。之后,使用 recvfrom() 函数接收服务器的回复。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_PORT 12345
#define SERVER_IP "127.0.0.1"
#define MAXLINE 1024

int main() {
    int sockfd;
    struct sockaddr_in servaddr;
    char sendline[MAXLINE], recvline[MAXLINE + 1];
    socklen_t len;

    // 创建UDP套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&servaddr, 0, sizeof(servaddr));

    // 填充服务器信息
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERVER_PORT);
    servaddr.sin_addr.s_addr = inet_addr(SERVER_IP);

    while (1) {
        printf("Enter the message to send: ");
        fgets(sendline, MAXLINE, stdin);

        // 发送消息给服务器
        sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr *) &servaddr, sizeof(servaddr));

        // 接收服务器的回复
        len = sizeof(servaddr);
        int n = recvfrom(sockfd, recvline, MAXLINE, 0, (struct sockaddr *) &servaddr, &len);
        recvline[n] = '\0'; // null terminate
        printf("Server's reply: %s\n", recvline);
    }

    // 关闭套接字
    close(sockfd);
    return 0;
}

相关链接:https://www.jianshu.com/p/373c2934e1fe

标签:UDP,双向通信,sockfd,服务器,接字,include,servaddr,客户端
From: https://www.cnblogs.com/banon/p/18241044

相关文章

  • 【QT5】<总览五> QT多线程、TCP/UDP
    文章目录前言一、QThread多线程二、QT中的TCP编程1.TCP简介2.服务端程序编写3.客户端程序编写4.服务端与客户端测试三、QT中的UDP编程1.UDP简介2.UDP单播与广播程序前言承接【QT5】<总览四>QT常见绘图、图表及动画。若存在版权问题,请联系作者删除!一、QThre......
  • UDP报文结构
    学习一个协议,首先就是去理解它的报文结构。UDP数据报可以分为报头与载荷两个部分。报头占八个字节,分别是源端口号,目的端口号,udp报文长度,UDP校验和,每个部分占两个字节。载荷是完整的应用层的数据报。报头和载荷可以认为是“拼接“在一起。UDP报文长度:是一个两个字节的16位的......
  • JAVAEE之网络编程(1)_套接字、UDP数据报套接字编程及从代码实例
    前言什么是网络编程呢? 网络编程,指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。当然,即便是同一个主机,只要是不同进程,基于网络来传输数据,也属于网络编程一、网路编程中的基本概念1.1发送端和接收端发送端:数据的发送方进程,称为发送端。发......
  • 【Socket】解决UDP丢包问题
    一、介绍UDP是一种不可靠的、无连接的、基于数据报的传输层协议。相比于TCP就比较简单,像写信一样,直接打包丢过去,就不用管了,而不用TCP这样的反复确认。所以UDP的优势就是速度快,开销小。但是随之而来的就是不稳定,面向无连接的,无法确认数据包。会导致丢包问题。二、丢包原因1、服......
  • UDP——实现C/S架构,有一台服务器,服务器中存储n首音频,要求客户端可以直接下载服务器的
    实现C/S架构,有一台服务器,服务器中存储n首音频,要求客户端可以直接下载服务器的音频,并且可以正常在客户端播放。服务器/*************************************************************************************************************************** filename: udp_ser......
  • socket 实现udp组播通信
    socket实现udp组播通信UDP组播(Multicast)是一种网络通信方式,它允许一个发送者(源)发送单一的数据包到多个接收者(目标)。与单播(Unicast)通信(其中数据包从一个发送者发送到一个接收者)和广播(Broadcast)通信(其中数据包发送到网络中的所有设备)不同,组播提供了一种中间方式,其中数据包被发送......
  • socket 实现udp网络数据通信
    利用udp实现网络数据通信UDP(UserDatagramProtocol)是用户数据报协议,是OSI参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。它是IETFRFC768是UDP的正式规范。UDP在IP数据包的头部仅仅加入了复用和数据完整性校验(数据包检查)的字段。UDP是对......
  • UDP协议实现多播功能
    /***author :[email protected]*@brief:程序可以加入到一个多播组中并等待服务器发送数据包,并且程序还需要具有发送功能,如果收到数据包则把消息内容输出到终端*@date:2024/06/06*@version:1.0*@note:none*......
  • UDP实现音频视频流传输
    UDP实现音频视频流传输服务器#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<arpa/inet.h>#include<fcntl.h>#include<sys/stat.h>#definePORT8080......
  • 基于c语言的UDP客户端、服务端二合一基础代码
    基于c语言的UDP客户端、服务端二合一基础代码示意图:准备好了吗,以下是基础代码:/****************************************************************************************************************************************字节序:数据以字节流的方式进行传输,底层都是......