Linux系统编程(14)UDP全双工通信和TCP半双工通信

news2024/9/21 1:37:51

一、UDP全双工通信

UDP通信基础:
recvfrom函数

  recvfrom 是一个用于接收数据的函数,,但 recvfrom 不仅接收数据,还可以获取发送数据的地址信息。

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
  • sockfd: 指定用于接收数据的套接字描述符。它通常是通过 socket() 函数创建的。

  • buf: 指向接收数据的缓冲区的指针。

  • len: 指定缓冲区的大小,即要接收的数据的最大字节数。

  • flags: 接收数据时的标志位,默认为0

  • src_addr: 指向存储发送方地址信息的 sockaddr 结构体的指针。如果不关心发送方的地址信息,可以传入 NULL

  • addrlen: 指向 src_addr 结构体长度的指针。在函数返回时,它将包含实际的地址长度。

  • 成功时,recvfrom 返回接收到的字节数。
  • 出错时,返回 -1
bind函数

    bind 函数在网络编程中用于将一个套接字与一个特定的地址(IP地址和端口号)绑定。它主要用于服务器端,使得服务器能够监听来自特定地址的连接请求。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • sockfd: 套接字文件描述符。这个套接字是通过 socket() 函数创建的,表示一个未绑定的套接字。

  • addr: 指向 sockaddr 结构体的指针,包含要绑定到的地址信息。通常使用 sockaddr_in 结构体来表示IPv4地址(对于IPv6使用 sockaddr_in6),然后将其强制转换为 sockaddr* 类型。

  • addrlen: 结构体 sockaddr 的大小,通常使用 sizeof(struct sockaddr_in)sizeof(struct sockaddr_in6)

  • 成功时,返回 0
  • 出错时,返回 -1

struct sockaddr结构体:

   struct sockaddr      通用地址结构 --- ip + 端口 
      {
          u_short sa_family;  地址族
          char sa_data[14];   地址信息
      };

      转换成网络地址结构如下:
    

 struct sockaddr_in    ///网络地址结构
      {
          u_short           sin_family; //地址族
          u_short           sin_port;   //地址端口
          struct in_addr  sin_addr;   //地址IP  //"192.168.1.123"
          char               sin_zero[8]; //占位
      };
其中sin_addr结构体:
      struct in_addr
      {
          in_addr_t s_addr;
      };
