使用:
(1)首先运行服务端,待服务端运行起来;
(2)最后运行客户端,输入要传输文件到哪个目标机器的IP地址;
(3)输入传输文件的路径及文件(完成的路径),其中包含文件的类型,也就是后缀需要包含(代表需要传输文件的类型)。
例如:E:/Data(D)/Cat_and_Dog/dog.jpg
参考博主:https://blog.csdn.net/sinat_23118323/article/details/71024351
客户端:

#pragma once
#ifndef _TCPSOCKET_H_
#define _TCPSOCKET_H_
#include <WinSock2.h> //windows socket的头文件
#include <Windows.h>
#include <iostream>
#include <thread>
#include <process.h>
#include<mutex>
#include<string>
#include<process.h>
#define err(errMsg) printf("[error] %s failed,code %d\
line:%d\n",errMsg, WSAGetLastError(),__LINE__)
#pragma comment(lib, "ws2_32.lib") //连接winsock2.h的静态库文件using namespace std;
class Socket {private:SOCKET clientSock;int id;string ip;char wb_file[MAXBYTE];
public://获取ClientSockSOCKET Getcientsock();//获取当前日期void OBTION_TIME();//获取开始时间double START_TIME();//获取结束时间double END_TIME();//获取文件大小void  getByteSize(unsigned long long size);//返回以MB为单位的文件大小unsigned long long RETURN_MB(unsigned long long size);//判断输入IP是否存在bool TARGE_FILE(string ip);//输入文件void SEND_FILE(string file);//LPVOID是一个没有类型的指针,也就是说你可以将任意类型的指针赋值给LPVOID类型的变量(一般作为参数传递)static DWORD WINAPI transmmit(const LPVOID arg);bool INPUT_IP(string ipt);//系统的实现以上函数int MAIN_SOCKET();//清理和关闭网络库void CLEAR();
};
//定义结构体用来设置
typedef struct my_file
{SOCKET clientSocket; //文件内部包含了一个SOCKET 用于和客户端进行通信sockaddr_in clientAddr; //用于保存客户端的socket地址int id; //文件块的序号
}F;
#endif // !_TCPSOCKET_H_

