【C语言实现windows向linux传输文件】

发现以前可能了解的少,就愚蠢至极,其实linux的ftp非常简单
直接sudo apt-get install vsftpd就可以了然后去etc下面去该配置文件就可以了,可能debian的redhat风格的linux的配置文件的路径可能不太一样。
只需要将配置文件里面的#write_enable=YES前面的#号去掉应该就能够上传文件了,还没试过没有去掉#号能不能上传,我都去掉了的
以前愚蠢是因为什么以为只需要再地址栏ftp://ip/地址输入就能到达ftp的路径了。但是这个确实设置了匿名可以这么搞,但是如果没有设置匿名他不会触发账户和密码的弹框的,不像windows本身的ftp配置,输入如果对方有账户和密码会触发弹框。

如果不想装xftp等三方的ftp工具的话可以直接控制台输入ftp
open ip后输入用户名和密码
然后lcd切换本地文件夹
put本地文件里面的内容
在这里插入图片描述

下面是前两年其实也可以实现把windows上的压缩包传到linux服务器上面去,这样也不需要安装ftp服务。今年拿来试了一下还是可以的,虽然我觉得以前愚蠢至极,但是这些功能是真的实现了的,给自己点个赞已经很棒了。

因为某些原因我需要在linux上操作一些东西,但是不知道为什么VMware tools可以进行小文件从windows向ubuntu复制,复制稍大文件电脑直接卡死,不知道什么原因。索性想用ftp ,但是ubuntu下配置的vsftp死活用不了,最后想到了用socke传输文件。
linux端,只能把windows上的zip传向linux

linux上的c代码,再linux上创建一个这个文件比如叫recive_zip.c
gcc recive_zip -o recive_zip
产生的文件后./recive_zip 6666
就开始监听了

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

int removeZero(char* filename){
	FILE* fp = fopen(filename,"rb");
	fseek(fp,-2048,SEEK_END);
	char buf[2048];
	char end[8];
	memset(end,0,8);
	end[0]=80;
	end[1]=75;
	end[2]=5;
	end[3]=6;
	memset(buf,0,2048);
	fread(buf,1,2048,fp);
	
	int i;
	char* tmp = buf;
	for(i=0;i<2048;i++){
		if(*tmp==*end){
			if(0 == memcmp(tmp,end,8)){printf("has find\nthis i is%d\n",i);break;}
		}
		tmp++;
	}	
	fclose(fp);
	struct stat statbuf;
	if(stat(filename,&statbuf)<0){
		perror("stat get file szie failed\n");
		return -1;
	}
	if(truncate(filename,statbuf.st_size-(2048-i-22))<0){
		perror("truncate failed\n");
		return -1;	
	};
	return 0;
}

int main(int argc,char** argv)
{
	if(argc < 2){
		printf("Usage:<%s><port>",argv[0]);
		exit(-1);
	}
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(0 > sockfd)
	{
		perror("socket");
		exit(-1);	
	}
	
	struct sockaddr_in seraddr={
		.sin_family=AF_INET,
		.sin_port=htons(atoi(argv[1])),
		.sin_addr.s_addr=htonl(INADDR_ANY)	
	};
	struct sockaddr_in cli_addr;
	memset(&cli_addr,0,sizeof(cli_addr));

	if(0 > bind(sockfd,(struct sockaddr*)&seraddr,sizeof(seraddr)))
	{
		perror("bind");
		exit(-1);	
	}

	if(0 > listen(sockfd,10))
	{
		perror("listen");	
		exit(-1);
	}

	printf("listen.........\n");
	
	int len = sizeof(struct sockaddr_in);
	int trans_sock = accept(sockfd,(struct sockaddr*)&cli_addr,&len);
	char msg[2048];
	if(trans_sock == -1){
                perror("accept");
        }
        printf("connect come form :%s\n",inet_ntoa(cli_addr.sin_addr));

	memset(msg,0,2048);
	int count = recv(trans_sock,msg,2048,0);
	printf("%d,%s\n",count,msg);
	char filename[128];
	strcpy(filename,msg);
	FILE* fp = fopen(msg,"wb+");
	while(1){
		memset(msg,0,2048);
		count = recv(trans_sock,msg,2048,0);
		if(count == 0){
			if(errno != EINTR){
				printf("connection disconnected\n");
				removeZero(filename);
				close(trans_sock);
				close(sockfd);
				fclose(fp);
				return 0;
			}
		}
		printf("recv %d bytes\n",count);
		fwrite(msg,count,1,fp);	
	}
	close(trans_sock);
	close(sockfd);
	fclose(fp);

	return 0;
}

windows端在devc++ panda 6.7.5上运行成功
为什么devc++经久不衰,你看哈vs现在的版本下载都是几个G,devc++都没多大,轻量级都占用不了啥资源
一下可以创建个文件send_zip.c
编译后直接在cmd 里面输入send_zip.exe 对端linux的ip 6666 文件路径名
devc++可以去百度下载
我把send_zip.exe和recive_zip上传到我的资源里面去
以前还愚蠢只知道ifconfig能够看ip
后来才知道ip addr也能看,有些不会预装ifconfig 但是ip工具是会预装的
需要在工具-编译选项-在链接时加入以下参数-static-libgcc -lws2_32

#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char** argv) {
	if (argc < 4) {
		printf("Usage<%s> <ip> <port> <filename>", argv[0]);
		exit(-1);
	}
	WSADATA wsd;

	if ((WSAStartup(MAKEWORD(2, 2), &wsd)) != 0) {
		printf( "wsastartup()failed: \n");
		exit(1);
	}

	SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock == INVALID_SOCKET) {
		printf("socket error\n");
		exit(-1);
	}

	struct sockaddr_in addr;
	
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr(argv[1]);
	addr.sin_port = htons(atoi(argv[2]));

	if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
		printf("connect error\n");
		return -1;
	}
	
	char buf[2048];
	FILE* fp = fopen(argv[3], "rb");

	if (fp == NULL) {
		printf("open %s failed,if this file exist?\n", argv[3]); 
		exit(-1);
	}
	int count = 0;
	strcpy(buf,argv[3]);
	count = send(sock,buf, 2048,0);
	printf("witre %d bytes\n", count);

	while(!feof(fp)){
		memset(buf,0,2048);
		count = fread(buf,1,2048,fp);
		printf("read %d bytes\n",count);
		send(sock,buf,2048,0);
	}
	closesocket(sock);
		printf("%s\n",argv[3]);

	WSACleanup();


	return 0;
}

send和recv并不是发多少 收到多少 在调试的时候windows上读到的2048个字节到linux上打印却有小于2048的。这个可能是因为二进制发送和tcp分片的原因吧,也不想再用wireshark抓包验证了。应该是linux上用2048的buf一次没取完,然后第二次就recv就小于2048了
用了16进制编辑器linux上的ghex观察所有zip的编码都是 50 4B 05 06 00 00 00 00 + 14个字符 一共22个字符;
这里还有两个linux下缩小文件大小的方法,stat 和truncate方法;fseek fwrite都没有办法改变文件大小。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值