windows环境下C++多线程文件传输

把上午写的传输字符串代码改了一下,本来是想实现客户端和服务器一对一多线程分块传输的,结果发现好像变成了一个服务器对多个客户端,每个客户端分配一条线程来处理文件传输任务的模式...

直接上代码,使用的是简单的fstream操作。
Sever代码:

#include "stdafx.h"
#include <WinSock2.h> //windows socket的头文件
#include <Windows.h>
#include <iostream>
#include <thread>
#include <mutex>
#include <process.h>
#include <fstream>
#include <string>

#pragma comment(lib, "ws2_32.lib") //连接winsock2.h的静态库文件

using namespace std;

mutex m;

//定义结构体用来设置
typedef struct my_file
{
	SOCKET clientSocket; //文件内部包含了一个SOCKET 用于和客户端进行通信
	sockaddr_in clientAddr; //用于保存客户端的socket地址
	int id; //文件块的序号
}F;

DWORD WINAPI transmmit(const LPVOID arg)
{
	//实际上这里也可以不加锁,上锁是为了方便看输出
	m.lock();

	F *temp = (F*)arg;
	//获取文件的序号
	//int file_id = temp->id;
	//获取客户机的端口号
	//ntohs(temp -> clientAddr.sin_port); 
	cout << "测试开始,等待客户端发送消息..." << endl;
	//从客户端处接受数据
	/*
	char Buffer[MAXBYTE] = { 0 }; //缓冲区
	recv(temp->clientSocket, Buffer, MAXBYTE, 0); //recv方法 从客户端通过clientScocket接收
	cout << "线程" << temp->id << "从客户端的" << ntohs(temp->clientAddr.sin_port) << "号端口收到:" << Buffer << endl;
	*/
	char file_name[100] = { 0 }; //文件路径
	cout << "输入传输文件路径: ";
	cin >> file_name;
	FILE *fp = fopen(file_name, "rb"); //将文件按二进制读取
	if (fp == NULL)
	{
		cout << "文件" << file_name << "出错或不存在" << endl;
	}
	else
	{
		char Buffer[MAXBYTE] = { 0 }; //文件缓冲区
		int size = 0; //读取的文件长度
		//每次读取完之后清空缓存区,以便下一块文件读入
		while ((size = fread(Buffer, sizeof(char), MAXBYTE, fp)) > 0) 
		{
			//返回非0值表示send错误
			if (send(temp->clientSocket, Buffer, size, NULL) < 0)
			{
				cout << "传输出错,请检查网络配置。" << endl;
			}
			memset(&Buffer, 0, MAXBYTE);
		}
		cout << temp->id << "线程已成功发送" << file_name << endl;
		fclose(fp);
	}


	/*
	//发送简单的字符串到客户端
	const char* s = "Server file";
	send(temp->clientSocket, s, strlen(s)*sizeof(char)+1, NULL);
	cout << "线程" << temp->id << "通过客户端的" << ntohs(temp->clientAddr.sin_port) << "号端口发送:" << s << endl;
	*/

	m.unlock();

	return 0;
}



