#include<stdio.h>
2 #include<sys/types.h>
3 #include<netinet/in.h>
4 #include<netinet/ip.h>
5 #include<sys/socket.h>
6 #include<stdlib.h>
7 #include<unistd.h>
8 #include<string.h>
9 #include<arpa/inet.h>
10 #include<fcntl.h>
11 #include<sys/stat.h>
12
13 int main(int argc, const char *argv[])
14 {
15 //选择外部传参
16 if(argc<3)
17 {
18 fprintf(stderr,"请输入IP和端口\n");
19 return -1;
20 }
21 //将外部传参的端口号字符串,转化成整形
22 int port=atoi(argv[2]);
23 //填充服务器的IP和端口号-->因为客户需要主动发数据包给服务器
24 //创建报式套接字
25 int sfd=socket(AF_INET,SOCK_DGRAM,0);//udp模式
26 if(sfd<0)
27 {
28 perror("sfd");
29 return -1;
30 }
31 //定义用来接受服务器的IP和地址寻找服务器用
32 struct sockaddr_in sin;
33 sin.sin_family = AF_INET;
34 sin.sin_port = htons(port);
35 sin.sin_addr.s_addr=inet_addr(argv[1]);
36
37 struct sockaddr_in cin;//这里指的要存储的数据包
38 socklen_t len=sizeof(cin);
39 char data[50]="";
40 char *ptr=data;
41 short *sh=(short*)data;
42 *sh=htons(1);
43 char *pb=ptr+2;
44 strcpy(pb,"5.png");
45 char *pc=pb+strlen(pb);
46 *pc=0;
47 strcpy(pc+1,"octet");
48 //计算数组实际占用字符大小
49 int size=2+strlen("5.png")+1+strlen("octet")+1;
50 printf("siz=%d\n",size);
51 if(sendto(sfd,data,size,0,(struct sockaddr*)&sin,sizeof(sin))<0)
52 {
53 perror("sendto");
54 return -1;
55 }
56 printf("sendto success\n");
57 char buf[516]="";//数据包接收
58 char ack[5]="";
59 short *ak;
60 int res=0;//接收返回的字节数
61 short num=1;
62 int fd=open("./1.png",O_WRONLY|O_CREAT,0664);//打开一个写入文件
63 if(fd<0)
64 {
65 perror("open");
66 return -1;
67 }
68 while(1)//循环
69 {
70 //接收服务器发来数据包,谁发来的,我发给谁
71 bzero(buf,sizeof(buf));
72 bzero(ack,sizeof(ack));
73 res=recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,&len);
74 if(0<res||res<=516)
75 {
76 write(fd,buf+4,res-4);
77 printf("res=%d\n",res);
78 if(res<516){
79 printf("数据读取完毕\n");
80 break;
81 }
82
83 }
84 else if(res<0){
85 perror("reveform");
86 close(sfd);
87 return -1;
88 }
89 short *bh=(short*)buf;//强转short型
90 *bh=htons(3);//将所有的操作码数据包的全部转为3
91 ptr=buf;//指针指向数组
92 if(ntohs(*(short*)(buf+2))!=num)
93 {
94 continue;//如果该数据包不是所需要的数据包,重新获取
95 }
96
97 printf("buf=%hd\n",ntohs(*(short*)(buf+2)));
98 ak=(short*)ack;//定义ack操作码
99 *ak=htons(4);//将ack码恒定位4
100 *(short*)(ack+2)=htons(num);//将块编号赋值给ack块编号
101
102 printf("%hd\n",ntohs(*(short*)(ack+2)));
103 //bzero(ack,sizeof(ack));
104 if(sendto(sfd,ack,4,0,(struct sockaddr*)&cin,sizeof(cin))<0)
105 {
106 perror("sendto");
107 return -1;
108 }
109 num++;//完成一次数据收发编号增加一次;
110 }
111 //关闭套接字
112 close(sfd);
113 return 0;
114 }
搭建tcp服务器
最新推荐文章于 2023-04-27 15:51:16 发布