2022.10.21work

1. 完成广播代码

发送端

#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>

#define IP "192.168.196.255"
#define PORT 8888

int main(int argc, const char *argv[])
{
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd<0){
		perror("socket");
		return -1;
	}

	struct sockaddr_in rst;
	rst.sin_family=AF_INET;
	rst.sin_port=htons(PORT);
	rst.sin_addr.s_addr=inet_addr(IP);

	int enbroad=1;
	int optlen=sizeof(enbroad);

	setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&enbroad,optlen);
	int i=0;
	char senbuf[]="test\n";
	while(1){
		sendto(sfd,senbuf,sizeof(senbuf),0,(struct sockaddr *)&rst,sizeof(rst));
		sleep(1);

	}

	return 0;
}

接收端

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define IP "192.168.196.255"
#define PORT 8888

int main(int argc, const char *argv[])
{
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd<0){
		perror("socket");
		return -1;
	}

	struct sockaddr_in urst;
	urst.sin_family=AF_INET;
	urst.sin_port=htons(PORT);
	urst.sin_addr.s_addr=inet_addr(IP);
	socklen_t rstlen=sizeof(urst);
	if(bind(sfd,(struct sockaddr *)&urst,rstlen)){
		perror("bind");
		return -1;
	}

	char recbuf[50];
	int reclen=0;
	while(1){
		reclen=recvfrom(sfd,recbuf,50,0,NULL,0);
		fwrite(recbuf,1,reclen,stdout);
		fflush(stdout);
	}
	
	return 0;
}


2. 完成tftp的上传下载

tftp模型

下载

上传 

 tftp协议语句结构

 

tftp.c

#include <stdio.h>
#include "tftp.h"


void menu()
{
	char opt='a';
	system("clear");
	printf("服务器IP地址:");
	char IP[16]="";
	fgets(IP,15,stdin);
	IP[strlen(IP)-1]=0;
	char filename[100]="";
	system("clear");
	while(1){
		system("ls");
		printf("----------\n");
		printf("-1.下载---\n");
		printf("-2.上传---\n");
		printf("-3.退出---\n");
		printf("----------\n");
		printf(":");
		scanf(" %c",&opt);
		while(getchar()!='\n');
		switch(opt)
		{
			case '1':
				bzero(filename,100);
				printf("下载文件名:");
				fgets(filename,100,stdin);
				filename[strlen(filename)-1]=0; // 去结尾回车符,下同
				download(IP,filename);
				system("clear");
				printf("下载完成\n");
				break;
			case '2':
				bzero(filename,100);
				printf("上传文件名:");
				fgets(filename,100,stdin);
				filename[strlen(filename)-1]=0;
				upload(IP,filename);
				system("clear");
				printf("上传完成\n");
				break;
			case '3':
				return;
				break;
		}
	
	}

}


// 构建请求指令
char *questmd(const char *IP,const char *filename)
{
	int namelen=strlen(filename);
	char *reqmd=(char *)malloc(namelen+9);
	bzero(reqmd,namelen+9);
	reqmd[1]=1;
	strcpy(reqmd+2,filename);
	strcpy(reqmd+3+namelen,"octet");
/*	
 	for(int i=0;i<namelen+9;i++){
		printf("%d ",reqmd[i]);
	}
*/
	return reqmd;

}
// 下载
int download(const char *IP,const char *filename)
{
	char *qmd=questmd(IP,filename);
	int filenamelen = strlen(filename);
	// 准备文件进行拷贝
	int fwd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0777);
	if(fwd<0){
		MSG_ERR("open");
	}

	// 创建套接字
	int urd=socket(AF_INET,SOCK_DGRAM,0);
	
	// tftp服务器地址信息结构体
	struct sockaddr_in ust;
	ust.sin_family=AF_INET;
	ust.sin_port=htons(PORT);
	ust.sin_addr.s_addr=inet_addr(IP);
	
	// 接受数据包
	char recbuf[516];
	int reclen=516;
	// ACK
	char ackbuf[4];
	bzero(ackbuf,4);
	ackbuf[1]=4;
	short ackrec=0;  // 记录快编号,复制重复接受
	struct sockaddr_in tempust;
	int templen;
	sendto(urd,qmd,filenamelen+9,0,(struct sockaddr *)&ust,sizeof(ust));
	do{
		bzero(recbuf,516);
		reclen=recvfrom(urd,recbuf,516,0,(struct sockaddr*)&tempust,&templen);
//		printf("%d___%d\n",ackrec,ntohs(*(short int *)(recbuf+2)));
		if(ackrec<ntohs(*(short int *)(recbuf+2))){    // 对比块编号防止重复下载
			ackrec=ntohs(*(short int *)(recbuf+2));
			ackbuf[2]=recbuf[2];ackbuf[3]=recbuf[3];
			write(fwd,recbuf+4,reclen-4);
		}
		sendto(urd,ackbuf,4,0,(struct sockaddr*)&tempust,templen);
	}while(reclen==516);
	close(fwd);
	close(urd);
	return 0;
}

// 上传
int upload(const char *IP,const char *filename)
{
	char *qmd=questmd(IP,filename);
	qmd[1]=2;
	int filenamelen=strlen(filename);
	int frd=open(filename,O_RDONLY);
	if(frd <0){
		MSG_ERR("open");
	}
	
	// 创建套接字
	int uwd=socket(AF_INET,SOCK_DGRAM,0);

	// tftp服务器地址信息结构体
	struct sockaddr_in ust;
	ust.sin_family=AF_INET;
	ust.sin_port=htons(PORT);
	ust.sin_addr.s_addr=inet_addr(IP);


	// 发送缓存
	char senbuf[516];
	senbuf[0]=0;senbuf[1]=3;
	
	// 读取文件长度
	int redlen=512;
	
	// 接受ACK
	char ackbuf[4];
	bzero(ackbuf,4);
	
	short blocknum=1; // 快编号

	// tftp临时端口
	struct sockaddr_in tempust;
	int templen;
	int sendlen = sendto(uwd,qmd,filenamelen+9,0,(struct sockaddr *)&ust,sizeof(ust));
	do{
		printf("%d_____%d\n",blocknum,ntohs(*(short *)(ackbuf+2)));
		recvfrom(uwd,ackbuf,4,0,(struct sockaddr *)&tempust,&templen);
		if((blocknum-1)==ntohs(*(short *)(ackbuf+2))){    // 对比ACK返回块编号,确保上传数据被接收
			bzero(senbuf+2,514);
			redlen = read(frd,senbuf+4,512);
			*(short int *)(senbuf+2)=htons(blocknum);
			blocknum++;
		}
		sendto(uwd,senbuf,redlen+4,0,(struct sockaddr *)&tempust, templen);
	}while(redlen==512);


}

tftp.h

#ifndef __TFTP_H__
#define __TFTP_H__

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>



#define MSG_ERR(msg) {\
	printf("%d",__LINE__);\
	perror(msg);\
	return -1;\
}

#define PORT 69

// 目录
void menu();


// 构建请求指令
char *questmd(const char *IP,const char *filename);

// 下载
int download(const char *IP,const char *filename);

// 上传
int upload(const char *IP,const char *filename);

#endif 

main.c

#include <stdio.h>
#include "tftp.h"

int main(int argc, const char *argv[])
{
	menu();
	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值