作业:实现客户端向服务器下载文件
代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#define ERR_MSG(msg) do{\
printf("line:%d\n",__LINE__);\
perror(msg);\
}while(0);
#define SER_PORT 69
#define SER_IP "192.168.10.118"
int main(int argc, const char *argv[])
{
//创建流式套接字
int cfd = socket(AF_INET,SOCK_DGRAM,0);
if(cfd<0)
{
ERR_MSG("socket");
return -1;
}
printf("socket create sucess cfd=%d __%d__\n",cfd,__LINE__);
//非必须绑定
//如果不绑定,则程序启动后,操作系统会默认绑定本机SER_IP和随机端口
//填充客户端的地址信息结构体,给bind函数使用
//该结构体在 man 7 ip(表示真实的地址信息结构体)
struct sockaddr_in sin;
sin.sin_family = AF_INET; //必须填充AF_INET
sin.sin_port = htons(SER_PORT); //端口号的网络字节序1024~49151
sin.sin_addr.s_addr = inet_addr(SER_IP); //ifconfig查看本机IP
struct sockaddr_in rcvaddr;
socklen_t len =sizeof(rcvaddr);
//组协议
char buf[516]="";
short *ptr1 = (short *)buf;
*ptr1 = htons(1); //操作码,下载
char *ptr2 = buf+2;
strcpy(ptr2,"5.png"); //要下载的文件名
char *ptr3 = ptr2+strlen(ptr2);
*ptr3 = 0;
char *ptr4 = ptr3+1;
strcpy(ptr4,"octet"); //模式
int size = 2+strlen(ptr2)+1+strlen(ptr4)+1;
//打开文件
int fd = open("./copy.txt",O_WRONLY|O_CREAT|O_TRUNC,0777);
if(fd<-1)
{
ERR_MSG("open");
return -1;
}
//发送下载请求包给服务器
if(sendto(cfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("sendto");
return -1;
}
printf("发送成功\n");
short *q1 = (short *)buf;
short *q2 = q1+1;
char *q3 = (char*)(q2+1);
int i=1;
ssize_t res = 0;
while(1)
{
//清空数据包
bzero(buf,sizeof(buf));
//接收数据
res = recvfrom(cfd,buf,sizeof(buf),0,(struct sockaddr *)&rcvaddr,&len);
if(res < 0)
{
ERR_MSG("recvfrom");
return -1;
}
//判断是否ERROR
if(*q1==htons(5))
{
printf("ERROR:[%d] %s\n",ntohs(*q2),q3);
}
//将数据写入文件
if(write(fd,q3,res-4)<0)
{
ERR_MSG("write");
return -1;
}
//ACK应答
bzero(q3,512);
*q1 = htons(4);
if(sendto(cfd,buf,4,0,(struct sockaddr *)&rcvaddr,len)<0)
{
ERR_MSG("sendto");
return -1;
}
printf("[%d]发送成功\n",i);
i++;
if(res<516)
{
printf("文件读取完毕\n");
break;
}
;
}
close(cfd);
return 0;
}
运行结果:
服务器结果:
显示读取文件: