41、网络编程/TCP.UDP通信模型练习20240301

一、编写基于TCP的客户端实现以下功能:

通过键盘按键控制机械臂:w(红色臂角度增大)s(红色臂角度减小)d(蓝色臂角度增大)a(蓝色臂角度减小)按键控制机械臂

1.基于TCP服务器的机械臂,端口号是8888, ip是Windows的ip;

查看Windows的IP:按住Windows+r 按键,输入cmd , 输入ipconfig。

2.点击软件中的开启监听;

3.机械臂需要发送16进制数,共5个字节,协议如下

0xff    0x02    x   y   0xff
0xff:起始结束协议,固定的;
0x02:控制机械手臂协议,固定的;
x:指定要操作的机械臂0x00 红色摆臂0x01 蓝色摆臂
y:指定角度

代码:

#include<myhead.h>
#define SER_IP "192.168.125.64"  //服务器IP
#define SER_PORT 8888          //服务器端口号
int main(int argc, const char *argv[])
{//创建套接字文件int sfd=socket(AF_INET,SOCK_STREAM,0);if(sfd==-1){perror("socket error");return -1;}//定义结构体存储服务器地址struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(SER_PORT);sin.sin_addr.s_addr=inet_addr(SER_IP);//连接服务器if(connect(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("connect error");return -1;}puts("connect success");//数据发送//定义控制红色臂的数组并初始化,范围是[-90,90]char rbuf[5]={0xff,0x02,0x00,0x00,0xff};//定义控制蓝色臂的数组并初始化,范围是[0,180]unsigned char bbuf[5]={0xff,0x02,0x01,0x00,0xff};//发送初始值send(sfd,rbuf,sizeof(rbuf),0);sleep(1);//防止沾包send(sfd,bbuf,sizeof(bbuf),0);char key=0;while(1){system("stty -icanon");//关闭缓冲区key=getchar();fflush(stdin);switch(key){case 'W':case 'w':{rbuf[3]+=2;//每次操作的角度偏移2度if(rbuf[3]>=90){rbuf[3]=90;}send(sfd,rbuf,sizeof(rbuf),0);}break;case 'S':case 's':{rbuf[3]-=2;if(rbuf[3]<=-90){rbuf[3]=-90;}send(sfd,rbuf,sizeof(rbuf),0);}break;case 'D':case 'd':{bbuf[3]+=2;if(bbuf[3]>=180){bbuf[3]=180;}send(sfd,bbuf,sizeof(bbuf),0);}break;case 'A':case 'a':{bbuf[3]-=2;if(bbuf[3]>180)//无符号整数小于零后会向255循环{bbuf[3]=0;}send(sfd,bbuf,sizeof(bbuf),0);}break;}}close(sfd);return 0;
}

运行:

思维导图

二、 基于UDP的TFTP文件传输

1.tftp协议概述

简单文件传输协议,适用于在网络上进行文件传输的一套标准协议,使用UDP传输

特点:

是应用层协议

基于UDP协议实现

数据传输模式

octet:二进制模式(常用)

mail:已经不再支持

2.tftp下载模型

TFTP通信过程总结

  1. 服务器在69号端口等待客户端的请求
  2. 服务器若批准此请求,则使用 临时端口 与客户端进行通信。
  3. 每个数据包的编号都有变化(从1开始)
  4. 每个数据包都要得到ACK的确认,如果出现超时,则需要重新发送最后的数据包或ACK包
  5. 数据长度以512Byte传输的,小于512Byte的数据意味着数据传输结束。

差错码:

0 未定义,差错错误信息

1 File not found.

2 Access violation.

3 Disk full or allocation exceeded.

4 illegal TFTP operation.

5 Unknown transfer ID.

6 File already exists.

7 No such user.

8 Unsupported option(s) requested.

代码:

#include<myhead.h>
#define SER_IP "192.168.125.57"
#define SER_POTR 69
int my_download(int cfd,struct sockaddr_in sin);
int my_upload(int cfd,struct sockaddr_in sin);
int my_save_data(char *p,int len);
int recv_ack(int cfd,struct sockaddr_in sin);int main(int argc, const char *argv[])
{//创建通信套接字int cfd=socket(AF_INET,SOCK_DGRAM,0);if(cfd==-1){perror("socket error");return -1;}//定义地址结构体 保存客户端地址struct sockaddr_in sin;sin.sin_family=AF_INET;sin.sin_port=htons(SER_POTR);sin.sin_addr.s_addr=inet_addr(SER_IP);int menu=0;while(1){system("clear");puts("\t\t------请选择选项------");printf("\t\t-------1.上传-------\n");printf("\t\t-------2.下载-------\n");printf("\t\t-------0.退出-------\n");scanf("%d",&menu);getchar();switch(menu){case 0:goto END;case 1:{int res=my_upload(cfd,sin);if(res==-1){puts("my_upload error");return -1;}}break;case 2:{int res=my_download(cfd,sin);if(res==-1){puts("my_download error");return -1;}}break;default:{puts("输入有误,请重新输入");}break;}puts("请输入任意键按回车结束!");while(getchar()!='\n');}END:close(cfd);return 0;
}int my_download(int cfd,struct sockaddr_in sin)
{//定义收发数据容器char pack[516]="";//组建请求协议包//1.请求下载printf("请输入要下载的文件名:");char txt[32]="";fgets(txt,sizeof(txt),stdin);txt[strlen(txt)-1]=0;short *p1=(short*)pack;*p1=htons(1);//存入前两字节的操作码1代表读(下载)char *p2=pack+2;strcpy(p2,txt);//存入文件名及结尾的0char *p3=p2+strlen(p2)+1;strcpy(p3,"octet");//存入模式位及结尾的0int packlen=4+strlen(p2)+strlen(p3);//发送下载请求if(sendto(cfd,pack,packlen,0,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("download request sendto error");return -1;}
/*	//读取服务器的回复消息int ack=recv_ack(cfd,sin);if(ack==-1){puts("recv_ack error");return -1;}
*/while(1){bzero(pack,sizeof(pack));int ack=recv_ack(cfd,sin);if(ack==-1){puts("my_download recv_ack error");return -1;}else if(ack==0)//下载完成{break;}*p1=htons(4);//设置ACK包*(p1+1)=htons(ack);//返回ACK包if(sendto(cfd,pack,sizeof(pack),0,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("upload request sendto error");return -1;}	}return 0;
}
int my_upload(int cfd,struct sockaddr_in sin)
{//定义收发数据容器char pack[516]="";//组建请求协议包//1.请求写入printf("请输入要上传的文件名:");char txt[32]="";fgets(txt,sizeof(txt),stdin);txt[strlen(txt)-1]=0;short *p1=(short*)pack;*p1=htons(2);//存入前两字节的操作码2代表写(上传)char *p2=pack+2;strcpy(p2,txt);//存入文件名及结尾的0char *p3=p2+strlen(p2)+1;strcpy(p3,"octet");//存入模式位及结尾的0int packlen=4+strlen(p2)+strlen(p3);if(sendto(cfd,pack,packlen,0,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("upload request sendto error");return -1;}//读取服务器的回复消息int ack=recv_ack(cfd,sin);if(ack==-1){puts("recv_ack error");return -1;}//2.开始上传数据//2.1只读形式打开要上传的文件int rfd=open(txt,O_RDONLY);if(rfd==-1){perror("upload open error");return -1;}int i=1;while(1){bzero(pack,sizeof(pack));//2.2设置发送数据的协议包*p1=htons(3);//前两字节操作码为3时代表此为数据包*(p1+1)=htons(i);//设置块编码从1开始int res=read(rfd,pack+4,512);//从文件中读取512数据存入数据域packlen=4+res;//本次的数据包大小//发送数据if(sendto(cfd,pack,sizeof(pack),0,(struct sockaddr*)&sin,sizeof(sin))==-1){perror("upload data sandto error");return -1;}ack=recv_ack(cfd,sin);//读取服务器的回复消息if(ack==-1){puts("recv_ack error");return -1;}else if(ack<i)//服务器返回的块编码小于当前发送的{//光标返回发送之前的位置重新发送lseek(rfd,-res,SEEK_CUR);}else if(ack==i)//服务器已接收该数据包可以发送下一个{i++;//块编码+1}if(res<512)//发送完成{break;}}close(rfd);return 0;
}
int my_save_data(char *p,int len)
{//追加写的形式创建一个文件存储下载的数据int wfd=open("./downtxt",O_WRONLY|O_APPEND|O_CREAT,0664);if(wfd==-1){perror("my_download open error");return -1;}write(wfd,p,len);close(wfd);return 0;
}
int recv_ack(int cfd,struct sockaddr_in sin)
{char pack[516]="";//接收服务器发来的消息 存入packint sinlen=sizeof(sin);int res=-1;if((res=(recvfrom(cfd,pack,sizeof(pack),0,(struct sockaddr*)&sin,&sinlen)))==-1){perror("recv_ack recvfrom error");return -1;}short *p=(short*)pack;short num=ntohs(*p);//获取发来消息的操作码switch(num){case 3:{printf("收到数据包,块编码:%d\n",ntohs(*(p+1)));//保存数据int seve=my_save_data(pack+4,res-4);if(seve==-1){puts("my_save_data error");return -1;}//如果读取的长度小于516说明已经下载完成if(res<sizeof(pack)){//最后一次回复ACK*p=htons(4);sendto(cfd,pack,4,0,(struct sockaddr*)&sin,sizeof(sin));return 0;//正常下载完成返回0}}break;case 4:{printf("收到ACK,快编码:%d\n",ntohs(*(p+1)));}break;case 5:{//收到错误码 输出差错码和差错信息printf("ERROR:%d:%s\n",ntohs(*(p+1)),pack+4);return -1;}break;}return ntohs(*(p+1));//返回块编码
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ELK学习

ELK 一、ELK介绍 &#x1f604; “ELK”是三个开源项目的首字母缩写&#xff0c;这三个项目分别是&#xff1a;Elasticsearch、Logstash 和 Kibana。Elasticsearch 是一个搜索和分析引擎。Logstash 是服务器端数据处理管道&#xff0c;能够同时从多个来源采集数据&#xff0…

软考重点题解析-基础知识

1.加密技术&#xff1a;分为对称加密技术&#xff1a;文件的加密和解密使用相同的密钥 和 非对称加密技术&#xff1a;加密和解密不同的密钥&#xff0c;分别是公开密钥和私有密钥。 例题&#xff1a;若A,B两人分别在认证机构&#xff08;CA&#xff09;M,N处获得证书&…

每日leetcode--最大数

正题之前 三玖yyds&#xff01;&#xff01;&#xff01; 题目 给定一组非负整数 nums&#xff0c;重新排列每个数的顺序&#xff08;每个数不可拆分&#xff09;使之组成一个最大的整数。 注意&#xff1a;输出结果可能非常大&#xff0c;所以你需要返回一个字符串而不是整…

STM32 | J-link安装过程

J-Link是一种由SEGGER公司开发的调试器和仿真器,用于嵌入式系统开发。它可以帮助开发人员在开发过程中进行调试和仿真,提供了快速、稳定的连接,并支持多种不同类型的微处理器和微控制器。 要获取J-Link软件,请访问SEGGER公司的官方网站(www.segger.com)并进入他们的下载…

解决:code ERESOLVE:ERESOLVE could not resolve 的报错问题

报错实例 报错原因 是我执行npm i xxx-xx的时候会出现这个错误 查了资料表示是node.js的问题 或者的依赖本身的问题 解决 1.在后面加上 --legacy-peer-deps 示例&#xff1a;npm i sass-loader7.3.1 --legacy-peer-deps 2&#xff0c;检查node版本&#xff0c;更改node版本 …

Doris——纵腾集团流批一体数仓架构

目录 前言 一、早期架构 二、架构选型 三、新数据架构 3.1 数据中台 3.2 数仓建模 3.3 数据导入 四、实践经验 4.1 准备阶段 4.2 验证阶段 4.3 压测阶段 4.4 上线阶段 4.5 宣导阶段 4.6 运行阶段 4.6.1 Tablet规范问题 4.6.2 集群读写优化 五、总结收益 六…

(Aliyun AI ACP 03)阿里云机器学习平台PAI

文章目录 阿里云人工智能工程师ACP认证考试知识点辅助阅读&#xff08;Aliyun AI ACP 03&#xff09;阿里云机器学习平台PAI引言PAI平台特点与优势阿里云AI产品的特点与应用场景集成解决方案与服务 阿里云人工智能工程师ACP认证考试知识点辅助阅读 &#xff08;Aliyun AI ACP …

Vue2:用node+express写一个轻量级的后端服务

1、桌面创建demo文件夹 进入demo&#xff0c;执行如下命令 npm init输入名称&#xff1a; test_server然后一路回车 2、安装express框架 npm i express3、新建server.js 在demo文件夹中&#xff0c;新建server.js const express require(express) const app express()…

OpenHarmony、HarmonyOS打开编辑 PDF 等操作的三方组件使用教程

项目场景: 随着数字化时代的发展,PDF 文档成为广泛应用于各行业的重要文件格式。为了提高OpenHarmony/HarmonyOS生态系统的功能性和用户体验,我们需要一款支持打开、编辑PDF文件的应用程序。 使用户能够轻松打开、浏览和编辑PDF文件。该应用将充分利用OpenHarmony/HarmonyO…

【HTML】HTML基础5(特殊字符)

目录 特殊字符的作用 常用的特殊字符 使用效果 特殊字符的作用 例如 当我在两个文字间打出空格时 <p>“银河护卫队”系列 在漫威电影宇宙中一直是异数般的存在&#xff0c;不仅因为影片主角是一群反英雄&#xff0c;<strong>与超级英雄相比显得格格不入<…

解决 MySQL 未运行但锁文件存在的问题

查看mysql状态时&#xff0c;显示错误信息"ERROR! MySQL is not running, but lock file (/var/lock/subsys/mysql) exists"。 解决步骤 1、检查 MySQL 进程是否正在运行 在继续之前&#xff0c;我们首先需要确定 MySQL 进程是否正在运行。我们可以使用以下命令检查…

大路灯买哪款最好?如何挑选立体式学习灯?五款大路灯总有一款适合你!

大路灯作为这几年学生照明电器中的"顶流网红"被大家熟知&#xff0c;大路灯的特点就是可以提供良好的光线带来舒适的照明体验。大路灯通过专业的技术&#xff0c;对台灯的性能不断优化、调校&#xff0c;最终形成目前最适合照明的一种电器&#xff0c;但市面上的大路…