基于UDP实现的全双工通信
client.c
//使用多进程实现客户端的的收和发
#include<stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <string.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc , char *argv[])
{
    int fd = socket(AF_INET,SOCK_DGRAM,0);
    if(fd < 0)
    {
        perror("socket error");
        return 0;
    }
    char buf[1024];
    struct sockaddr_in seraddr;
    seraddr.sin_family = AF_INET;
    seraddr.sin_port = htons(50000);
    seraddr.sin_addr.s_addr = inet_addr("192.168.85.128");
    struct sockaddr_in srcaddr;
    socklen_t srcaddrlen = sizeof(srcaddr);
    pid_t pid = fork();
    if(pid < 0)
    {
        perror("fork fail");
        return 0;
    }
    if(pid > 0)
    {
        while(1)
        {
            printf("client >");
            bzero(buf,sizeof(buf));
            fgets(buf,sizeof(buf),stdin); 
            sendto(fd,buf,strlen(buf),0,(const struct sockaddr *)&seraddr,sizeof(seraddr));
            if(strncmp(buf,"quit",4) == 0)
            {
                kill(pid,9);
                wait(NULL);
                return 0;
            }
        }
    }
    if(pid == 0)
    {
        while(1)
        {
            recvfrom(fd,buf,sizeof(buf),0,NULL,NULL);
            printf(" %s\n",buf);

        }
    }
    return 0;
}
server.c
//使用多进程实现服务端的收和发
#include<stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <string.h>
#include <arpa/inet.h>
#include <signal.h>
#include<sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void handler(int signo)
{
    wait(NULL);
    kill(getpid(),9);
}
int main(int argc , char *argv[])
{
    int fd = socket(AF_INET,SOCK_DGRAM,0);
    if(fd < 0)
    {
        perror("socket error");
        return 0;
    }
    char buf[1024];
    struct sockaddr_in seraddr;
    seraddr.sin_family = AF_INET;
    seraddr.sin_port = htons(50000);
    seraddr.sin_addr.s_addr = inet_addr("192.168.85.128");
    struct sockaddr_in srcaddr;
    socklen_t srcaddrlen = sizeof(srcaddr);
    bind(fd,(const struct sockaddr *)&seraddr,sizeof(seraddr));
        recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr *) & srcaddr,&srcaddrlen);
    if(strncmp(buf,"quit",4) == 0)
    {
        return 0;
    }
    printf("receive :%s",buf);
    printf("receive from : %s\n",inet_ntoa(srcaddr.sin_addr));
    printf("port : %d\n",ntohs(srcaddr.sin_port));
    char returnbuf[2048];
    pid_t pid = fork();
    if(pid < 0)
    {
        perror("fork fail");
        return 0;
    }
    if(pid > 0)
    { 
        while(1)
        {   //signal(SIGCHLD,handler);
            //bzero(buf,sizeof(buf));
            printf("server >");
            fgets(buf,sizeof(buf),stdin);
            sprintf(returnbuf,"%s%s","\nfrom server:",buf);
            sendto(fd,returnbuf,strlen(returnbuf),0,(const struct sockaddr *)&srcaddr,sizeof(srcaddr));
        }
    }
    if(pid == 0)
    {
        while(1)
        {
            recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr *) & srcaddr,&srcaddrlen);
            if(strncmp(buf,"quit",4) == 0)
            {
                break;
            }
            printf("receive :%s",buf);
            printf("receive from : %s\n",inet_ntoa(srcaddr.sin_addr));
            printf("port : %d\n",ntohs(srcaddr.sin_port));

        }
        return 0;
    }
}

二、TCP通信

由于TCP面向连接和可靠性高的特性,因此,在使用TCP协议通信时,需要在客户端和服务端之间先建立连接才能进行数据通信。

TCP通信流程

listen函数

listen 函数用于将一个套接字设置为监听模式,等待客户端的连接请求。

int listen(int sockfd, int backlog);
  • sockfd: 套接字文件描述符。这个套接字必须已经用 socket() 函数创建,并且使用 bind() 函数绑定到了一个特定的地址和端口。

  • backlog: 指定内核为该套接字排队的最大连接数。这表示在 accept() 函数处理之前,内核可以排队等待的最大连接数。如果有更多的连接请求到达,新的连接可能会被拒绝或未处理,直到队列中有空闲位置。

  • 成功时,返回 0
  • 出错时,返回 -1

connect函数  

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

 功能:该函数固定有客户端使用,表示从当前主机向目标
            主机发起链接请求。
   参数:sockfd 本地socket创建的套接子id
                    addr 远程目标主机的地址信息。
                 addrlen: 参数2的长度。
   返回值:成功 0
              失败 -1;

accept函数
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

accept 函数用于服务器端网络编程,在套接字处于监听模式时,accept 函数会从监听队列中提取第一个连接请求,并为该连接创建一个新的套接字(专门用来连接)

  • sockfd: 监听套接字的文件描述符。这个套接字是通过 socket() 创建的,并且已经通过 bind() 绑定到了一个地址和端口,通过 listen() 函数进入了监听状态。

  • addr: 指向 sockaddr 结构体的指针,accept 函数将填充客户端的地址信息到该结构体中。如果你不关心客户端的地址,可以将其设置为 NULL

  • addrlen: 一个值-结果参数,它指向一个保存了 addr 结构大小的变量。在函数返回时,这个变量会包含客户端地址结构的实际大小。如果 addrNULL,则 addrlen 也应为 NULL

  • 成功时,返回一个新的文件描述符,这个描述符代表新建立的连接。服务器通过这个新套接字与客户端进行通信。
  • 出错时,返回 -1,并设置 errno 以指示错误类型。

