嵌入式:网络编程Day3

 1.编写UDP服务器端、客户端

 udpSer.c

#include <myhead.h>

#define ERR_MSG(msg)  do{\
	fprintf(stderr, "__%d__ ", __LINE__);\
	perror(msg);\
}while(0)

#define IP "192.168.10.124"
#define PORT 6666

int main(int argc, const char *argv[])
{
	//创建报式套接字
	int sfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sfd < 0){
		ERR_MSG("socket");
		return -1;
	}
	printf("sfd = %d\n", sfd);

	//填充服务器的地址信息结构体  AF_INET  man 7 ip
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(PORT);
	sin.sin_addr.s_addr = inet_addr(IP);

	//绑定服务器地址和端口号
	if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0){
		ERR_MSG("bind");
		return -1;
	}
	printf("bind success\n");

	struct sockaddr_in cin;           //存储数据包时从谁那里来的
	socklen_t addrlen = sizeof(cin);

	char buf[128] = "";
	while(1){
		bzero(buf, sizeof(buf));
		//接收数据
		if(recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&cin, &addrlen) < 0){
			ERR_MSG("recvfrom");
			return -1;
		}

		printf("[%s : %d] : %s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);

		//发送数据 ---> 谁发送给我,我发送给谁
		strcat(buf, "*_*");
		if(sendto(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&cin, sizeof(cin)) < 0){
			ERR_MSG("sendto");
			return -1;
		}
		printf("sendto success\n");
	}

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


	return 0;
}

udpCli.c

#include <myhead.h>

#define ERR_MSG(msg)  do{\
	fprintf(stderr, "__%d__", __LINE__);\
	perror(msg);\
}while(0)

#define IP "192.168.10.124"
#define PORT 6666

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

	//填充客户端的地址结构体,给下面的sendto函数使用 AF_INET: man 7 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和随机端口
	
	struct sockaddr_in rcvaddr;           //存储数据包时从谁那里来的
	socklen_t addrlen = sizeof(rcvaddr);
	
	char buf[128] = "";
	while(1){
		bzero(buf, sizeof(buf));
		//发送数据  --->  给服务器
		printf("请输入 >>> ");
		fgets(buf, sizeof(buf), stdin);
		buf[strlen(buf) - 1] = '\0';

		if(sendto(cfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, sizeof(sin)) < 0){
			ERR_MSG("sendto");
			return -1;
		}
		printf("sendto success\n");

		//接收数据
		if(recvfrom(cfd, buf, sizeof(buf), 0, (struct sockaddr*)&rcvaddr, &addrlen) < 0){
			ERR_MSG("recvfrom");
			return -1;
		}

		printf("[%s : %d] : %s\n", inet_ntoa(rcvaddr.sin_addr), ntohs(rcvaddr.sin_port), buf);
	}

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

	return 0;
}

2.编写tftp的下载代码

udpTftpCli.c

#include <myhead.h>

#define ERR_LOG(msg) do{\
	perror(msg);\
	printf("%d %s %s\n", __LINE__, __func__, __FILE__);\
}while(0)

#define IP "192.168.122.61" 
#define PORT 69
#define N 516

int do_download(int , struct sockaddr_in );


int main(int argc, const char *argv[])
{

	//1.创建报式套接字
	int sfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sfd < 0)
	{
		perror("socket");
		return -1;
	}

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


	char choose;
	while(1)
	{
		system("clear");
		printf("******************\n");
		printf("******1.下载******\n");
		printf("******2.上传******\n");
		printf("******3.退出******\n");
		printf("******************\n");

		scanf("%c", &choose);
		while(getchar()!=10);

		switch(choose)
		{
		case '1':
			//下载功能, todo
			do_download(sfd, sin);
			break;
		case '2':
			//上传功能,todo
			//do_upload(sfd, sin);
			break;
		case '3':
			goto END;
			break;
		default:
			printf("输入错误\n");
		}
		printf("请输入任意字符清屏>>>");
		while(getchar()!=10);		
	}

	//关闭文件描述符
END:
	close(sfd);
	return 0;
}



//下载功能
int do_download(int sfd, struct sockaddr_in sin)
{
	char filename[20] = "";
	printf("请输入要下载的文件名>>>");
	fgets(filename, 20, stdin);
	filename[strlen(filename)-1] = 0;

	//发送下载请求
	char buf[N] = "";
	int size = sprintf(buf, "%c%c%s%c%s%c", 0, 1, filename, 0, "octet", 0);

	if(sendto(sfd, buf, size, 0, (struct sockaddr*)&sin, sizeof(sin))<0)
	{
		ERR_LOG("sendto");
		return -1;
	}

	int flag = 0;
	int fd=-1 ;

	//循环接收发送应答包
	ssize_t recv_len;
	unsigned short num = 1;
	socklen_t addrlen = sizeof(sin);
	while(1)
	{
		bzero(buf, N);
		recv_len = recvfrom(sfd, buf, N, 0, (struct sockaddr*)&sin, &addrlen);
		if(recv_len < 0)
		{
			ERR_LOG("recvfrom");
			return -1;
		}
		if(3 == buf[1]) 			//如果是数据包
		{
			if(0 == flag) 	//防止文件重复打开
			{
				//存储从服务器下载下来的文件,接收数据成功后再创建数据;
				//创建并打开filename文件
				fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0664);
				if(fd < 0)
				{
					ERR_LOG("open");
					return -1;
				}
				flag = 1;
			}
			//判断当前的快编号,是否与我期望的快编号一致
			if(htons(num) == *(unsigned short*)(buf+2)) 	//防止数据包重复到达
			{
				//提取数据,写入到文件中
				//char str[513] = "";
				//strncpy(str, buf+4, 512);
				//printf("%s", str);
				//fflush(stdout);

				if(write(fd, buf+4, recv_len-4) < 0)
				{
					printf("fd:%d recv_len=%ld\n", fd, recv_len);
					ERR_LOG("write");
					break;
				}

				//回复ack包
				//由于数据包前四个字节与ack包除了操作码不一致外,其余全部一致。
				//所以我们直接将数据包的操作码修改成4即可,发送数据包的前四个字节。
				buf[1] = 4; 	
				if(sendto(sfd, buf, 4, 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
				{
					ERR_LOG("sendto");
				}

				//判断数据包的大小是否小于 512+2+2;
				if(recv_len < 512+2+2)
				{
					printf("-----文件下载完毕!!-----\n");
					break;
				}
				num++;
			}
		}
		else if(5 == buf[1]) 	//错误包
		{
			//打印错误信息
			printf("-----ERROR:%s-----\n", buf+4);
			break;
		}
	}
	close(fd);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值