#include "tcpSocket.h"
#define MAXBYTES 300*1024
//表示一秒钟会有多少个时钟计时单元
#define CLOCKS_PER_SEC ((clock_t)1000)
mutex m;
//获取当前日期
void Socket::OBTION_TIME() {SYSTEMTIME start; //windows.h中  GetLocalTime(&start);//time.h的tm结构体一样的效果  cout << start.wYear << "/" << start.wMonth << "/" << start.wDay << " " << start.wHour << ":" << start.wMinute << ":" << start.wSecond << endl;
}
// 获取开始时间
double Socket::START_TIME() {DWORD start_time;start_time = GetTickCount64();return (double)start_time;
}
//获取结束时间
double Socket::END_TIME() {DWORD end_time;end_time = GetTickCount64();return double(end_time);
}
SOCKET Socket::Getcientsock() {return clientSock;
}
//获取文件大小
void Socket::getByteSize(unsigned long long size) {unsigned long long rest = 0;if (size < 1024) {cout << size << "B" << endl;return;}else {size /= 1024;}if (size < 1024) {cout << size << "KB" << endl;return;}else {rest = size % 1024;size /= 1024;}if (size < 1024) {size *= 100;cout << (size / 100) << "." << (rest * 100 / 1024 % 100) << "MB" << endl;return;}else {size = size * 100 / 1024;cout << (size / 100) << "." << (size % 100) << "GB" << endl;return;}
}void Socket::SEND_FILE(string file) {int i = 0;char Temporary_file[MAXBYTE] = { 0 };//保存发送文件的格式for (i = 0; i <  file.length(); i++) {wb_file[i] = file[i];Temporary_file[i] = file[i];}wb_file[i] = '\0';Temporary_file[i] = '\0';send(clientSock, Temporary_file, strlen(Temporary_file), 0);
}
//LPVOID是一个没有类型的指针,也就是说你可以将任意类型的指针赋值给LPVOID类型的变量(一般作为参数传递)
DWORD WINAPI Socket::transmmit(const LPVOID arg){//上锁是为了方便看输出m.lock();//F* temp = (F*)arg;Socket* so = (Socket*)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; //文件路径char File_Alias[100] = { 0 };file_name = so->wb_file;unsigned long long len_file = 0;FILE* fp = fopen(file_name, "rb");if (fp == NULL) {cout << "文件" << file_name << "出错或不存在" << endl;}else {//获取文件大小unsigned long long g_fileSize ;//注意这个地方不能使用unsigned long long,因为当文件传输很大的时候,ftell返回的是long//fseek(fp, 0, SEEK_END);//将读取的文件指针放到文件末尾//g_fileSize = ftell(fp);//fseek(fp, 0, SEEK_SET);//指针移到文件开头struct _stat64 st;_stat64(file_name, &st);g_fileSize = st.st_size;string send_file_len;send_file_len = to_string(g_fileSize);send(so->clientSock, send_file_len.c_str(), send_file_len.length(), 0);cout << "发送文件时间: ";so->OBTION_TIME();double start_time = so->START_TIME();char Buffer[MAXBYTES] = { 0 }; //文件缓冲区unsigned long long  size = 0; //读取的文件长度unsigned long long Actual_file_len = 0;//为了确保长度更精确while ((size = fread(Buffer, sizeof(char), MAXBYTES, fp)) > 0) {//返回非0值表示send错误if (send(so->clientSock, Buffer, (unsigned long long)size, NULL) < 0){cout << "传输出错,请检查网络配置。" << endl;break;}len_file += size;cout.width(3);//i的输出为3位宽if ((len_file*100/ g_fileSize)%5>0) {cout << (len_file * 100 / g_fileSize) << "%";cout << "\b\b\b\b";//回删三个字符,使数字在原地变化}size = 0;//每次读取完之后清空缓存区,以便下一块文件读入memset(&Buffer, 0, MAXBYTES);}const char* t = "end";send(so->clientSock, t, strlen(t), NULL);cout << so->id << "线程已成功发送" << file_name << endl;cout << "发送文件大小: ";so->getByteSize(len_file);cout << "文件发送结束时间: ";so->OBTION_TIME();double end_time = so->END_TIME();double currentTime = 0;currentTime = (double)(end_time-start_time)/ CLOCKS_PER_SEC;cout << "发送文件耗时: " << currentTime <<"s"<< 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;
}
bool Socket::INPUT_IP(string ipt) {//客户端socket//加载winsock库WSADATA wsadata;//WSA-windows socket ansyc windows的异步套接字 2.2版本的if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) {err("WSAStartup");return 0;}clientSock = socket(AF_INET, SOCK_STREAM, 0);if (clientSock == INVALID_SOCKET) {err("SOCKET");return 0;}//初始化socket信息sockaddr_in clientAddr;memset(&clientAddr, 0, sizeof(SOCKADDR));//clientAddr.sin_addr.s_addr = htonl(INADDR_ANY);const char* ips = ipt.c_str();clientAddr.sin_family = AF_INET;clientAddr.sin_port = htons(3725);//将本地字节序转换为网络字节序,大端和小端存储clientAddr.sin_addr.s_addr = inet_addr(ips);if (connect(clientSock, (SOCKADDR*)&clientAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) {err("connect");return false;}return true;
}
//接收和传输文件目录
bool Socket::TARGE_FILE(string ip) {bool flag = INPUT_IP(ip);if (flag == true)return 1;else {return 0;}
}
int Socket::MAIN_SOCKET(){//建立连接//while (true) {cout << "已建立连接。" << endl;char Buffer[MAXBYTE] = { 0 }; // 文件缓冲区char wb_file[100] = { 0 }; //写入的文件//“句柄” 类似指针, 但通过指针可读写对象, 通过句柄只是使用对象;HANDLE hThread[2];for (int i = 0; i < 1; i++) {sockaddr_in clntAddr;memset(&clntAddr, 0, sizeof(SOCKADDR));//使用 API 的 CreateThread, 它执行完入口函数后会自动退出, 无需 ExitThread;hThread[i] = CreateThread(NULL, 0,&transmmit, this, 0, NULL);}//等待子线程完成WaitForMultipleObjects(1, hThread, TRUE, INFINITE);cout << "错误代码: " << WSAGetLastError() << endl;//}return 0;
}
void Socket::CLEAR() {closesocket(clientSock);关闭网络库 if (WSACleanup() != 0) {err("WSACleanup");return ;}cout << "客户端连接已关闭。" << endl;system("pause");}

#include"tcpSocket.h"
int main() {Socket* soc = new Socket();char Tempoary[1024] = { 0 };while (true) {string ip;cout << "请输入目标机器的IP:";cin >> ip;bool flag=soc->TARGE_FILE(ip);if (flag == true)break;else {cout << "IP地址错误或者目标主机不存在" << endl;continue;}}while (true) {cout << "其次请客户端输入传输文件路径: ";string file;cin >> file;soc->SEND_FILE(file);int ret = recv(soc->Getcientsock(), Tempoary, 10, 0);if (ret < 0)continue;soc->MAIN_SOCKET();}soc->CLEAR();return 0;
}

