当前位置: 首页 > news >正文

学习嵌入式第三十五天

文章目录

  • 网络(续上)
    • 1.函数接口
    • 2.相关功能实现
      • 1.TCP连接
      • 2.UDP
  • 习题

网络(续上)

1.函数接口

  • sendto

    原型:ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
    功能:向一个指定的目标地址发送数据
    参数:sockfd:socket返回的套接字描述符buf:向包含要发送数据的缓冲区的指针len:要发送的数据长度flags:修改套接字调用行为的标志位,通常为0dest_addr:指向一个sockaddr结构体addrlen:指向的结构体的长度
    返回值:成功返回实际发送的字节数失败返回-1
    
  • 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:控制接受操作的标志位,通常为0src_addr:输出参数,一般为NULL,不为NULL时,函数将发送方的地址信息填充到这个结构体中addrlen:输入输出参数输入时:必须指向一个整数,大小为src_addr缓冲区的大小输出时:函数会修改这个整数,并将其设置为src_addr中实际存储的地址信息的真实长度
    返回值:成功返回接收到的字节数失败返回-1
    

2.相关功能实现

1.TCP连接

  • 客户端连接

    int tcp_client_connect(char const *ip,char const *port){int fd = socket(AF_INET,SOCK_STREAM,0);//创建一个TCP套接字if(fd < 0){perror("socket fail");return -1;}//创建失败struct sockaddr_in seraddr;memset(&seraddr,0,sizeof(seraddr));//初始化服务器地址结构体seraddr.sin_family = AF_INET;seraddr.sin_port = htons(atoi(port));//设置端口号seraddr.sin_addr.s_addr = inet_addr(ip);//输入自己的IP
    /*尝试连接到服务器,失败返回-1,成功返回套接字描述符*/if(connect(fd,(const struct sockaddr *)&seraddr,sizeof(seraddr)) < 0){perror("connect fail");return -1;}return fd;
    }
    
  • 服务器连接

    int tcp_accept(char const *ip,char const *port){int fd = socket(AF_INET,SOCK_STREAM,0);//创建一个TCP套接字if(fd < 0){perror("socket fail");return -1;}//创建失败res_fd[0] = fd;printf("fd = %d\n",fd);struct sockaddr_in seraddr;memset(&seraddr,0,sizeof(seraddr));//初始化服务器地址结构体seraddr.sin_family = AF_INET;seraddr.sin_port = htons(atoi(port));//设置端口seraddr.sin_addr.s_addr = inet_addr(ip);//设置IP
    /*绑定套接字到指定的IP和端口*/if(bind(fd,(const struct sockaddr *)&seraddr,sizeof(seraddr)) < 0){perror("connect fail");return -1;}
    /*监听端口,准备接受连接*/if(listen(fd,5) < 0){perror("listen fail");return -1;}
    /*接受一个客户端的连接,并返回连接的文件描述符*/int connfd = accept(fd,NULL,NULL);if(connfd < 0){perror("accept fail");return -1;}res_fd[1] = connfd;return connfd;
    }
    

2.UDP

  • 客户端向服务器端发送消息,服务器端回复收到

    • 客户端

      int main(){// 创建 UDP 套接字int clifd = socket(AF_INET,SOCK_DGRAM,0);if(clifd < 0){perror("socket fail"); // 创建失败,输出错误信息return -1;}// 定义并初始化服务器地址结构体struct sockaddr_in seraddr;memset(&seraddr,0,sizeof(seraddr));seraddr.sin_family = AF_INET; // IPv4seraddr.sin_port = htons(50000); // 端口号50000,转为网络字节序seraddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务器IP// 主循环,不断发送和接收消息while(1){char buf[1024] = {0}; // 发送缓冲区// 从标准输入读取一行数据fgets(buf,sizeof(buf),stdin);// 发送数据到服务器,包含字符串结束符int ret = sendto(clifd,buf,strlen(buf)+1,0,(const struct sockaddr*)&seraddr,sizeof(seraddr));char rbuf[1024] = {0}; // 接收缓冲区// 接收服务器返回的数据recvfrom(clifd,rbuf,sizeof(rbuf)+1,0,NULL,NULL);// 打印服务器返回的数据printf("buf = %s\n",rbuf);// 清空接收缓冲区memset(rbuf,0,sizeof(rbuf));}return 0;
      }
      
    • 服务器端

      int main(){// 创建 UDP 套接字int serfd = socket(AF_INET,SOCK_DGRAM,0);if(serfd < 0){perror("socket fail"); // 创建失败,输出错误信息return -1;}// 定义并初始化服务器地址结构体struct sockaddr_in seraddr;memset(&seraddr,0,sizeof(seraddr));seraddr.sin_family = AF_INET; // IPv4seraddr.sin_port = htons(50000); // 端口号50000,转为网络字节序seraddr.sin_addr.s_addr = INADDR_ANY; // 监听所有网卡// 绑定套接字和地址if(bind(serfd,(const struct sockaddr *)&seraddr,sizeof(seraddr)) < 0){perror("fail to bind"); // 绑定失败,输出错误信息return -1;}// 主循环,不断接收和回复客户端消息while(1){char buf[1024]; // 接收缓冲区struct sockaddr_in cliaddr; // 客户端地址结构体socklen_t len = sizeof(cliaddr); // 地址长度// 接收客户端消息,获取客户端地址int ret = recvfrom(serfd,buf,sizeof(buf),0,(struct sockaddr*)&cliaddr,&len);// 打印接收到的字节数printf("ret = %d \n",ret);printf("--------------------------\n");// 打印客户端IP地址printf("cliaddr = %s\n",inet_ntoa(cliaddr.sin_addr));// 打印客户端端口号printf("cliport = %d\n",ntohs(cliaddr.sin_port));printf("--------------------------\n");// 构造回复消息char sbuf[1024] = {0};sprintf(sbuf,"recv:%s",buf);// 发送回复消息给客户端sendto(serfd,sbuf,strlen(sbuf)+1,0,(struct sockaddr*)&cliaddr,sizeof(cliaddr));// 清空发送缓冲区memset(sbuf,0,sizeof(sbuf));}return 0;
      }
      

