#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#define IP "192.168.0.116"
#define ERR_MSG(msg) do{\
fprintf(stderr,"line:__%d__",__LINE__);\
perror("msg");\
}while(0)
int main(int argc, const char *argv[])
{
//创建文件描述符
int fd;
//创建报式套接字
int sfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
printf("socket create success sfd=%d __%d__\n",sfd,__LINE__);
//填充服务器地址信息
struct sockaddr_in sin;
sin.sin_family = AF_INET; //必须填AF_INET
sin.sin_port = htons(69); //端口
sin.sin_addr.s_addr = inet_addr(IP);
//结构体sin的大小
int addrlen = sizeof(sin);
//操作权限
int UD = 0;
puts("*****1:下载文件*****");
puts("*****2:上传文件*****");
scanf("%d",&UD);
while((UD != 1) && (UD != 2))
{
puts("请重新输入");
scanf("%d",&UD);
}
char filename[128] = "";
puts("请输入文件名");
read(0, filename, sizeof(filename));
filename[strlen(filename) - 1] = '\0';
//判断上传文件是否存在的标志
int flag = 0;
//判断上传文件是否存在
if(UD == 2)
{
while(1)
{
DIR *dir = opendir("/home/ubuntu/scorkt/udp/");
struct dirent* dt = NULL;
if(dir == NULL)
{
ERR_MSG(open dir false);
return -1;
}
while((dt = readdir(dir)) != NULL)
{
if(strcmp(filename, dt->d_name) == 0)
{
flag = 1;
break;
}
}
if(flag)
break;
puts("该文件不存在,请重新输入");
read(0, filename, sizeof(filename));
filename[strlen(filename) - 1] = '\0';
closedir(dir);
}
}
//封装读写请求
char *wr = NULL;
int code = 0;
int block = 0;
char buf[516] = "";
bzero(buf, sizeof(buf));
short *p1 = (short *)buf;
*p1 = htons(UD);
char *p2 = buf +2;
strcpy(p2,filename);
char *p3 = p2 + strlen(p2);
*p3 = 0;
char *p4 = p3 + 1;
strcpy(p4, "octet");
char *p5 = p4 + strlen(p4);
*p5 = 0;
//读写请求的数据长度
int size_num = 4 + strlen(p2) + strlen(p4);
ssize_t ret = 0;
//发送读写请求
ret = sendto(sfd, buf, size_num, 0, (struct sockaddr*)&sin, addrlen);
if(ret < 0)
{
ERR_MSG("sendto");
return -1;
}
puts("发送成功");
//记录临时端口信息ack
int ret_code = 0;
struct sockaddr_in lin;
//清空缓存区
bzero(buf,0);
//buf接收数据
ret_code = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&lin, &size_num);
//提取2字节操作码
p1 = (short*)buf;
code = ntohs(*p1);
if(5 == code)
{
//提取2字节差错码
p1 = (short*)(buf + 2);
block = ntohs(*p1);
//提取差错信息
printf("err : %d\t%s\n",block,buf+4);
return -1;
}
//下载文件
if(UD == 1)
{
if(3 == code)
{
//打开文件标识符
fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
if(fd < 0)
{
ERR_MSG("opne false");
return -1;
}
while(1)
{
if(3 == code)
{
//提取2字节块编号
p1 = (short*)(buf + 2);
block = ntohs(*p1);
//移动光标
lseek(fd, (block-1)*512, SEEK_SET);
wr = buf + 4;
write(fd, wr, ret_code-4);
//返回ack
bzero(buf,0);
p1 = (short*)buf;
*p1 = htons(4);
p1 = (short*)(buf + 2);
*p1 = htons(block);
ret = sendto(sfd, buf, 4, 0, (struct sockaddr*)&lin, addrlen);
if(ret < 0)
{
ERR_MSG("sendto");
return -1;
}
if(ret_code < 516)
{
puts("接收完成");
break;
}
//清空缓存区
bzero(buf,0);
//buf接收数据
ret_code = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&lin, &size_num);
//提取2字节操作码
p1 = (short*)buf;
code = ntohs(*p1);
}else if(5 == code)
{
//提取2字节差错码
p1 = (short*)(buf + 2);
block = ntohs(*p1);
//提取差错信息
printf("err : %d\t%s\n",block,buf+4);
return -1;
}
}
}
}else if(UD == 2)//上传文件
{
//打开文件描述符
fd = open(filename, O_RDONLY);
if(fd < 0)
{
ERR_MSG("opne false");
return -1;
}
//循环发送数据包
block = 0; //块编号
while(1)
{
if(4 == code)
{
bzero(buf,0);
p1 = (short*)buf;
*p1 = htons(3);
p1 = (short*)(buf + 2);
*p1 = htons(++block);
ret = read(fd,buf + 4,512);
ret_code = sendto(sfd, buf, ret + 4, 0, (struct sockaddr*)&lin, addrlen);
if(ret_code < 0)
{
ERR_MSG("sendt0 data false");
return -1;
}
if(ret < 512)
{
puts("上传完成");
break;
}
//清空缓存区
bzero(buf,0);
//buf接收数据
ret_code = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&lin, &size_num);
//提取2字节操作码
p1 = (short*)buf;
code = ntohs(*p1);
}else if(5 == code)
{
//提取2字节差错码
p1 = (short*)(buf + 2);
block = ntohs(*p1);
//提取差错信息
printf("err : %d\t%s\n",block,buf+4);
return -1;
}
}
}
//关闭套接字
close(sfd);
close(fd);
return 0;
}
创建客户端接收、上传文件
于 2023-04-22 13:35:51 首次发布