1.TCP机械臂测试
程序代码:
1 #include<myhead.h>
2 #define SER_IP "192.168.126.112" //服务器IP
3 #define SER_PORT 8888 //服务器端口号
4
5 #define CLI_IP "192.168.126.121" //客户端IP
6 #define CLI_PORT 9999 //客户端端口号
7 int main(int argc, const char *argv[])
8 {
9 //1.创建用于通信的套接字文件描述符
10 int cfd=socket(AF_INET,SOCK_STREAM,0); //通信协议族,IPv4;指定通信类型,TCP;参数2已指定通信类型
11 if(cfd==-1)
12 {
13 perror("socket error");
14 return -1;
15 }
16 printf("cfd=%d\n",cfd);
17 //2.绑定(非必须)
18 //2.1填充地址信息结构体
19 struct sockaddr_in cin;
20 cin.sin_family=AF_INET;//地址族,IPv4
21 cin.sin_port=htons(CLI_PORT);//端口号,主机号转换为网络号,2字节
22 cin.sin_addr.s_addr=inet_addr(CLI_IP);//ip地址,点分十进制转为4字节无符号网络字节序
23 //2.2绑定,将ip地址和端口号绑定到套接字文件描述符
24 if(bind(cfd,(struct sockaddr*)&cin,sizeof(cin))==-1)
25 //文件描述符;
26 //通信地址信息结构体,不同通信方式,结构体不同,将具体地址信息强转为该类型,地址
27 //结构体大小,值
28 {
29 perror("bind error");
30 return -1;
31 }
32 printf("bind success\n");
33 //3.连接服务器
34 //3.1填充要连接的服务器地址信息结构体
35 struct sockaddr_in sin;
36 sin.sin_family=AF_INET;//地址族IPv4
37 sin.sin_port=htons(SER_PORT);//端口号,主机号转换为网络号
38 sin.sin_addr.s_addr=inet_addr(SER_IP);//ip地址,点分十进制转为4字节无符号网络字节序
39 //3.2连接服务器
40 if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
41 //套接字文件描述符
42 //要发送数据起始地址
43 //要发送数据大小
44 //是否阻塞,0阻,MSG_DONTWAIT非阻塞
45 {
46 perror("connect error");
47 return -1;
48 }
49 printf("connect success\n");
50 //4.数据收发
51 char rbuf[5]={0xff,0x02,0x00,0x00,0xff};
52 //起始结束协议,固定的;控制机械臂协议,固定的
53 //x指定操作机械臂,0x00红,0x01蓝;y:指定角度
54 unsigned char bbuf[5]={0xff,0x02,0x01,0x00,0xff};
55 //发送给服务器当做初始值
56 send(cfd,rbuf,sizeof(rbuf),0);//文件描述符;要发送数据起始地址;数据大小;是否阻塞
57 sleep(1);
58 send(cfd,bbuf,sizeof(bbuf),0);
59 char key=0;//接收键盘输入的字符
60 while(1)
61 {
62 system("clear");//执行终端指令
63 scanf("%c",&key);//键盘输入一个字符
64 getchar();//吸收垃圾字符,回车
65 switch(key)
66 {
67 //红色机械臂
68 case 'W':
69 case 'w':
70 {
71 rbuf[3]+=5;//每次操作角度增加5度
72 if(rbuf[3]>=90)
73 rbuf[3]=90;
74 send(cfd,rbuf,sizeof(rbuf),0);
75 }
76 break;
77 case 'S':
78 case 's':
79 {
80 rbuf[3]-=5;//每次操作角度减小5度
81 if(rbuf[3]<=-90)
82 rbuf[3]=-90;
83 send(cfd,rbuf,sizeof(rbuf),0);
84 }
85 break;
86 //蓝色机械臂
87 case 'D':
88 case 'd':
89 {
90 bbuf[3]+=5;//每次操作角度增加
91 if(bbuf[3]>=180)
92 bbuf[3]=180;
93 send(cfd,bbuf,sizeof(bbuf),0);
94 }
95 break;
96 case 'A':
97 case 'a':
98 {
99 bbuf[3]-=5;//每次操作角度减小
100 if(bbuf[3]<=0)
101 bbuf[3]=0;
102 send(cfd,bbuf,sizeof(bbuf),0);
103 }
104 break;
105 case 'Q':
106 case 'q':
107 goto END;
108 default:printf("enter error\n");
109 }
110 }
111 END:
112 //5.关闭套接字
113 close(cfd);
114 return 0;
115 }
~
~
运行结果:
2. 基于UDP的TFTP文件传输
程序代码:
#include <myhead.h>
#define SER_IP "192.168.125.254" //服务端IP
#define SER_PORE 69 //端口号
//定义下载函数
int download(int cfd,struct sockaddr_in sin)
{
//组件协议包:下载请求
char pack[516]="";
short *p1=(short *)pack;
*p1=htons(1); //设置操作码
char file[20]="";
printf("请输入文件名:");
fgets(file,sizeof(file),stdin);
file[strlen(file)-1]=0;
char *p2=(pack+2);
strcpy(p2,file); //文件名
char *p4=p2+strlen(p2)+1;
strcpy(p4,"octet"); //模式位
int packlen=4+strlen(p2)+strlen(p4); //请求包大小
printf("%d\n",packlen);
//向服务器发送请求包
sendto(cfd,pack,packlen,0,(struct sockaddr*)&sin,sizeof(sin));
//以只写的形式打开文件
int wfd=-1;
if((wfd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0664))==-1){
perror("open error");
return -1;
}
int res=0;
struct sockaddr_in cin;
socklen_t socklen=sizeof(cin);
while(1)
{
//收取服务器发来的数据包
//判断数据包的操作码是否为3 以及 数据包数据内容是否为512字节
//若为512字节,则读取后,回复一个应答包,继续接收下一个
//如果小于512,则读取数据后,回复一个应答包,结束接收数据
//清空协议包
bzero(pack,sizeof(pack));
res=recvfrom(cfd,pack,sizeof(pack),0,(struct sockaddr*)&cin,&socklen); //接收数据包
if(*p1==ntohs(3)) //数据包
{
write(wfd,pack+4,res-4);
//回复应答包
*p1=htons(4);
sendto(cfd,pack,4,0,(struct sockaddr*)&cin,sizeof(cin));
if(res-4<512){
printf("下载完成\n");
break;
}
}else if(*p1==ntohs(5)) //错误包
{
printf("error\n");
return -1;
}
}
close(wfd);
return 0;
}
//定义上传函数
int upload(int cfd,struct sockaddr_in sin)
{
//组件协议包:上传请求
char pack[516]="";
unsigned short *p1=(unsigned short *)pack;
*p1=htons(2); //设置操作码
char file[20]="";
printf("请输入文件名:");
fgets(file,sizeof(file),stdin);
file[strlen(file)-1]=0;
char *p2=(pack+2);
strcpy(p2,file); //文件名
char *p4=p2+strlen(p2)+1;
strcpy(p4,"octet"); //模式位
int packlen=4+strlen(p2)+strlen(p4); //请求包大小
printf("%d\n",packlen);
//向服务器发送请求包
sendto(cfd,pack,packlen,0,(struct sockaddr*)&sin,sizeof(sin));
//以只读的形式打开文件
int rfd=-1;
if((rfd=open(file,O_RDONLY,0664))==-1){
perror("open error");
return -1;
}
int res=0;
struct sockaddr_in cin;
socklen_t socklen=sizeof(cin);
unsigned short num=0; //定义块编号;
while(1)
{
//清空
bzero(pack,sizeof(pack));
res=recvfrom(cfd,pack,sizeof(pack),0,(struct sockaddr*)&cin,&socklen);
if(*p1==ntohs(4)) //接收应答包
{
//发送数据包
*p1=htons(3);
//填充块编号
num++;
*(p1+1)=htons(num);
//读取数据
res=read(rfd,p1+2,512);
sendto(cfd,pack,sizeof(pack),0,(struct sockaddr*)&cin,sizeof(cin));
if(res==0){
printf("上传完成\n");
break;
}else if(res<0){
printf("error\n");
return -1;
}
}else if(*p1==ntohs(5)) //错误包
{
printf("error\n");
return -1;
}
}
close(rfd);
return 0;
}
int main(int argc, const char *argv[])
{
/*
//判断是否外部传参
if(argc!=2){
printf("unknow filename\n");
return -1;
}
*/
//1.创建用于通信的套接字文件描述符
int cfd=-1;
if((cfd=socket(AF_INET,SOCK_DGRAM,0))==-1){
perror("socket error");
return -1;
}
//2.数据收发
//填充服务器的地址信息结构体
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(SER_PORE);
sin.sin_addr.s_addr=inet_addr(SER_IP);
//创建菜单
int menu=0;
while(1)
{
system("clear"); //执行终端指令
printf("\t******1.下载******\n");
printf("\t******2.上传********\n");
printf("\t******3.退出******\n");
printf("请输入选项:");
scanf("%d",&menu);
getchar();//吸收垃圾字符,回车
switch(menu)
{
case 1:
{
//下载
download(cfd,sin);
}
break;
case 2:
{
//上传
upload(cfd,sin);
}
break;
case 3:
{
//退出
goto END;
}
break;
default:printf("enter error\n");break;
}
}
END:
//3.关闭套接字
close(cfd);
return 0;
}
运行结果:
流程图: