作业10.21

广播

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

#define MSG_ERR(msg)do{\
	fprintf(stderr,"line:%d",__LINE__);\
	perror("msg");\
}while(0);

int main(int argc, const char *argv[])
{
	//创建报式套接字
	int sfd=socket(AF_INET,SOCK_DGRAM,0);
	if(sfd<0){
		MSG_ERR("socket");
		return -1;
	}
	//填充发送端的IP和端口号用于bind函数绑定
	struct sockaddr_in cin;
	cin.sin_family 		=AF_INET;
	cin.sin_port 		=htons(7777);
	cin.sin_addr.s_addr =inet_addr("192.168.250.255");


	if(bind(sfd,(struct sockaddr*)&cin,sizeof(cin))<0){
		MSG_ERR("bind");
		return -1;
	}
	printf("bind success\n");

	//设置允许广播
	int set_broad=1;
	if(setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&set_broad,sizeof(set_broad))<0){
		MSG_ERR("setbroadopt");
		return -1;
	}
	printf("set broadcast success\n");


	//填充接收端的IP和端口号,用于sendto 函数的时候发送给服务器使用
	
	struct sockaddr_in sin;
	sin.sin_family 		=AF_INET;
	sin.sin_port 		=htons(9999);
	sin.sin_addr.s_addr =inet_addr("192.168.150.255");
	

	struct sockaddr_in rcvaddr;
	socklen_t addrlen=sizeof(rcvaddr);

	char buf[128]="";
	ssize_t res=0;
	while(1){
		//从终端获取数据发送给服务器
		printf("请输入:");
		fgets(buf,sizeof(buf),stdin);
		buf[strlen(buf)-1]=0;
		//发送数据给服务器,地址信息结构体应该填服务器的地址信息
		if(sendto(sfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin))<0){
			MSG_ERR("sendto");
			return -1;
		}
		printf("send  success\n");

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

 

 tftp的上传下载

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

#define MSG_ERR(msg)do{\
	fprintf(stderr,"line:%d",__LINE__);\
	perror("msg");\
}while(0);

int do_download(int sfd,struct sockaddr_in sin);

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

	//填充服务器IP和的端口供于bind函数绑定
	
	struct sockaddr_in cin;
	cin.sin_family 			=AF_INET;
	cin.sin_port 			=htons(8888);
	cin.sin_addr.s_addr 	=inet_addr("192.168.250.135");//客户端运行所在IP

	if(bind(sfd,(struct sockaddr*)&cin,sizeof(cin))<0){
		MSG_ERR("bind");
		return -1;
	}
	printf("bind success\n");

	//填充服务器的IP和端口,供于下面sendto的函数发送给服务器的时候使用
	struct sockaddr_in sin;
	sin.sin_family 		=AF_INET;
	sin.sin_port 		=htons(69);
	sin.sin_addr.s_addr =inet_addr("192.168.255.135");
	


	//选择上传还是下载,或者退出
	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;
				break;
			case'2':
				do_download(sfd,sin);
				break;
			case'3':
				goto END;//少用goto 会破坏程序结构
				break;
			default:
				printf("Put error,please put again!\n");
			
		}
	}
END:
	//关闭文件描述符
	close(sfd);
	return 0;
}

int do_download(int sfd,struct sockaddr_in sin){
	//组下载请求包,发送给服务器,服务器在69号端口等待请求
	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=2+strlen(pb)+7;

		//发送协议
		if(sendto(sfd,buf,size,0,(struct sockaddr*)&sin,sizeof(sin))<0){
			MSG_ERR("sendto");
			return -1;
		}
		printf("download request success\n");

		socklen_t addrlen=sizeof(sin);
		ssize_t res=0;

		unsigned short num=0;
		while(1){
			bzero(buf,sizeof(buf));
			//循环接收数据包,地址信息结构体必须接,后续要将ack发给临时端口
			res=recvfrom(sfd,buf,516,0,(struct sockaddr*)&sin,&addrlen);
			if(res<0){
				MSG_ERR("recvfrom");
				return -1;
			}


			//由于发送回来的操作码都是网络字节序,所有有效的操作码都存储在buf[1]的位置
			//只要判断buf[1]是3还是5即可
			if(3==buf[1]){ // 数据包
				//由于UDP可能丢失,或者重复到达,所以需要在每次接收到数据包的时候
				//判断一下这个包是不是我需要的,通过快编号判断
				if(num+1==ntohs(*(unsigned short*)(buf+2))){
					//处理数据,数据首地址在buf+4的位置上
					printf("%s",buf+4);//修改成写入到文件中
					fflush(stdout);

					//回复ACK
					buf[1]=4;
					if(sendto(sfd,buf,4,0,(struct sockaddr*)&sin,sizeof(sin))<0){
						MSG_ERR("sendto");
						return -1;
					}

					//如果数据小于512个字节,则传输结束
					if(res-2-2<512){
						printf("Send msg over!\n");
						break;
					}
					num++;
				}
			}
			else if(5==buf[1])  //错误报
				{
					printf("ERROR:%s\n",buf+4);
					return -2;
				}
		}
		return 0;
}

	   

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值