int main()
{
	WSADATA wsaData;
	//第一个参数是winsocket load的版本号(2.2)
	WSAStartup(MAKEWORD(2, 3), &wsaData);
	//创建服务器端的socket(协议族, sokcet类型)
	SOCKET servSocket = socket(AF_INET, SOCK_STREAM, 0);//如果改成SOCK_DGRAM则使用UDP
	sockaddr_in servAddr; //服务器的socket地址,包含sin_addr表示IP地址,sin_port保持端口号和sin_zero填充字节
	memset(&servAddr, 0, sizeof(SOCKADDR)); //初始化socket地址
	servAddr.sin_family = PF_INET; //设置使用的协议族
	servAddr.sin_port = htons(2017); //设置使用的端口
	servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //define s_addr = S_un.S_addr
	::bind(servSocket, (SOCKADDR *)&servAddr, sizeof(SOCKADDR)); //将之前创建的servSocket和端口,IP地址绑定

	HANDLE hThread[2]; //获取句柄
	listen(servSocket, 1); //监听服务器端口
	for (int i = 0; i < 1; i++)
	{
		F *temp = new F; //创建新的传输结构体
		sockaddr_in clntAddr;
		int nSize = sizeof(SOCKADDR);
		SOCKET clientSock = accept(servSocket, (SOCKADDR*)&clntAddr, &nSize);
		//temp数据成员赋值
		temp->clientSocket = clientSock;
		temp->id = i + 1;
		temp->clientAddr = clntAddr;
		//通过句柄创建子线程
		hThread[i] = CreateThread(NULL, 0, &transmmit, temp, 0, NULL);
	}
	//等待子线程完成
	WaitForMultipleObjects(1, hThread, TRUE, INFINITE);
	cout << "错误代码: " << WSAGetLastError() << endl;

	//关闭socket,释放winsock
	closesocket(servSocket);
	WSACleanup();

	cout << "服务器连接已关闭。" << endl;
	system("pause");

	return 0;
}


Client端代码:

#include "stdafx.h"
#include <WinSock2.h> //windows socket的头文件
#include <Windows.h>
#include <iostream>
#include <thread>
#include <process.h>

#pragma comment(lib, "ws2_32.lib") //连接winsock2.h的静态库文件

using namespace std;

int main()
{
	//加载winsock库
	WSADATA wsadata;
	WSAStartup(MAKEWORD(2, 3), &wsadata);

	//客户端socket
	SOCKET clientSock = socket(PF_INET, SOCK_STREAM, 0);
	//初始化socket信息
	sockaddr_in clientAddr;
	memset(&clientAddr, 0, sizeof(SOCKADDR));
	//clientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	clientAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	clientAddr.sin_family = PF_INET;
	clientAddr.sin_port = htons(2017);
	//建立连接
	connect(clientSock, (SOCKADDR*)&clientAddr, sizeof(SOCKADDR));

	cout << "已建立连接。" << endl;

	/*
	char* s = new char[100];
	cout << "请输入你要发送的文字消息: ";
	cin >> s;
	send(clientSock, s, strlen(s)*sizeof(char) + 1, NULL);
	cout << "已发送:" << s << endl;
	*/

	char Buffer[MAXBYTE] = { 0 }; // 文件缓冲区
	char wb_file[100] = { 0 }; //写入的文件

	cout << "请输入想要写入的文件: ";
	cin >> wb_file;

	FILE *fp = fopen(wb_file, "wb");
	if (fp == NULL)
	{
		cout << "操作文件时出错" << endl;
		system("pause");
	}
	else
	{
		memset(&Buffer, 0, MAXBYTE);
		int size = 0;
		//当成功接收文件(size > 0)时,判断写入的时候文件长度是否等于接收的长度
		while ((size = recv(clientSock, Buffer, MAXBYTE, 0)) > 0)
		{
			if (fwrite(Buffer, sizeof(char), size, fp) < size)
			{
				cout << "写入出错,部分文件缺失。" << endl;
			}
			//清空缓存区以便下一次接收
			memset(&Buffer, 0, MAXBYTE);
		}
		cout << "接收完成" << endl;
		fclose(fp);
	}
	
	closesocket(clientSock);
	WSACleanup();

	cout << "客户端连接已关闭。" << endl;
	system("pause");

	return 0;
}


因为之前用了WaitForMultipleObjects,所以客户端即使已经接收完成,亦不会输出接收完成的信息,只有关闭服务器的时候才会输出...

接下来思考一下怎么实现大文件分块传输的问题吧_(:з)∠)_


  • 4
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 在 Windows 下使用 C 语言写一个远程管理程序,你可以使用一些网络编程库,例如 Winsock。 首先,你需要在代码中包含 Winsock 库,然后使用 `WSAStartup` 函数初始化 Winsock。 ```c #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") int main(int argc, char* argv[]) { WSADATA wsa; if (WSAStartup(MAKEWORD(2,2), &wsa) != 0) { printf("WSAStartup failed: %d\n", WSAGetLastError()); return 1; } // ... return 0; } ``` 然后,你需要创建一个 socket,并使用 `bind` 函数将其绑定到一个本地地址和端口上。接下来,使用 `listen` 函数将 socket 设置为侦听状态,然后使用 `accept` 函数来接受客户端的连接。 ```c int main(int argc, char* argv[]) { // ... SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_socket == INVALID_SOCKET) { printf("socket failed: %d\n", WSAGetLastError()); return 1; } SOCKADDR_IN addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(8888); if (bind(listen_socket, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) { printf("bind failed: %d\n", WSAGetLastError()); return 1; } if (listen(listen_socket, SOMAXCONN) == SOCKET_ERROR) { printf("listen failed: %d\n", WSAGetLastError()); return 1; } SOCKET client_socket = accept(listen_socket, NULL, NULL); if (client_socket == INVALID_SOCKET) { printf("accept failed: %d\n", WSAGetLastError()); return 1; } // ... return 0; } ### 回答2: 在Windows下编写一个远程管理程序,可以使用C语言和相应的库来实现。主要步骤如下: 1. 使用Winsock库来建立网络连接。可以通过创建一个套接字(Socket)来进行通信,其中包括服务器端和客户端。 2. 服务器端需要创建一个Socket并绑定到特定的IP地址和端口号。然后使用listen函数来监听客户端的连接请求。 3. 客户端需要先创建一个Socket并使用connect函数来连接到服务器端的IP地址和端口号。 4. 服务器端需要使用accept函数来接受客户端的连接请求,并返回一个新的Socket来进行后续的通信。 5. 可以使用send和recv函数来通过Socket发送和接收数据。远程管理程序可以定义相关命令和消息格式,通过发送不同的指令来实现远程操作。 6. 在服务器端,可以使用多线程或者多进程来处理多个客户端的连接。这样可以实现同时处理多个远程操作请求。 7. 在通信过程中需要注意数据的加密和解密,以保证通信的安全性。 8. 可以定义一些管理命令,如远程文件传输、远程进程管理、远程命令执行等功能。 9. 可以通过界面设计来使远程管理程序更加友好和易用。 需要注意的是,远程管理程序的具体实现可能会因需求的不同而有所差异,可以根据实际情况进行适当的调整和改进。这只是一个基本框架,具体的功能实现需要根据实际需求进行设计和开发。 ### 回答3: 在Windows下运行的远程管理程序可以使用C语言编写。首先,可以使用C语言的网络编程功能来实现程序与远程主机之间的通信。可以使用Socket API来建立与远程主机的连接,使用TCP协议进行数据传输。 程序可以实现以下功能: 1. 远程登录:用户可以输入远程主机的IP地址和端口号,程序会建立与远程主机的连接,然后发送用户认证信息以登录到远程主机的系统。 2. 文件传输:用户可以选择文件,程序将文件分割成较小的数据包,并通过网络传输到远程主机。在远程主机上,程序将接收数据包并重新组装成完整的文件。 3. 远程命令执行:用户可以输入命令,在程序中将命令发送到远程主机上执行,并将执行结果返回给用户。 4. 远程进程管理:程序可以向远程主机发送指令,获取当前正在运行的进程列表,并提供关闭、结束进程等操作。 5. 远程桌面控制:程序可以通过传输屏幕截图数据,实现远程主机的桌面显示,并通过用户控制来实现远程桌面操作。 编写这种远程管理程序需要深入理解网络编程的原理和知识,以及了解Windows操作系统的相关API。需要使用C语言实现网络连接、数据传输、进程管理等功能。另外,还需要考虑网络安全性和稳定性等方面的问题,以及进行错误处理和异常处理等。 总之,使用C语言可以编写一个在Windows下运行的远程管理程序,实现远程登录、文件传输、命令执行、进程管理和远程桌面控制等功能,为用户提供方便快捷的远程管理操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值