网络安全传输系统(2)—框架搭建

1.框架搭建需要实现文件上传和下载等的基本功能

  • 网络协议采用TCP协议,通过TCP协议传输文件打算采取如下的顺序(针对客户机而言):
    • 1、先发送命令,1代表上传,2代表下载,3代表退出
    • 2、发送文件名
    • 3、发送文件长度
    • 4、发送文件数据
  • 因此对于上传文件客户机和服务器分别遵循如下顺序
  • 客户机:
    • 1、获取需要上传的文件名
    • 2、打开文件
    • 3、发送命令1
    • 4、发送文件名
    • 5、发送文件长度
    • 6、发送文件数据
    • 7、关闭文件
  • 服务器:
    • 1、接收命令,根据命令做相应的处理
    • 2、接收文件名
    • 3、创建/打开文件
    • 4、接收文件长度
    • 5、接收文件数据
    • 6、关闭文件
  • 对应下载文件和这个过程类似。同时对于客户机而言还有打印菜单等需求。在退出时客户机和服务器都需要做出相应的操作。

2.源码

  • client.c
#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include <sys/stat.h>
#include<errno.h>
#include<fcntl.h>
#include<unistd.h>

#define port 3333

char ipaddr[15];
int sockfd;
struct sockaddr_in sockaddr;

void linkS()
{
	//创建socket
	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket");
		_exit(0);
	}

	// 连接
	// 2.1 初始化地址
	memset(&sockaddr, 0, sizeof(sockaddr));
	sockaddr.sin_family = AF_INET;  // 设置地址族协议为ipv4
	sockaddr.sin_port = htons(port);  // 设置地址的端口号信息,将主机字节序转换成网络字节序
	sockaddr.sin_addr.s_addr = inet_addr(ipaddr);  // 将字符串型ip地址(点分十进制)转换成32位网络字节序的ip地址,或者inet_aton();
	
	// 2.2 连接服务器
	if (connect(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) == -1)
	{
		perror("connect");
		_exit(0);
	}
}

void upload_file(char *filename)
{
	int fd;
	char cmd = 'U';
	int FileNameSize = strlen(filename);
	char buf[1024];
	int count = 0;
	struct stat fstat;

	// 打开文件
	fd = open(filename, O_RDONLY);

	// 发送命令
	write(sockfd, &cmd, 1);

	//发送文件名
	write(sockfd, (void *)&FileNameSize, 4);
	write(sockfd, filename, FileNameSize);

	// 发送文件长度
	if ((stat(filename, &fstat)) == -1)
		return;
	write(sockfd, (void *)&fstat.st_size, 4);

	// 发送文件数据
	while ((count = read(fd, (void *)buf, 1024)) > 0)
	{
		write(sockfd, buf, count);
	}
	// 关闭文件
	close(fd);
}

void download_file(char *filename)
{
	int fd;
	char cmd = 'D';
	char buf[1024];
	int FileNameSize = strlen(filename);
	int filesize = 0, count = 0, totalrecv = 0;

	//发送命令
	write(sockfd, &cmd, 1);

	//发送文件名
	write(sockfd, (void *)&FileNameSize, 4);
	write(sockfd, filename, FileNameSize);

	//打开并创建文件
	if ((fd = open(filename, O_RDWR | O_CREAT)) == -1)
	{
		perror("open:");
		_exit(0);
	}

	//接收数据
	read(sockfd, &filesize, 4);
	while ((count = read(sockfd, (void *)buf, 1024)) > 0)
	{
		write(fd, buf, count);
		totalrecv += count;
		if (totalrecv == filesize)
			break;
	}

	//关闭文件
	close(fd);
}

void quit()
{
	char cmd = 'Q';

	//发送命令
	write(sockfd, (void *)&cmd, 1);

	//清屏
	system("clear");

	//退出
	_exit(0);
}

void menu()
{
	char cmd;
	char c;
	char file_u[30];
	char file_d[30];
	while (1)
	{
		printf("\n------------------------------  1.Upload Files  ------------------------------\n");
		printf("------------------------------  2.Download Files  ------------------------------\n");
		printf("------------------------------      3.Exit   ------------------------------------\n");
		printf("Please input the Client command:");
		cmd = getchar();

		switch (cmd)
		{
			case '1':
			{
				printf("Upload Files:");
				//输入文件名
				while ((c = getchar()) != '\n' && c != EOF);
				fgets(file_u, 30, stdin);
				file_u[strlen(file_u) - 1] = '\0';
				//上传文件
				upload_file(file_u);
			}
			break;
			
			case '2':
			{
				printf("Download Files:");
				//输入文件名
				while ((c = getchar()) != '\n' && c != EOF);
				fgets(file_d, 30, stdin);
				file_d[strlen(file_d) - 1] = '\0';
				//下载文件
				download_file(file_d);
			}
			break;
			
			case '3':
			{
				//退出
				quit();
				break;
			}
			break;
			
			default:
			{
				printf("Please input right command!");
			}
			break;
		}
	}
}

int main(int argc, char *args[])
{
	if (argc != 2)
	{
		printf("format error: you mast enter ipaddr like this : client 192.168.0.6\n");
		_exit(0);
	}
	strcpy(ipaddr, args[1]);
	//建立连接
	linkS();

	//打印菜单
	menu();

	//结尾操作
	close(sockfd);

	return 0;
}
  • server.c
#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<errno.h>
#include<fcntl.h>
#include<unistd.h>

#define port 3333

int sockfd, newfd;
struct sockaddr_in sockaddr;
struct sockaddr_in client_addr;
int sin_size;

void handle(char cmd)
{
	char filename[30] = { 0 };
	int FileNameSize = 0;
	int fd;
	int filesize = 0;
	int count = 0, totalrecv = 0;
	char buf[1024];
	struct stat fstat;
	
	switch (cmd)
	{
		case 'U':
		{
			// 接收文件名
			read(newfd, &FileNameSize, 4);
			read(newfd, (void *)filename, FileNameSize);
			filename[FileNameSize] = '\0';
			
			// 创建文件
			if ((fd = open(filename, O_RDWR | O_CREAT)) == -1)
			{
				perror("creat:");
				_exit(0);
			}
			// 接收文件长度
			read(newfd, &filesize, 4);

			// 接收文件
			while ((count = read(newfd, (void *)buf, 1024)) > 0)
			{
				write(fd, &buf, count);
				totalrecv += count;
				if (totalrecv == filesize)
					break;
			}
			// 关闭文件
			close(fd);
		}
		break;

		case 'D':
		{
			//接收文件名
			read(newfd, &FileNameSize, 4);
			read(newfd, filename, FileNameSize);
			filename[FileNameSize] = '\0';
			
			//打开文件
			if ((fd = open(filename, O_RDONLY)) == -1)
			{
				perror("creat:");
				_exit(0);
			}
			
			//发送文件包括文件长度
			if ((stat(filename, &fstat)) == -1)
				return;
			write(newfd, &fstat.st_size, 4);

			while ((count = read(fd, (void *)buf, 1024)) > 0)
			{
				write(newfd, &buf, count);
			}
			
			close(fd);
		}
		break;
	}
}
int main()
{
	char cmd;
	
	// 创建sockfd
	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket:");
		_exit(0);
	}

	memset(&sockaddr, 0, sizeof(sockaddr));
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = htons(port);
	sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

	// 绑定地址
	if (bind(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) == -1)
	{
		perror("bind:");
		_exit(0);
	}
	
	// 监听
	if (listen(sockfd, 10) == -1)
	{
		perror("listen");
	}

	while (1)
	{
		// 等待连接请求
		if ((newfd = accept(sockfd, (struct sockaddr *)(&client_addr), &sin_size)) == -1)
		{
			perror("accept:");
			_exit(0);
		}
		
		// 处理事件
		while (1)
		{
			read(newfd, &cmd, 1);

			if (cmd == 'Q')
			{
				break;
			}
			else
			{
				handle(cmd);
			}
		}

		close(newfd);
	}

	close(sockfd);
	
	return 0;
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值