服务端:


#pragma once
#ifndef _TCPSERVER_H_
#define _TCPSERVER_H_
#include <WinSock2.h> //windows socket的头文件
#include <Windows.h>
#include <iostream>
#include <thread>
#include <mutex>
#include <process.h>
#include <fstream>
#include <string>
#include<time.h>#define err(errMsg) printf("[error] %s failed,code %d\
line:%d\n",errMsg, WSAGetLastError(),__LINE__)#pragma comment(lib, "ws2_32.lib") //连接winsock2.h的静态库文件using namespace std;
class Server {private:SOCKET clientSock;SOCKET servSocket;int id;char  wb_file[MAXBYTE];//写入文件路径char filename[MAXBYTE];public://获取clientSockSOCKET GetclientSock();//获取当前日期void OBTION_TIME();//获取开始时间double START_TIME();//获取结束时间double END_TIME();//获取文件大小void  getByteSize(unsigned long long size);//返回以MB为单位的文件大小unsigned long long RETURN_MB(unsigned long long size);//绑定和监听void TARGE_FILE();//返回文件的类型string TYPE_file();//LPVOID是一个没有类型的指针,也就是说你可以将任意类型的指针赋值给LPVOID类型的变量(一般作为参数传递)static DWORD WINAPI transmmit(const LPVOID arg);//系统的实现以上函数int MAIN_Server();//接收文件void REVER_file(string file,string fileanme);//清理网络库和关闭void CLEAR();};
//定义结构体用来设置
typedef struct my_file {SOCKET clientSocket; //文件内部包含了一个SOCKET 用于和客户端进行通信sockaddr_in clientAddr; //用于保存客户端的socket地址int id; //文件块的序号
}F;#endif // !_TCPSERVER_H_

#include "tcpServer.h"
#define MAXBYTES 300*1024
mutex m;
//获取当前日期
void Server::OBTION_TIME() {SYSTEMTIME start; //windows.h中  GetLocalTime(&start);//time.h的tm结构体一样的效果  cout << start.wYear << "/" << start.wMonth << "/" << start.wDay << " " << start.wHour << ":" << start.wMinute << ":" << start.wSecond << endl;
}
//获取开始时间
double Server::START_TIME() {DWORD start_time;start_time = GetTickCount64();return (double)start_time;
}
//获取结束时间
double Server::END_TIME() {DWORD end_time;end_time = GetTickCount64();return double(end_time);
}
//获取文件大小
void  Server::getByteSize(unsigned long long size) {unsigned long long rest = 0;if (size < 1024) {cout << size << "B" << endl;return;}else {size /= 1024;}if (size < 1024) {cout << size << "KB" << endl;return;}else {rest = size % 1024;size /= 1024;}if (size < 1024) {size *= 100;cout << (size / 100) << "." << (rest * 100 / 1024 % 100) << "MB" << endl;return;}else {size = size * 100 / 1024;cout << (size / 100) << "." << (size % 100) << "GB" << endl;return;}
}
string Server::TYPE_file() {string end_file = "";char Temporary[1024] = { 0 };char file[1024] = { 0 };int index_last = 0;int ret = recv(GetclientSock(), file, 100, 0);for (int i = strlen(file) - 1; i >= 0; i--) {if (file[i] == '\\') {index_last = i;break;}}index_last++;if (ret > 0) {file[ret] = '\0';for (int i = index_last; i < strlen(file); i++) {end_file += file[i];}}return end_file;
}
void Server::TARGE_FILE() {//加载网络库WSADATA wsaData;//第一个参数是winsocket load的版本号(2.2)if (WSAStartup(MAKEWORD(2, 3), &wsaData) != 0) {err("WSAStartup");return ;}//创建服务器端的socket(协议族, sokcet类型)servSocket = socket(AF_INET, SOCK_STREAM, 0);//如果改成SOCK_DGRAM则使用UDPif (servSocket == INVALID_SOCKET) {err("SOCKET");return ;}sockaddr_in servAddr; //服务器的socket地址,包含sin_addr表示IP地址,sin_port保持端口号和sin_zero填充字节memset(&servAddr, 0, sizeof(SOCKADDR)); //初始化socket地址servAddr.sin_family = AF_INET; //设置使用的协议族servAddr.sin_port = htons(3725); //设置使用的端口servAddr.sin_addr.s_addr = INADDR_ANY; //define s_addr = S_un.S_addr//将之前创建的servSocket和端口,IP地址绑定if (bind(servSocket, (SOCKADDR*)&servAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) {err("bind");return ;}listen(servSocket, 1); //监听服务器端口sockaddr_in clntAddr;int nSize = sizeof(clntAddr);cout << "等待连接..." << endl;clientSock = accept(servSocket, (SOCKADDR*)&clntAddr, &nSize);if (clientSock == INVALID_SOCKET) {err("accept");}cout << "连接成功" << endl;
}
void Server::REVER_file(string file,string filename) {int i = 0;int len_file = file.length();int len_filename = filename.length();for (i = 0; i < len_file; i++) {wb_file[i] = file[i];}int j = 0;for (i = len_file; i < (len_file + len_filename)&&j<len_filename;j++, i++) {wb_file[i] = filename[j];}wb_file[i] = '\0';
}
SOCKET Server::GetclientSock() {return clientSock;
}
int Server::MAIN_Server() {char Buffer[MAXBYTES] = { 0 }; // 文件缓冲区char wb_files[MAXBYTE] = { 0 };FILE* fp = fopen(wb_file, "wb");//如果录入文件不存在的话就创建一个新的文件if (fp == NULL) {fp = fopen(wb_file, "w");}unsigned long long len_file = 0;if (fp == NULL) {cout << "操作文件时出错" << endl;system("pause");}else {cout << "接收文件时间: ";OBTION_TIME();unsigned long long g_fileSize = 0;char rev_buffer[MAXBYTES] = { 0 };//接收文件的长度int rev_len = recv(clientSock, rev_buffer, MAXBYTE, 0);if (rev_len > 0) {rev_buffer[rev_len] = '\0';for (int i = 0; i < strlen(rev_buffer); i++) {g_fileSize = g_fileSize * 10 + ((unsigned long long)rev_buffer[i] - 48);}}double start_time = START_TIME();memset(&Buffer, 0, MAXBYTES);unsigned long long  size = 0;//当成功接收文件(size > 0)时,判断写入的时候文件长度是否等于接收的长度while ((size = recv(clientSock, Buffer, MAXBYTES, 0)) > 0) {if (Buffer[size - 3] == 'e' && Buffer[size - 2] == 'n' && Buffer[size - 1] == 'd'){char buffer[MAXBYTES] = { 0 };for (int i = 0; i < strlen(Buffer) - 3; i++) {buffer[i] = Buffer[i];}len_file += size - 3;size -= 3;if (fwrite(buffer, sizeof(char), size, fp) < size) {cout << "写入出错,部分文件缺失。" << endl;break;}cout.width(3);//i的输出为3位宽if ((len_file * 100 / g_fileSize) % 5 > 0) {cout << (len_file * 100 / g_fileSize) << "%";cout << "\b\b\b\b";//回删三个字符,使数字在原地变化}break;}else {if (fwrite(Buffer, sizeof(char), size, fp) < size) {cout << "写入出错,部分文件缺失。" << endl;}len_file += size;}cout.width(3);//i的输出为3位宽if ((len_file * 100 / g_fileSize) % 5 > 0) {cout << (len_file * 100 / g_fileSize) << "%";cout << "\b\b\b\b";//回删三个字符,使数字在原地变化}//清空缓存区以便下一次接收memset(&Buffer, 0, MAXBYTE);}cout << "接收完成" << endl;cout << "接受文件大小: ";len_file = (unsigned long long)len_file;getByteSize(len_file);cout << "文件结束接受时间: ";OBTION_TIME();double end_time = END_TIME();double currentTime = 0;currentTime = (double)(end_time - start_time) / CLOCKS_PER_SEC;cout << "接收文件耗时: " << currentTime <<"s"<< endl;fclose(fp);}return 0;}
void Server::CLEAR() {//关闭socket,释放winsockclosesocket(servSocket);////关闭网络库 if (WSACleanup()) {err("WSACleanup");return ;}cout << "服务器连接已关闭。" << endl;system("pause");
}

#include "tcpServer.h"
int main() {Server* ser = new Server();ser->TARGE_FILE();string wb_file;while (true) {cout << "首先请服务端输入想要写入的文件(不用输入文件名): ";cin >> wb_file;string st = "ESC";string end_file = ser->TYPE_file();send(ser->GetclientSock(), st.c_str(),st.length(), 0);ser->REVER_file(wb_file,end_file);ser->MAIN_Server();}ser->CLEAR();return 0;
}

使用C++实现Socket编程传输文件相关推荐

  1. Python爱好者 socket模块传输文件 -

    Python爱好者 socket模块传输文件 - Python爱好者 socket模块传输文件 - socket模块传输文件 热度 1已有 32 次阅读2012-10-31 14:14 |个人分类:p ...

  2. java socket 传多个文件下载,Socket编程多文件传输

    有子曰:"其为人也孝弟,而好犯上者,鲜矣:不好犯上,而好作乱者,未之有也.君子务本,本立而道生.孝弟也者,其为仁之本与!" 项目介绍:基于TCP协议实现多文件传输 将F盘test文 ...

  3. 使用C++实现Socket编程传输协议文件(包括大文件)

    使用: (1)首先运行服务端,待服务端运行起来: (2)最后运行客户端,输入要传输文件到哪个目标机器的IP地址: (3)输入传输文件的路径及文件(完成的路径),其中包含文件的类型,也就是后缀需要包含( ...

  4. 【Java】TCP Socket编程案例——文件传输聊天工具

    TCP(传输控制协议)是面向连接的可靠数据传输协议.TCP连接一旦建立起来,一直占用,直到关闭连接.另外,TCP为了保证数据的正确性,会重发一切没有收到的数据,还会对数据内容进行验证,并保证数据传输的 ...

  5. socket编程实现文件传输功能

    这节我们来完成 socket 文件传输程序,这是一个非常实用的例子.要实现的功能为:client 从 server 下载一个文件并保存到本地. 编写这个程序需要注意两个问题: 1) 文件大小不确定,有 ...

  6. 【Java】UDP Socket编程案例——文件传输聊天工具

    UDP(用户数据报协议)就像日常生活中的邮件投递,是不能保证可靠地寄到目的地.UDP是无连接的,对系统资源的要求较少,UDP可能丢包,也不保证数据顺序.但是对于网络游戏和在线视频等要求传输快,实时性高 ...

  7. socket编程二十二:socket编程实现文件传输功能

    这节我们来完成 socket 文件传输程序,这是一个非常实用的例子.要实现的功能为:client 从 server 下载一个文件并保存到本地. 编写这个程序需要注意两个问题: 1) 文件大小不确定,有 ...