这几个函数之间的关系

listen函数将创建的socket套接字设置为监听模式后,创建一个序列用来存储请求连接的设备,accept函数每次将第一个在队列中的请求进行处理后产生一个用来通信的和客户端建立连接的新的套接字 ,用来负责后续的通信

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2064077.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【vue3|第25期】Vue3中的useRoute:轻松访问路由信息

日期&#xff1a;2024年8月21日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉在这里插入代码片得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不…

撰写文献综述策略

撰写文献综述 文献综述在形式上与任何其他类型的学术文本没有任何不同&#xff0c;因为它也具有基本部分。每个部分中包含的内容取决于您撰写文献综述的目的&#xff1a; 简介 此部分应明确定义评论的目的和重点。论文&#xff1a;如果您将评论作为毕业论文或学位论文的一部分…

文件IO函数练习

作业&#xff1a;使用write和read完成文件的拷贝。 代码 #include <myhead.h>int main(int argc, const char *argv[]) {int fd open("./1.txt",O_RDONLY);//已只读打开被拷贝文件if(-1 fd){perror("open");return -1;}int fd1 open("./2.…

Python使用QtSide6(PyQt)编写界面

1、安装QtSide6 开始菜单cmd 创建虚拟环境 python -m venv env2 进入虚拟环境 call env2/scripts/activate 安装Pyside6 pip install Pyside6 2、设计Qt界面 打开designer.exe&#xff0c;设计界面 点击菜单【窗体】【View Python Code...】&#xff0c;点击【全部复制】…

论文阅读:MonoScene: Monocular 3D Semantic Scene Completion

论文阅读&#xff1a;MonoScene: Monocular 3D Semantic Scene Completion Abstract MonoScene提出了一个3D语义场景完成&#xff08;SSC&#xff09;框架&#xff0c;其中场景的密集几何形状和语义是从单个单目 RGB 图像中推断出来的。与SC文献不同&#xff0c;我们依靠2.5或…

回归预测|基于北方苍鹰优化NGO-Transformer-GRU组合模型的数据预测Matlab程序多特征输入单输出

回归预测|基于北方苍鹰优化NGO-Transformer-GRU组合模型的数据预测Matlab程序多特征输入单输出 文章目录 前言回归预测|基于北方苍鹰优化NGO-Transformer-GRU组合模型的数据预测Matlab程序多特征输入单输出 一、NGO-Transformer-GRU模型NGO-Transformer-GRU组合模型的数据预测1…

Linux之数字证书

新书速览|Ubuntu Linux运维从零开始学_ubuntu linux运维从零开始学 pdf 下载-CSDN博客 《Ubuntu Linux运维从零开始学&#xff08;Linux技术丛书&#xff09;》(肖志健)【摘要 书评 试读】- 京东图书 (jd.com) 随着网络环境的恶化&#xff0c;人们已经逐渐抛弃网络上面的明文…

嵌入式day32

recvfrom 参数&#xff1a; sockfd //socket的fd buf //保存数据的一块空间的地址 len //这块空间的大小 flags //0 默认的接收方式 --- 阻塞方式 src_addr //用来保存发送方的地址信息 addrlen //表示发送方实际的地址信息大小 返回值&#xff1a; 成功 返回接收到的字…

小米、友邦带领恒指大反攻!

港股三大指数反弹止步2连跌&#xff0c;恒生科技指数一度冲高至2%&#xff0c;恒指收涨1.44%。盘面上&#xff0c;大型科技股多数表现活跃&#xff0c;业绩超预期&#xff0c;小米大涨超8%表现尤其抢眼&#xff0c;京东涨约4%&#xff0c;百度涨1.71%&#xff0c;网易涨2.14%&a…

linux内核编译及驱动程序的添加

内核编译:Makefile 条件编译 先拷贝一个默认的配置到.config (官方所有的默认配置文件在arch/arm/configs下) 我使用的是内核源码顶层目录下的config_mini2440_td35 在Kconfig中定义menuconfig中的可配置选项 make menuconfig //可视化配置菜单 --内核活地图 .config #…

