c
复制代码
#include<myhead.h>
#define SER_IP "192.168.109.125" //服务器ip地址
#define SER_PORT 69 //服务器端口号
#define CLI_IP "192.168.117.113" //客户端ip地址
#define CLI_PORT 9999 //客户端端口号
void dowload(int cfd,struct sockaddr_in sin,socklen_t addrlen)
{
//定义协议包数组
char msgBuf[516] = "";
//提示并输入文件名
char fileName[21] = ""; //记录文件名
printf("请输入您要下载的文件名:");
scanf("%s", fileName);
//封装请求协议
short *p1 =(short *)msgBuf; //封装请求
*p1 = htons(1); //表示下载请求包
char *p2 = msgBuf + 2; //文件名部分
strcpy(p2, fileName);
char *p4 = p2 + strlen(p2) + 1; //传输模式
strcpy(p4, "octet");
int msgLen = 2 + strlen(p2) + strlen(p4) +2; //请求包的长度
//将消息发送给服务器
sendto(cfd, msgBuf, msgLen, 0, (struct sockaddr*)&sin, sizeof(sin));
ssize_t len;
//以只写的形式打开一个文件,文件名为 fileName
umask(0);
int fd=open(fileName,O_WRONLY | O_CREAT | O_TRUNC,0664);
while(1)
{
//接收服务器发来的数据包
//判断是错误包还是数据包
len=recvfrom(cfd,msgBuf,516,0,(struct sockaddr*)&sin,&addrlen);
//如果是数据包,读取数据包4字节之后的数据
//如果数据包长度为512,则将消息写入文件后
//向服务器回复一个应打包
//如果数据包长度小于512,则接收完数据写入文件后,回复一个应打包后,就可以
//结束循环了
if(msgBuf[1]==3)
{
write(fd,msgBuf+4,len-4);
msgBuf[1]=4;
sendto(cfd, msgBuf, 4, 0, (struct sockaddr*)&sin, sizeof(sin));
if(len-4<512)
{
break;
}
}
else if(msgBuf[1]==5)
{
if(msgBuf[3]==1)
{
remove(fileName);
}
printf("%s\n",msgBuf+4);
break;
}
}
}
void updoading(int cfd,struct sockaddr_in sin,socklen_t addrlen)
{
//定义协议包数组
char msgBuf[516] = "";
//提示并输入文件名
char fileName[21] = ""; //记录文件名
printf("请输入您要上传的文件名:");
scanf("%s", fileName);
//以只读的形式打开一个文件,文件名为 fileName
int fd=open(fileName,O_RDONLY);
if(fd==-1)
{
perror("open error");
return;
}
//封装请求协议
short *p1 =(short *)msgBuf; //封装请求
*p1 = htons(2); //表示上传请求包
char *p2 = msgBuf + 2; //文件名部分
strcpy(p2, fileName);
char *p4 = p2 + strlen(p2) + 1; //传输模式
strcpy(p4, "octet");
int msgLen = 2 + strlen(p2) + strlen(p4) +2; //请求包的长度
//将消息发送给服务器
sendto(cfd, msgBuf, msgLen, 0, (struct sockaddr*)&sin, sizeof(sin));
int len;
while(1)
{
//接收服务器发来的ACK
//判断是错误包还是ACK
recvfrom(cfd,msgBuf,4,0,(struct sockaddr*)&sin,&addrlen);
//如果是ACK,写入数据在数据包4字节之后
//如果数据包长度为512,则将消息写入文件后,向服务器回复一个数据包
//如果数据包长度小于512,则发送数据包后,结束循环
if(msgBuf[1]==4)
{
len=read(fd,msgBuf+4,512);
printf("len=%d\n",len);
msgBuf[1]=3;
sendto(cfd, msgBuf,len+4, 0, (struct sockaddr*)&sin, sizeof(sin));
if(len<512)
{
break;
}
}
else if(msgBuf[1]==5)
{
printf("%s\n",msgBuf+4);
break;
}
}
}
int main(int argc, const char *argv[])
{
//1、创建用于通信的套接字文件描述符
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(-1 == cfd)
{
perror("socket error");
return -1;
}
printf("socket success cfd = %d\n", cfd); //3
//2、绑定ip地址和端口号(可选)
//2.1 填充客户端地址信息结构体
struct sockaddr_in cin;
cin.sin_family = AF_INET; //通信域
cin.sin_port = htons(CLI_PORT); //客户端端口号
cin.sin_addr.s_addr = inet_addr(CLI_IP); //客户端ip地址
//2.2 进行绑定工作
if(bind(cfd, (struct sockaddr*)&cin, sizeof(cin)) == -1)
{
perror("bind error");
return -1;
}
printf("bind success\n");
//3、数据收发
//封装服务器的地址信息结构体
struct sockaddr_in sin; //服务器地址信息结构体
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT); //服务器端口号
sin.sin_addr.s_addr = inet_addr(SER_IP); //服务器ip地址
socklen_t addrlen = sizeof(sin); //地址信息结构体的大小
int num;
while(1)
{
printf("1.下载\n");
printf("2.上传\n");
printf("3.退出\n");
scanf("%d",&num);
switch(num)
{
case 1:
dowload(cfd,sin,addrlen);
break;
case 2:
updoading(cfd,sin,addrlen);
break;
case 3:
break;
}
if(num==3)
break;
}
//4、关闭客户端
close(cfd);
return 0;
}