习题

1.客户端向服务器端发送一个文件名,服务器将文件内容打包发给客户端

  • 客户端

    int main(){int clifd = socket(AF_INET,SOCK_DGRAM,0);if(clifd < 0){perror("socket fail");return -1;}struct sockaddr_in seraddr;memset(&seraddr,0,sizeof(seraddr));seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50000);seraddr.sin_addr.s_addr = inet_addr("127.0.0.1");msg_t msg;msg.type = -1;fgets(msg.buf,sizeof(msg.buf),stdin);msg.buf[strlen(msg.buf)-1] = '\0';sendto(clifd,msg.buf,sizeof(msg.buf),0,(const struct sockaddr*)&seraddr,sizeof(seraddr));int fd = open(msg.buf,O_WRONLY|O_TRUNC|O_CREAT,0666);if(fd < 0){perror("fail to open file");return -1;}int n = 0;while((n = recvfrom(clifd,&msg,sizeof(msg),0,NULL,NULL)) > 0){if(msg.type == 0){break;}write(fd,msg.buf,msg.type);memset(&msg,0,sizeof(msg));}close(fd);
    close(clifd);
    return 0;
    }
    
  • 服务器端

    int main(){int serfd = socket(AF_INET,SOCK_DGRAM,0);if(serfd < 0){perror("socket fail");return -1;}struct sockaddr_in seraddr;memset(&seraddr,0,sizeof(seraddr));seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50000);seraddr.sin_addr.s_addr = INADDR_ANY;if(bind(serfd,(const struct sockaddr *)&seraddr,sizeof(seraddr)) < 0){perror("fail to bind");return -1;}DIR *dir;struct dirent *dp;msg_t msg;struct sockaddr_in cliaddr;socklen_t len = sizeof(cliaddr);dir = opendir("/home/linux/桌面");if(dir == NULL){perror("fail to open dir");return -1;}recvfrom(serfd,msg.buf,sizeof(msg.buf),0,(struct sockaddr*)&cliaddr,&len);printf("buf = %s\n",msg.buf);while(1){dp = readdir(dir);if(dp == NULL){perror("fail to read dir");return -1;}else if('.' == dp->d_name[0]){continue;}else if(strcmp(dp->d_name,msg.buf) == 0){sprintf(msg.buf,"/home/linux/桌面/%s",dp->d_name);int fd = open(msg.buf,O_RDONLY);if(fd < 0){perror("fail to open file");return -1;}int n;while((n = read(fd,msg.buf,sizeof(msg.buf))) > 0){msg.type = n;sendto(serfd,&msg,sizeof(msg),0,(const struct sockaddr*)&cliaddr,sizeof(cliaddr));}msg.type = 0;sendto(serfd,&msg,sizeof(msg),0,(const struct sockaddr*)&cliaddr,sizeof(cliaddr));close(fd);break;}}closedir(dir);
    close(serfd);
    return 0;
    }
    

2.用UDP实现服务器端和客户端的点对点聊天

  • 客户端

    int clifd;
    struct sockaddr_in seraddr;
    socklen_t len = sizeof(seraddr);void *thread1(void* arg){char buf[1024];while(1){memset(buf,0,sizeof(buf));recvfrom(clifd,buf,sizeof(buf),0,(struct sockaddr*)&seraddr,&len);if(strcmp(buf,".quit") == 0){printf("server quit\n");break;}printf("server say:%s\n",buf);}return NULL;
    }
    void *thread2(void* arg){char buf[1024];while(1){memset(buf,0,sizeof(buf));fgets(buf,sizeof(buf),stdin);if(strcmp(buf,".quit\n") == 0){break;}sendto(clifd,buf,strlen(buf)+1,0,(struct sockaddr*)&seraddr,sizeof(seraddr));}return NULL;
    }int main(){clifd = socket(AF_INET,SOCK_DGRAM,0);if(clifd < 0){perror("fail to socket");return -1;}memset(&seraddr,0,sizeof(seraddr));seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50000);seraddr.sin_addr.s_addr = inet_addr("127.0.0.1");pthread_t pid1;pthread_t pid2;void *(*p1)(void*) = thread1;void *(*p2)(void*) = thread2;pthread_create(&pid1,NULL,p1,NULL);pthread_create(&pid2,NULL,p2,NULL);pthread_join(pid1,NULL);pthread_join(pid2,NULL);close(clifd);return 0;
    }
    
  • 服务器端

    int serfd;
    struct sockaddr_in seraddr;struct sockaddr_in cliaddr;
    socklen_t len = sizeof(cliaddr);void *thread1(void* arg){char buf[1024];while(1){memset(buf,0,sizeof(buf));recvfrom(serfd,buf,sizeof(buf),0,(struct sockaddr*)&cliaddr,&len);if(strcmp(buf,".quit") == 0){printf("client quit\n");break;}printf("client say:%s\n",buf);}return NULL;
    }
    void *thread2(void* arg){char buf[1024];while(1){memset(buf,0,sizeof(buf));fgets(buf,sizeof(buf),stdin);if(strcmp(buf,".quit\n") == 0){break;}sendto(serfd,buf,strlen(buf)+1,0,(struct sockaddr*)&cliaddr,len);}return NULL;
    }int main(){serfd = socket(AF_INET,SOCK_DGRAM,0);if(serfd < 0){perror("fail to socket");return -1;}memset(&seraddr,0,sizeof(seraddr));seraddr.sin_family = AF_INET;seraddr.sin_port = htons(50000);seraddr.sin_addr.s_addr = INADDR_ANY;if(bind(serfd,(const struct sockaddr*)&seraddr,sizeof(seraddr))< 0){perror("fail to bind");return -1;}pthread_t pid1;pthread_t pid2;void *(*p1)(void*) = thread1;void *(*p2)(void*) = thread2;pthread_create(&pid1,NULL,p1,NULL);pthread_create(&pid2,NULL,p2,NULL);pthread_join(pid1,NULL);pthread_join(pid2,NULL);close(serfd);return 0;
    }
    
http://www.dtcms.com/a/344071.html

相关文章:

  • PCB电路设计学习2 元件原理图封装的添加 手工设计元件封装
  • LeetCode100 -- Day4
  • webpack开发模式与生产模式(webpack --mode=development/production“, )
  • 如何修复“DNS服务器未响应”错误
  • OpenHarmony子系统介绍
  • LLM实践系列:利用LLM重构数据科学流程01
  • 数据分析专栏记录之 -基础数学与统计知识 2 概率论基础与python
  • OpenHands:开源AI软件开发代理平台的革命性突破
  • 密码管理中Null 密码
  • 第七章 愿景22 超级丹项目汇报
  • 算法第五十三天:图论part04(第十一章)
  • Spring Boot+Docker+Kubernetes 云原生部署实战指南
  • LLM实践系列:利用LLM重构数据科学流程03- LLM驱动的数据探索与清洗
  • Windows应急响应一般思路(一)
  • [激光原理与应用-317]:光学设计 - Solidworks - 零件、装配体、工程图
  • VTK学习笔记3:曲线与曲面源
  • 闲置笔记本链接硬盘盒充当Windows NAS 网易UU远程助力数据读取和处理
  • 全球电商业财一体化趋势加速,巨益科技助力品牌出海精细化运营
  • 数字隔离器:新能源系统的安全与效能革命
  • JavaWeb前端04(Vue生命周期,钩子函数)
  • Jmeter自动化性能测试常见问题汇总
  • 什么是Jmeter?Jmeter使用的原理步骤是什么?
  • chapter07_初始化和销毁方法
  • 第2章 cmd命令基础:证书操作(certutil)
  • base64认识实际使用
  • Samba实现Windows与Linux文件共享
  • Linux下基于Electron的程序ibus输入法问题
  • Ubuntu20系统上离线安装MongoDB
  • Kafka Broker 核心原理全解析:存储、高可用与数据同步
  • Java性能优化实战(四):IO与网络优化的4个关键方向