图片:
#if 1 //-----------组【写】请求-------------//
int main()
{
//创建套接字
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if(sock_fd < 0)
{
perror("error");
}
else
{
printf("创建成功! %d\n", sock_fd);//文件描述符0 1 2已被使用,最小就是3开始
}
//【虚拟机】给【服务器Tptpd32】发送【上传】a.txt的请求
//服务器就是我们的Tptpd32工具
//他的IP是我们的本机IP:10.36.145.91
//端口固定69
//给【特定端口、IP】发送请求
struct sockaddr_in ser_addr;
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons(69); //指定端口 69,虚拟机下都是小端,转成window下识别的大端数据
inet_pton(AF_INET, "10.36.145.91", (void *)&ser_addr.sin_addr);//指定IP,点分十进制,转成32位无符号整数,window下识别的IP数据
//组【写】请求
char buf[64] = "";
int buf_len = sprintf(buf, "%c%c%s%c%s%c", 0, 2,"a.txt", 0, "netascii", 0);
//把组写请求,发送到服务器上
//等待服务器回应
sendto(sock_fd, buf, buf_len, 0, (struct sockaddr *)&ser_addr, sizeof(ser_addr));
//打开本地文件
int fd = open("a.txt", O_RDWR);
if(fd < 0)
{
perror("error");
return 0;
}
//接收数据包
char rec_buf[1024] = "";//不能小于516
int rec_buf_len = 0;
unsigned short p_num = 0;//short类型占两个字节,计算【块编号】
//存储服务器的信息-----交流的时候服务器的端口,一直是【动态】的
struct sockaddr_in from_addr;
socklen_t addrlen = sizeof(from_addr);
while(1)
{
bzero(&from_addr, sizeof(from_addr));
//上面发送了写信息
//会从服务器接收到ACK的包信息:[0 4 0 0],存进rec_buf数组
recvfrom(sock_fd, rec_buf, sizeof(rec_buf), 0,\
(struct sockaddr*)&from_addr, &addrlen);
//根据操作码的第二位的标志位判定
//接收出差错了
if(rec_buf[1] == 5)
{
printf("error = %s\n", rec_buf + 4);
break;
}
else if(rec_buf[1] == 4)
{//先收到一次ACK[0 4 0 0]---->然后发送数据包,数据包构成:[0 3 0 1 512byte]
//[0 3 0 1]:操作位+块编号
//512byte:一次上传服务器内容大小
//跳过[0 4 0 0]前四位【操作码、块编号】
//把文件内容读到数组中,读512字节数据
rec_buf_len = read(fd, rec_buf + 4, 512);
//在网络层通过IP进行信息交互
//数据格式需要改变!!!
//ACK收到,开始发送数据包
rec_buf[1] = 3;
//接收到一个,需要对块编号,进行++了
//unsigned short * :拿到编号位short两个字节的[0 0]的首地址,
//取地址,把计算后的值 0 赋值给p_num
//先在客户端【虚拟机】上,对数据包的块编号+1,
//且需要对之前从服务器接收到的大端【块编号】,进行小端处理才行
p_num = ntohs( *(unsigned short *)(rec_buf + 2));
//p_num + 1 得到--->1
//再计算完成后
//转成服务器适用的【大端】数据
//1 变成 [0 1],第一位补0,完成块编号的++操作
*(unsigned short *)(rec_buf + 2) = htons(p_num + 1);
printf("即将发送数据包编号:%d\n",p_num+1);
//发送的数据,去除【操作码、块编号】的四个字节
sendto(sock_fd, rec_buf, rec_buf_len + 4, 0, (struct sockaddr*)&from_addr,sizeof(from_addr));
if(rec_buf_len < 512)
{
printf("文件读取完\n");
break;
}
}
}
close(sock_fd);
close(fd);
return 0;
}
#endif