生产者消息可靠性

若支付服务和mq之前网络链接失败/mq挂掉/交易服务挂掉,都有可以让支付订单无法更新,所以导致发送者不可靠,mq本身不可靠,消费者不可靠,消息延迟,针对以下问题 生产者可靠性 支付服务和mq之间有可能连不上,连不上怎么办,可以增加失败重连 配置文件中配置-重连 测试结果…

《黑神话·悟空》主创冯骥:我真的不适合做生物

出品| 木青生信大模型 作者| 穆易青、kimi 头图| 大地老周 引言 《黑神话:悟空》自8月20日全球上线以来,以其震撼的视觉效果和深刻的游戏体验,迅速成为现象级作品。这款游戏不仅创下了450万份的单日销量纪录,更在Steam等平台上取得了前所未有的成功。作为一名热爱游戏的…

SDXS:知识蒸馏在高效图像生成中的应用

人工智能咨询培训老师叶梓 转载标明出处 扩散模型虽然在图像生成方面表现出色&#xff0c;但其迭代采样过程导致在低功耗设备上部署面临挑战&#xff0c;同时在云端高性能GPU平台上的能耗也不容忽视。为了解决这一问题&#xff0c;小米公司的Yuda Song、Zehao Sun、Xuanwu Yin…

财务报表解读指南:关键指标与分析方法详解

一、概述 财务报表中包含了丰富的信息&#xff0c;但如果在分析时缺乏明确的思路或忽略重点&#xff0c;很容易被复杂的数据搞得无所适从。本文将介绍财务报表中的关键指标&#xff0c;包括资产负债率的分析、净资产收益率的解读&#xff0c;以及销售复合增长率的计算&#xf…

如何生成随机数(通过rand函数,srand函数,time函数深入讲解)

目录 1. 随机数的生成 2. srand函数 3. time函数 4. 设置随机数的范围 1. 随机数的生成 既然是猜数字游戏&#xff0c;那么最终的数字答案肯定是重要的&#xff0c;我们要如何实现这个随机数的生成呢&#xff1f; 在这个功能上&#xff0c;C语言提供了一个函数叫rand&…

智算中心算力池化技术深度分析报告

智算中心算力池化技术深度分析 智能算力&#xff0c;人工智能基石&#xff0c;助力构建多要素融合信息基础设施。作为数字经济高质量发展核心引擎&#xff0c;智能算力基础设施建设正迎来高潮。 智算中心&#xff0c;作为集约化算力基础设施&#xff0c;以智能算力为核心&…

特征工程练手(四):特征选择

本文为和鲸python 特征工程入门与实践闯关训练营资料整理而来&#xff0c;加入了自己的理解&#xff08;by GPT4o&#xff09; 原活动链接 原作者&#xff1a;云中君&#xff0c;大厂后端研发工程师 目录 0、关卡总结1、前言2、基础知识讲解2.1get_best_model_and_accuracy2…

springboot集成kafka-生产者发送消息

springboot集成kafka发送消息 1、kafkaTemplate.send()方法1.1、springboot集成kafka发送消息Message对象消息1.2、springboot集成kafka发送ProducerRecord对象消息1.3、springboot集成kafka发送指定分区消息 2、kafkaTemplate.sendDefault()方法3、kafkaTemplate.send(...)和k…

案例-异常

题目: (如果一开始不知道如何用异常的语法写,可先用如if语句代替try...catch,最后再把if优化为try...catch) 代码: javabean类: 测试类:

Java CompletableFuture:你真的了解它吗?

文章目录 1 什么是 CompletableFuture&#xff1f;2 如何正确使用 CompletableFuture 对象&#xff1f;3 如何结合回调函数处理异步任务结果&#xff1f;4 如何组合并处理多个 CompletableFuture&#xff1f; 1 什么是 CompletableFuture&#xff1f; CompletableFuture 是 Ja…