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

来源:互联网 发布:腾讯云数据库重启 编辑:程序博客网 时间:2024/06/03 21:12

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

直接上代码,使用的是简单的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则使用UDPsockaddr_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,释放winsockclosesocket(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);//客户端socketSOCKET 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,所以客户端即使已经接收完成,亦不会输出接收完成的信息,只有关闭服务器的时候才会输出...

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


0 0