  8. 例程:socket编程实现文件传输功能

    程序要实现的功能:client 从 server 下载一个文件并保存到本地. 编写这个程序需要注意两个问题: (1)文件大小不确定 有可能比缓冲区大很多,调用一次 write()/send() 函数不 ...

  9. socket 编程实现文件传输功能!强无敌,网络通讯的必备知识储备!

    socket 文件传输程序,这是一个非常实用的例子. 要实现的功能为:client 从 server 下载一个文件并保存到本地. 编写这个程序需要注意两个问题: ======== 1) 文件大小不确定 ...

最新文章

  1. PHP利用CURL_MULTI实现多线程
  2. 洛谷 1351 联合权值
  3. C#】通过遍历IFrame访问页面元素
  4. 9个不为人知的Python技巧
  5. 用putty中的pscp命令拷贝文件
  6. mysql y_关于MySQL中Y和~问题
  7. 精英赛上线|冠军万元奖金
  8. 晨风机器人对接php_php封装实现钉钉机器人报警接口的示例代码
  9. winpe+linux iso,用syslinux引导maxdos,winpe,slax l
  10. Android将库导入到build.gradle
  11. PCA主成分分析python实现
  12. mysql 定时备份脚本
  13. SHP格式数据点线面无边界坐标生成经纬度边界点集合数据
  14. linux文件怎么打包压缩文件,linux文件怎么打包、压缩和解压?详细教程来了!...
  15. EM算法·最大期望算法
  16. 计算机屏幕闪烁黑屏,台式机电脑。显示屏指示灯一直闪烁,屏幕黑屏。。...-显示器电源灯闪黑屏...
  17. 不求星光灿烂,但愿岁月静好
  18. moviepy音视频剪辑:颜色相关变换函数blackwhite、colorx、fadein/out、gamma_corr、invert_colors、lum_contrast、mask_color介绍
  19. ViewModel 和 ViewModelProvider.Factory:ViewModel 的创建者
  20. java怎么通过坐标定位控件_[已解决] 可以定位到控件, 但每次执行 click () 方法会报空指针错误 java.lang.NullPointerException...

热门文章

  1. 操作系统学习:Linux0.12初始化详细流程-首个子进程
  2. Django博客系统(短信验证码)
  3. html 标签、图像、链接、注释、锚点定位、特殊字符
  4. 网络工程师_记录的一些真题_2016上半年上午
  5. 工业视觉检测发展的现状
  6. 可微分的「OpenCV」:这是基于PyTorch的可微计算机视觉库
  7. 基于计算机视觉的构件表面缺陷特征提取
  8. 基于机器视觉的缺陷检测的原理与方法
  9. MongoDB中mapReduce的使用
  10. 06 回归算法 - 损失函数、过拟合欠拟合