win2win(windows之间局域网文件传输)

发布时间 2023-11-22 09:48:10作者: seafly0616

简介

  这是一个基于C语言编写的控制台程序,可以在VS平台下编译。

使用场景

  由于Windows之间自带的文件共享太费事,步骤太繁琐,于是参考网络文章Ctrl+C了一个凑出了一个小工具,主要实现网线直连或者同网段的局域网内的两台Windows电脑之间的文件传输。程序基于TCP协议传输,因此在运行程序之前,确保两台电脑正确配置了IP地址,并且保证IP地址在同一网段即可。出版本单线程,传输中小文件还是够用的,后续有空会更新出多线程并发以提高传输效率。

使用方法

 

完整源代码(win2win.c):下面是完整的源代码(单文件),直接新建一个 Visual Studio C++ 的控制台应用程序工程,然后把内容贴进去编译即可。

#include<stdio.h>
#include<Winsock2.h>
#include<time.h>
#include<string.h>
#include <stdint.h>
#pragma warning(disable:4996)
#pragma comment(lib,"ws2_32.lib")

// Server fixed to be recv people
// Client fixed to be send people

#define USER_ERROR -1
#define MAX_PACKET_SIZE 2048

long getFileSize(const char *FileName)
{
	FILE *fp = fopen(FileName, "rb");
	if (fp == NULL)
		return 0;

	fseek(fp, 0, SEEK_END);
	long fsize = ftell(fp);
	fclose(fp);

	return fsize;
}

void printProcess(double cur, double total)
{
	long percent = cur / total * 100;
	printf("Finished %%%d\r", percent);
	fflush(stdout);
}

long str2num(const char *str)
{
	char *endptr;
	return strtol(str, &endptr, 0);
}

int main_server(uint16_t bindPort)
{
	char recvData[MAX_PACKET_SIZE];
	int ret;
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		printf("Failed to load Winsock.\n");
		return USER_ERROR;
	}

	SOCKET socket_of_server;
	SOCKET socket_of_client;
	socket_of_server = socket(AF_INET, SOCK_STREAM, 0);
	if (socket_of_server == INVALID_SOCKET)
	{
		printf("socket() Failed:%d\n", WSAGetLastError());
		return USER_ERROR;
	}

	struct sockaddr_in s_sin;
	s_sin.sin_family = AF_INET;
	s_sin.sin_port = htons(bindPort);
	s_sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	if (bind(socket_of_server, (LPSOCKADDR)&s_sin, sizeof(s_sin)) == SOCKET_ERROR)
	{
		printf("blind() Failed:%d\n", WSAGetLastError());
		return USER_ERROR;
	}
	if (listen(socket_of_server, 5) == SOCKET_ERROR)
	{
		printf("listen() Failed:%d\n", WSAGetLastError());
		return USER_ERROR;
	}
	struct sockaddr_in c_sin;
	int c_sin_len = sizeof(c_sin);

	int loopflag = 1;
	while (loopflag)
	{
		printf("Waiting for Connection ...\n");
		socket_of_client = accept(socket_of_server, (SOCKADDR *)&c_sin, &c_sin_len);
		if (socket_of_client == INVALID_SOCKET)
			printf("accept() Failed:%d\n", WSAGetLastError());
		else
		{
			printf("Get New Connection IP: %s\r\n", inet_ntoa(c_sin.sin_addr));

			memset(recvData, 0, sizeof(recvData));
			ret = recv(socket_of_client, recvData, sizeof(recvData), 0);
			printf("Get File Name: %s\n", recvData);

			FILE *fp = fopen(recvData, "wb+");
			if (fp == NULL)
			{
				fprintf(stderr, "fopen() %s failed, %s\n", recvData, strerror(errno));
				return -1;
			}

			memset(recvData, 0, sizeof(recvData));
			ret = recv(socket_of_client, recvData, sizeof(recvData), 0);
			long fsize = ntohl(*((long *)recvData));
			printf("Get File Size: %ld\n", fsize);
			printf("Get File Content ...\n");

			long length = 0;
			long curoff = 0;
			long remain = fsize;
			while (1)
			{
				length = recv(socket_of_client, recvData, sizeof(recvData), 0);
				if (length > 0)
				{
					//printf("Get length is %ld\n", length);
					fwrite(recvData, 1, length, fp);
					curoff += length;
					remain -= length;
					printProcess((double)curoff, fsize);
				}

				if (remain <= 0)
				{
					break;
				}
			}

			printf("\nGet File Complete!\n");
			loopflag = 0;
			fclose(fp);
		}
	}

	closesocket(socket_of_server);
	WSACleanup();
	return 0;
}



