1.TCP機械臂測試
程序代碼:
1 #include<myhead.h>2 #define SER_IP "192.168.126.112" //服務器IP3 #define SER_PORT 8888 //服務器端口號4 5 #define CLI_IP "192.168.126.121" //客戶端IP6 #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;//地址族,IPv421 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;//地址族IPv437 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;
}
運行結果:
?流程圖: