2022-10-22 网络编程作业,广播代码,tftp协议

广播代码

接收

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

#define PORT 8888
#define IP "192.168.8.255"
#define ERR_MSG(msg) do{\
		fprintf(stdout, "%d", __LINE__);\
		perror(msg);\
}while(0)

int main(int argc, const char *argv[])
{
	//创建广播接收端
	
	//创建套接字
	int ufd = socket(AF_INET, SOCK_DGRAM, 0);
	if(ufd < 0)
	{
		ERR_MSG("socket");
		return -1;
	}
	puts("socket success");

	//填充服务器的IP和端口
	struct sockaddr_in sin;
	sin.sin_family 		= AF_INET;
	sin.sin_port 		= htons(PORT); //端口号
	sin.sin_addr.s_addr = inet_addr(IP); //IP

	//绑定IP地址和端口号
	if(bind(ufd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
	{
		ERR_MSG("bind");
		return -1;
	}
	puts("bind success");

	char buf[128] = "";

	//如果想知道数据包从谁那发过来
	//需要定义地址数据结构体和长度来接收
	struct sockaddr_in cin;
	socklen_t addrlen;

	while(1)
	{
		//接收数据
		//if(recvfrom(ufd, buf, sizeof(buf), 0, NULL, NULL) < 0)
		if(recvfrom(ufd, buf, sizeof(buf), 0, (struct sockaddr *)&cin, &addrlen) < 0)
		{
			ERR_MSG("recvfrom");
			return -1;
		}
		puts("recvfrom success");

		//终端显示数据
		printf("%s : %d buf:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);
	}

	//关闭套接字
	close(ufd);

	return 0;
}

发送

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

#define ERR_MSG(msg) do{\
        fprintf(stdout, "%d", __LINE__);\
        perror(msg);\
}while(0)

int main(int argc, const char *argv[])
{
	//创建套接字
	int sfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sfd < 0)
	{
		ERR_MSG("socket");
		return -1;
	}
	puts("socket success");

	//填充服务器IP和端口
	struct sockaddr_in sin;
	sin.sin_family 		= AF_INET;
	sin.sin_port 		= htons(8888);
	sin.sin_addr.s_addr = inet_addr("192.168.8.255");
	
	//设置允许广播
	int broad = 1;
	if(setsockopt(sfd, SOL_SOCKET, SO_BROADCAST, &broad, sizeof(broad)) < 0)
	{
		ERR_MSG("setsockopt");
		return -1;
	}
/*
	//当udp中使用connect时
	//只能和指定的服务器或客户端通信
	//同时sendto和recvfrom可以改成send和recv
	//如果继续使用sendto和recvfrom,要把后面参数改成NULL,0和NULL, NULL
	if(connect(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
	{
		ERR_MSG("connect");
		return -1;
	}
	puts("connect success");
*/
	
	char buf[128] = "";
	while(1)
	{
		//客户端发送数据包给服务器
		printf("请输入:");
		bzero(buf, sizeof(buf));
		fgets(buf, sizeof(buf), stdin);
		buf[strlen(buf) - 1] = 0;
		if(sendto(sfd, buf, sizeof(buf), 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
		//if(send(sfd, buf, sizeof(buf), 0) < 0)
		{
			ERR_MSG("sendto");
			return -1;
		}
		puts("sendto success");
	}
	//关闭套接字
	close(sfd);
	
	return 0;
}

tftp协议

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

int do_download(int sfd, struct sockaddr_in sin);
int do_upload(int sfd, struct sockaddr_in sin);

#define ERR_MSG(msg) do{\
		fprintf(stdout, "%d", __LINE__);\
		perror(msg);\
}while(0)

int main(int argc, const char *argv[])
{
	//客户端
	//创建套接字文件
	int sfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sfd < 0)
	{
		ERR_MSG("socket");
		return -1;
	}
	puts("socket success");

	//填充服务器地址结构体
	struct sockaddr_in sin;
	sin.sin_family 		= AF_INET;
	sin.sin_port 		= htons(69);
	sin.sin_addr.s_addr = inet_addr("192.168.8.67");

	//选择是上传还是下载,或者退出
	char c = 0;
	while(1)
	{
		printf("------------------------------\n");
		printf("-----------1. 上传------------\n");
		printf("-----------2. 下载------------\n");
		printf("-----------3. 退出------------\n");
		printf("------------------------------\n");
		printf("请输入>>>");
		c = getchar();
		while(getchar()!=10);

		switch(c)
		{
		case '1':
			do_upload(sfd, sin);
			break;
		case '2':
			do_download(sfd, sin);
			break;
		case '3':
			goto END;
			break;
		default:
			printf("输入错误,请重新输入!\n");             
		}
	}

END:
	//关闭套接字文件
	close(sfd);
	return 0;
}

int do_download(int sfd, struct sockaddr_in sin)
{
	//读写请求
	char buf[520] = "";

	unsigned short *pa =(unsigned short *)buf;
	*pa = htons(1);

	printf("请输入需要下载的文件名:");
	char name[20] = "";
	scanf("%s", name);
	char *pb = buf + 2;
	strcpy(pb, name);

	char *pd = pb + strlen(pb) + 1;
	strcpy(pd, "octet");

	int size = strlen(pb) + strlen(pd) + 4;

	//发送读写请求
	if(sendto(sfd, buf, size, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
	{
		ERR_MSG("sendto");
		return -1;
	}
	puts("sendto success");
	
	ssize_t res = 0;
	socklen_t addrlen = sizeof(sin);
	unsigned short count = 1; 	//块编号
	unsigned short data;
	int fd;
	while(1)
	{
		//客户端接收数据包
		bzero(buf, sizeof(buf));
		res = recvfrom(sfd, buf, 516, 0, (struct sockaddr*)&sin, &addrlen);
		if(res < 0)
		{
			ERR_MSG("recvfrom");
			return -1;
		}
		if(buf[1] == 3)
		{
			if(count == ntohs(*(unsigned short*)(buf+2)))
			{
				int fd = open("./1.c", O_WRONLY|O_CREAT|O_APPEND, 0777);
				if(fd < 0)
				{
					ERR_MSG("open");
					return -1;
				}
				if(write(fd, buf+4, 512) < 0)
				{
					ERR_MSG("write");
					return -1;
				}

				//客户端发送ack包
				buf[1] = 4;
				if(sendto(sfd, buf, 4, 0, (struct sockaddr*)&sin, addrlen) < 0)
				{
					ERR_MSG("sendto");
					return -1;
				}
				if(res < 516) 	//数据长度小于512,停止发送
				{
					break;
				}
				count++;
			}
		}
		else if(buf[1] == 5) 	//错误信息
		{
			printf("ERROR:%s\n",buf+4);
			return -2;
		}
	}
	return 0;
}


int do_upload(int sfd, struct sockaddr_in sin)
{	
	socklen_t addrlen = sizeof(sin);
	char buf[520] = "";
	ssize_t res = 0;
	unsigned short count = 0; 	//块编号

	//读写请求
	//操作码
	unsigned short* pa = (unsigned short*)buf;
	*pa = htons(2);
	//文件名
	printf("请输入需要上传的文件名:");
	char name[20] = "";
	scanf("%s", name);
	char *pb = buf + 2;
	strcpy(pb, name);
	//模式
	char *pc = pb+1+strlen(pb);
	strcpy(pc,"octet");
	int size = 4+strlen(pb)+strlen(pc);

	//发送读写请求
	if(sendto(sfd, buf, size, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
	{
		ERR_MSG("sendto");
		return -1;
	}
	puts("sendto success");

	//打开文件
	int fd = open(name, O_RDONLY);
	if(fd < 0)
	{
		ERR_MSG("open");
		return -1;
	}

	while(1)
	{
		//接收同意ack包
		bzero(buf, sizeof(buf));
		if(recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, &addrlen) < 0)
		{
			ERR_MSG("recvfrom");
			return -1;
		}
		printf("ack包接收成功\n");
		
		//错误信息
		if(buf[1] == 5)
		{
			printf("ERROR:%s\n",buf+4);
			return -1;
		}

		if(count == ntohs(*(unsigned short*)(buf+2)))
		{
			buf[1] = 3;
			count++;
			*(unsigned short*)(buf+2) = htons(count);
			//读取文件
			res = read(fd, buf+4, 512);
			if(res < 0)
			{
				ERR_MSG("read");
				return -1;
			}

			//上传文件
			if(sendto(sfd, buf, 516, 0, (struct sockaddr*)&sin, addrlen) < 0)
			{
				ERR_MSG("sendto");
				return -1;
			}
			if(res <512)
			{
				printf("文件读取完毕\n");
				break;
			}
		}
		else
		{
			printf("文件发送错误\n");
		}
		if(buf[1] == 5)
		{
			printf("ERROR:%s\n", buf+4);
			return -1;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值