int main_client(const char *FileName, const char *toIP, uint16_t toPort)
{
	char sendData[MAX_PACKET_SIZE];
	int ret;


	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		printf("WSAStartup() failed.\n");
		return USER_ERROR;
	}

	SOCKET socket_client = socket(AF_INET, SOCK_STREAM, 0);
	if (socket_client == INVALID_SOCKET)
	{
		printf(" Failed socket() \n");
		return 0;
	}

	struct sockaddr_in server_in;
	server_in.sin_family = AF_INET;
	server_in.sin_port = htons(toPort);
	server_in.sin_addr.S_un.S_addr = inet_addr(toIP);

	if (connect(socket_client, (struct sockaddr*)&server_in, sizeof(server_in)) == -1)
	{
		printf(" Failed connect() \n");
		return 0;
	}
	else
	{
		printf("Connecting to IP:%s, Port:%d\n", inet_ntoa(server_in.sin_addr), server_in.sin_port);

		memset(sendData, 0, sizeof(sendData));
		strcpy(sendData, FileName);
		send(socket_client, sendData, sizeof(sendData), 0);
		printf("Put File Name: %s\n", FileName);

		memset(sendData, 0, sizeof(sendData));
		long fsize = getFileSize(FileName);
		*((long *)sendData) = htonl(fsize);
		send(socket_client, sendData, sizeof(sendData), 0);
		printf("Put File Size: %ld\n", fsize);
		printf("Put File Content ...\n");

		if (fsize <= 0)
		{
			goto end_connect;
		}

		Sleep(1000);//1000ms

		FILE *fp = fopen(FileName, "rb");
		if (fp == NULL)
		{
			fprintf(stderr, "fopen() %s failed, %s\n", FileName, strerror(errno));
			exit(1);
		}

		long remain = fsize;
		long length = 0;
		long curoff = 0;
		while (1)
		{
			memset(sendData, 0, sizeof(sendData));
			length = fread(sendData, 1, sizeof(sendData), fp);
			if (length > 0)
			{
				//printf("Put length is %ld\n", length);
				send(socket_client, sendData, sizeof(sendData), 0);
				curoff += length;
				remain -= length;
				printProcess((double)curoff, fsize);
			}
			else
			{
				break;
			}
		}
		printf("\nPut File Complete!\n");
		fclose(fp);
	}

end_connect:
	closesocket(socket_client);
	WSACleanup();
	return 0;
}

void cmd_help(const char *exe)
{
	fprintf(stderr, "Usage: %s  <R|T>  [FileName] [IP] [Port]\n", exe);
	fprintf(stderr, "  e.g: %s   R  6666                        --Rx From Port 6666\n", exe);
	fprintf(stderr, "  e.g: %s   T  hello.txt  127.0.0.1  6666  --Tx To Port 6666\n", exe);
	fprintf(stderr, " Note:\n");
	fprintf(stderr, "       T    --Tx File\n");
	fprintf(stderr, "       R    --Rx File\n");
	fprintf(stderr, "        \n");
	fprintf(stderr, "Author: seafly0616@qq.com\n");
	fprintf(stderr, "Reference link: https://blog.csdn.net/sinat_37372543/article/details/87989599\n");
}

int main(int argc, const char *argv[])
{
	if (argc < 2)
	{
		cmd_help(argv[0]);
		return -1;
	}

	const char *optstr = argv[1];

	switch (*optstr)
	{
	case 'T':
	{
		if (argc != 5)
		{
			cmd_help(argv[0]);
			return -1;
		}
		const char *FileName = argv[2];
		const char *toIP = argv[3];
		uint16_t toPort = str2num(argv[4]);
		main_client(FileName, toIP, toPort);
		break;
	}
	case 'R':
	{
		if (argc != 3)
		{
			cmd_help(argv[0]);
			return -1;
		}
		uint16_t bindPort = str2num(argv[2]);
		main_server(bindPort);
		break;
	}
	default:
	{
		fprintf(stderr, "Error: Invalid option '%c' \n", *optstr);
		cmd_help(argv[0]);
		break;
	}

	}

	return 0;
}
//原文链接:https ://blog.csdn.net/sinat_37372543/article/details/87989599