文件传输_文件传输协议 - CSDN
精华内容
参与话题
  • Socket实现文件传输

    万次阅读 2018-07-25 18:12:24
    Socket实现文件传输 1.客户端 通过new Socket("ip",port)连接服务端 创建文件输入流读取文件 创建返回套接字的输出流 写入文章名称,长度等属性 读取、写入文章操作 关闭流 package com.company;...

    Socket实现文件传输

    1.客户端

    通过new Socket("ip",port)连接服务端

    创建文件输入流读取文件

    创建返回套接字的输出流

    写入文章名称,长度等属性

    读取、写入文章操作

    关闭流

    package com.company;
    
    import javax.xml.crypto.Data;
    import java.io.*;
    import java.net.Socket;
    
    //客户端
    public class Client extends Socket{
    	private  final String SERVER_IP="192.168.201.104";
    	private final int SERVER_PORT=8999;
    	private Socket client;
    	private FileInputStream fis;
    	private DataOutputStream dos;
    
    	//创建客户端,并指定接收的服务端IP和端口号
    	public Client() throws IOException{
    		this.client=new Socket(SERVER_IP,SERVER_PORT);
    		System.out.println("成功连接服务端..."+SERVER_IP);
    	}
    
    	//向服务端传输文件
    	public void sendFile(String url) throws IOException {
    		File file=new File(url);
    		try {
    			 fis = new FileInputStream(file);
    			//BufferedInputStream bi=new BufferedInputStream(new InputStreamReader(new FileInputStream(file),"GBK"));
    			dos = new DataOutputStream(client.getOutputStream());//client.getOutputStream()返回此套接字的输出流
    			//文件名、大小等属性
    			dos.writeUTF(file.getName());
    			dos.flush();
    			dos.writeLong(file.length());
    			dos.flush();
    			// 开始传输文件
    			System.out.println("======== 开始传输文件 ========");
    			byte[] bytes = new byte[1024];
    			int length = 0;
    			
    			while ((length = fis.read(bytes, 0, bytes.length)) != -1) {
    				dos.write(bytes, 0, length);
    				dos.flush();
    			}
    			System.out.println("======== 文件传输成功 ========");
    		}catch(IOException e){
    			e.printStackTrace();
    			System.out.println("客户端文件传输异常");
    		}finally{
    			fis.close();
    			dos.close();
    		}
    	}
    	public static void main(String[] args) {
    		try {
    			Client client = new Client(); // 启动客户端连接
    			client.sendFile("E:/dxn/aaa.txt"); // 传输文件
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    

    2服务端

    启动服务端new ServerSocket(port)

    接收连接服务端的客户端对象

    创建返回套接字的输入流

    创建文件输出流写出文件

    读取文章名称,长度等属性

    读取、写入文章操作

    关闭流

    package com.company;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class FileServer extends ServerSocket{
    
            private static final int SERVER_PORT = 8999; // 服务端端口
            private ServerSocket server;
            private Socket socket;
            private DataInputStream dis;
            private FileOutputStream fos;
    
            public FileServer() throws Exception {
                server=new ServerSocket(SERVER_PORT);
            }
    
            public void task() throws IOException{
                System.out.println("======== 等待连接 ========");
                Socket socket = server.accept();
                System.out.println(" Ip:"+socket.getInetAddress()+"已连接");
                try {
                    dis = new DataInputStream(socket.getInputStream());
                    // 文件名和长度
                    String fileName = dis.readUTF();
                    long fileLength = dis.readLong();
                    File directory = new File("E:/a");
                    if(!directory.exists()) {
                        directory.mkdir();
                    }
                    File file = new File(directory.getAbsolutePath() + File.separatorChar + fileName);
    
                    fos = new FileOutputStream(file);
                    System.out.println("file。。。。。。。。。。。。。。"+file);
                    System.out.println("fileName。。。。。。。。。。。。。。"+fileName);
    
                    System.out.println("======== 开始接收文件 ========");
                    byte[] bytes = new byte[1024];
                    int length = 0;
                    while((length = dis.read(bytes, 0, bytes.length)) != -1) {
                        fos.write(bytes, 0, length);
                        fos.flush();
                    }
    
                    System.out.println("======== 文件接收成功 ========");
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            if(fos != null)
                                fos.close();
                            if(dis != null)
                                dis.close();
                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
    
            public static void main(String[] args) {
                try {
                    FileServer server = new FileServer(); // 启动服务端
                    server.task();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
    

    3. 每接收到一个Socket就建立一个新的线程来处理它

    package com.company;
    
    
    import java.io.DataInputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class Server extends ServerSocket {
    
    	private static final int SERVER_PORT = 8999; // 服务端端口
    
    	private ServerSocket server;
    
    	public Server() throws Exception {
    		server=new ServerSocket(SERVER_PORT);
    	}
    
    	/**
    	 * 使用线程处理每个客户端传输的文件
    	 * @throws Exception
    	 */
    	public void load() throws Exception {
    		while (true) {
    			System.out.println("-----------等待连接-------- ");
    			Socket socket = server.accept();//接收连接服务端的客户端对象
    			System.out.println("ip" + socket.getInetAddress() + "已连接");
    			new Thread(new Transfer(socket),"thread1").start();// 每接收到一个Socket就建立一个新的线程来处理它
    			System.out.println(Thread.currentThread().getName());
    		}
    	}
    
    	/**
    	 * 处理客户端传输过来的文件线程类
    	 */
    	class Transfer implements Runnable {
    
    		private Socket socket;
    		private DataInputStream dis;
    		private FileOutputStream fos;
    
    		public Transfer(Socket socket) {
    			this.socket = socket;
    		}
    
    		@Override
    		public void run() {
    			try {
    				dis = new DataInputStream(socket.getInputStream());
    
    				// 文件名和长度
    				String fileName = dis.readUTF();
    				long fileLength = dis.readLong();
    				File directory = new File("E:/xn");
    				if(!directory.exists()) {
    					directory.mkdir();
    				}
    				File file = new File(directory.getAbsolutePath() + File.separatorChar + fileName);
    				System.out.println("file"+file);
    				fos = new FileOutputStream(file);
    
    				// 开始接收文件
    				byte[] bytes = new byte[1024];
    				int length = 0;
    				while((length = dis.read(bytes, 0, bytes.length)) != -1) {
    					fos.write(bytes, 0, length);
    					fos.flush();
    				}
    				System.out.println("======== 文件接收成功 [File Name:" + fileName + "] ");
    			} catch (Exception e) {
    				e.printStackTrace();
    			} finally {
    				try {
    					if(fos != null)
    						fos.close();
    					if(dis != null)
    						dis.close();
    
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    	public static void main(String[] args) {
    		try {
    			Server server = new Server(); // 启动服务端
    			server.load();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    
    

     4.DataInputStream:数据输入流     读取基本 Java 数据类型

    DataOutputStream:数据输出流      写出基本 Java 数据类型

     

     

    展开全文
  • 使用TCP协议实现文件传输

    千次阅读 2013-01-17 15:54:42
    使用TCP协议实现文件传输。程序会分为服务器端和客户端,首先运行服务器端,监听来自客户端的连接,客户端运行后会通过程序内的服务器端IP地址,向服务器发送连接请求。双方建立请求之后,客户端将所需文件的文件名...

    使用TCP协议实现文件传输。程序会分为服务器端和客户端,首先运行服务器端,监听来自客户端的连接,客户端运行后会通过程序内的服务器端IP地址,向服务器发送连接请求。双方建立请求之后,客户端将所需文件的文件名和绝对路径传输给服务器,如果服务器找到此文件,则将此文件传输给客户端,然后断开连接。

    具体算法描述如下:

    【1】服务器端:

    1、初始化socket服务

    2、监听连接请求并做相应的处理

    2.1创建监听套接字

    2.2监听套接口

    2.3接受套接字的连接

    2.4接收客户端传来的数据

    case 文件绝对路径:

    按照路径找到文件,并打开。提取本地文件名,发回给客户端

    发送文件总长度给客户端

    case 已准备接收文件完毕

    if 发送缓冲区为空

    读取文件,写入缓冲区

    将文件流分成大小相同的组(最后一组可能会小一点),顺次发送给客户端

    将缓冲区清空

    case 文件成功传送

    打印消息,退出

    case 文件已存在

    打印消息,退出

    2.5关闭同客户端的连接

    3、释放socket服务

    【2】客户端:

    1、初始化socket,winsock服务

    2、连接服务器,进行数据的传输

    2.1初始化,创建套接字

    2.2通过IP地址,向服务器发送连接请求,建立连接

    2.3主动发送所求文件绝对路径

    2.4接受服务器端数据并做相应处理

    case 打开文件错误:

    重新发送文件绝对路径至服务器,请求重发

    case 文件长度:

    打印消息

    case 文件名:

    if 文件已经存在

    发送“文件已经存在”

    else

    分配缓冲区,并向服务器发送“Ready”消息

    case 文件流:

    为已接收文件名创建文件

    打开文件,将文件流数据写入文件,直至接收所有分组数据

    发送“成功接收“消息

    3、关闭套接字

    释放服务

    源程序:

    【1】服务器端:

    头文件:

    /*server.h*/
    #pragma comment(lib, "WS2_32")
    #include <WinSock2.h>
    #include <iostream>
    #include <assert.h>
    #include<Windows.h>
    #ifndef COMMONDEF_H
    #define COMMONDEF_H
    #define MAX_PACKET_SIZE   10240    // 数据包的最大长度,单位是sizeof(char)
    #define MAXFILEDIRLENGTH 256     // 存放文件路径的最大长度
    #define PORT     4096    // 端口号
    //#define SERVER_IP    "127.0.0.1" // server端的IP地址
    // 各种消息的宏定义
    #define INVALID_MSG      -1   // 无效的消息标识
    #define MSG_FILENAME     1   // 文件的名称
    #define MSG_FILELENGTH     2   // 传送文件的长度
    #define MSG_CLIENT_READY    3   // 客户端准备接收文件
    #define MSG_FILE      4   // 传送文件
    #define MSG_SENDFILESUCCESS    5   // 传送文件成功
    #define MSG_OPENFILE_ERROR    10   // 打开文件失败,可能是文件路径错误找不到文件等原因
    #define MSG_FILEALREADYEXIT_ERROR 11   // 要保存的文件已经存在了
    class CCSDef
    {
    public:
    #pragma pack(1)      // 使结构体的数据按照1字节来对齐,省空间
    // 消息头
    struct TMSG_HEADER
    {
       char    cMsgID;    // 消息标识
       TMSG_HEADER(char MsgID = INVALID_MSG)
        : cMsgID(MsgID)
       {
       }
    };
    // 请求传送的文件名
    // 客户端传给服务器端的是全路径名称
    // 服务器传回给客户端的是文件名
    struct TMSG_FILENAME : public TMSG_HEADER
    {
       char szFileName[256];   // 保存文件名的字符数组
       TMSG_FILENAME()
        : TMSG_HEADER(MSG_FILENAME)
       {
       }
    };
    // 传送文件长度
    struct TMSG_FILELENGTH : public TMSG_HEADER
    {
       long lLength;
       TMSG_FILELENGTH(long length)
        : TMSG_HEADER(MSG_FILELENGTH), lLength(length) 
       {
       }
    };
    // Client端已经准备好了,要求Server端开始传送文件
    struct TMSG_CLIENT_READY : public TMSG_HEADER
    {
       TMSG_CLIENT_READY()
        : TMSG_HEADER(MSG_CLIENT_READY)
       {
       }
    };
    // 传送文件
    struct TMSG_FILE : public TMSG_HEADER
    {
       union     // 采用union保证了数据包的大小不大于MAX_PACKET_SIZE * sizeof(char)
       {
        char szBuff[MAX_PACKET_SIZE];
        struct
        {
         int nStart;
         int nSize;
         char szBuff[MAX_PACKET_SIZE - 2 * sizeof(int)];
        }tFile;
       };
       TMSG_FILE()
        : TMSG_HEADER(MSG_FILE)
       {
       }
    };
    // 传送文件成功
    struct TMSG_SENDFILESUCCESS : public TMSG_HEADER
    {
       TMSG_SENDFILESUCCESS()
        : TMSG_HEADER(MSG_SENDFILESUCCESS)
       {
       }
    };
    // 传送出错信息,包括:
    // MSG_OPENFILE_ERROR:打开文件失败
    // MSG_FILEALREADYEXIT_ERROR:要保存的文件已经存在了
    struct TMSG_ERROR_MSG : public TMSG_HEADER
    {
       TMSG_ERROR_MSG(char cErrorMsg)
        : TMSG_HEADER(cErrorMsg)
       {
       }
    };
    #pragma pack()
    };
    #endif
    

    cpp文件:

    /*Server.cpp*/
    #include"Server.h"
    char g_szNewFileName[MAXFILEDIRLENGTH];
    char g_szBuff[MAX_PACKET_SIZE + 1];
    long g_lLength;
    char* g_pBuff = NULL;
    //初始化socket库
    bool InitSocket();
    //关闭socket库
    bool CloseSocket();
    //解析消息并进行相应的处理
    bool ProcessMsg(SOCKET sClient);
    //监听Client消息
    void ListenToClient();
    //打开文件
    bool OpenFile(CCSDef::TMSG_HEADER* pMagHeader,SOCKET sClient);
    //传送文件
    bool SendFile(SOCKET sClient);
    //读取文件进缓冲区
    bool ReadFile(SOCKET sClient);
    
    int main()
    {
    	while(1)
    	{
    		InitSocket();
    		ListenToClient();
    		CloseSocket();
    		system("del E:\\test1.A_exp");
    	}
    		//system("pause");
    	return 0;
    }
    
    //初始化socket库
    bool InitSocket()
    {
    	WSADATA wsaData;
    	WORD socketVersion=MAKEWORD(2,2);
    	if(::WSAStartup(socketVersion,&wsaData)!=0)
    	{//初始化WinSock服务
    		printf("Init socket dll error\n");
    		return false;
    	}
    	return true;
    }
    //关闭socket库
    bool CloseSocket()
    {//释放winsock库
    	::WSACleanup();
    	if(g_pBuff != NULL)
    	{
    		delete [] g_pBuff;
    		g_pBuff = NULL;
    	}
    	return true;
    }
    //解析消息并进行相应的处理
    bool ProcessMsg(SOCKET sClient)
    {
    	//从套接口中接收数据,返回copy的字节数
    	int nRecv = ::recv(sClient,g_szBuff,MAX_PACKET_SIZE+1,0);
    	if(nRecv>0)
    	{
    		g_szBuff[nRecv]='\0';
    	}
    	//解析命令
    	CCSDef::TMSG_HEADER* pMsgHeader=(CCSDef::TMSG_HEADER*)g_szBuff;
    
    	switch(pMsgHeader->cMsgID)
    	{
    	case MSG_FILENAME://文件名
    		{
    			OpenFile(pMsgHeader,sClient);
    		}
    		break;
    	case MSG_CLIENT_READY://客户端已准备完毕,开始传送文件
    		{
    			SendFile(sClient);
    		}
    		break;
    	case MSG_SENDFILESUCCESS://传送文件成功
    		{
    			printf("Send File Success!\n");
    			return false;
    		}
    		break;
    	case MSG_FILEALREADYEXIT_ERROR://要保存的文件已经存在
    		{
    			printf("The file ready to send already exit!\n");
    			return false;
    		}
    		break;
    	}
    	return true;
    }
    //监听Client消息
    void ListenToClient()
    {
    	//创建套接字
    	SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    	if(sListen == SOCKET_ERROR)
    	{
    		printf("Init Socket Error!\n");
    		return;
    	}
    	//绑定socket
    	sockaddr_in sin;
    	sin.sin_family=AF_INET;
    	sin.sin_port=htons(PORT);
    	sin.sin_addr.S_un.S_addr=INADDR_ANY;
    	if (::bind(sListen, (LPSOCKADDR)&sin, sizeof(sockaddr_in)) == SOCKET_ERROR)
    	{
    	   printf("Bind Error!\n");
    	   return;
    	}
    	// 设置socket进入监听状态
    	if(::listen(sListen,10)==SOCKET_ERROR)
    	{
    		printf("Listen Error!\n");
    		return;
    	}
    	printf("Listening To Client...\n");
    	//循环接收client端的连接请求
    	sockaddr_in ClientAddr;
    	int nAddrLen = sizeof(sockaddr_in);
    	SOCKET sClient;
    	//取队列最前端客户连接请求,创建套接字连接通道
    	while((sClient=::accept(sListen,(sockaddr*)&ClientAddr,&nAddrLen))==INVALID_SOCKET)
    	{}
    	//解析消息并进行相应的处理
    	//int count=10;//作为定时当程序执行10s未完成时直接退出
    	//while(ProcessMsg(sClient)==true&&count>0)
    	//{
    	//	Sleep(1000);
    	//	count--;
    	//}
    	while(ProcessMsg(sClient)==true)
    	{
    		Sleep(1000);
    	}
    	//关闭同客户端的连接
    	::closesocket(sClient);
    	::closesocket(sListen);
    }
    //打开文件
    bool OpenFile(CCSDef::TMSG_HEADER* pMsgHeader,SOCKET sClient)
    {
    	CCSDef::TMSG_FILENAME* pRequstFileNameMsg=(CCSDef::TMSG_FILENAME*)pMsgHeader;
    	//对文件名进行处理
    	char *p1,*p2;
    	for(p1=pRequstFileNameMsg->szFileName,p2=g_szNewFileName;*p1!='\0';p1++,p2++)
    	{
    		if(*p1!='\n')
    		{
    			*p2=*p1;
    		}
    		if(*p2=='\\')//将‘\’转换为‘\\’
    		{
    			*(++p2)='\\';
    		}
    	}
    	*p2='\0';
    	ReadFile(sClient);
    	return true;
    }
    //传送文件
    bool SendFile(SOCKET sClient)
    {
    	if (NULL == g_pBuff)
    	{//如果缓冲区为空
    	   ReadFile(sClient);
    	}
    	int nPacketBufferSize = MAX_PACKET_SIZE - 2 * sizeof(int); // 每个数据包存放文件的buffer大小
    	// 如果文件的长度大于每个数据包所能传送的buffer长度那么就分块传送
    	for (int i = 0; i < g_lLength; i += nPacketBufferSize)
    	{  
    	   CCSDef::TMSG_FILE tMsgFile;
    	   tMsgFile.tFile.nStart = i;
    	   if (i + nPacketBufferSize + 1> g_lLength)
    	   {//文件块已经是最后一块
    		tMsgFile.tFile.nSize = g_lLength - i;
    	   }
    	   else
    	   {
    		tMsgFile.tFile.nSize = nPacketBufferSize;
    	   }
    	   memcpy(tMsgFile.tFile.szBuff, g_pBuff + tMsgFile.tFile.nStart, tMsgFile.tFile.nSize);//copy到缓冲区
    	   ::send(sClient, (char*)(&tMsgFile), sizeof(CCSDef::TMSG_FILE), 0);
    	   Sleep(0.5);
    	}
    	delete [] g_pBuff;
    	g_pBuff = NULL;
    	return true;
    }
    //读取文件进缓冲区
    bool ReadFile(SOCKET sClient)
    {
    	if(g_pBuff!=NULL)
    	{//如果缓冲区不为空
    		return true;
    	}
    	//打开文件
    	FILE *pFile;
    	if((pFile = fopen(g_szNewFileName, "rb"))==NULL)
    	{//文件打开失败,发送错误报告
    		 printf("Cannot find the file, request the client input file name again\n");
    		 CCSDef::TMSG_ERROR_MSG tMsgErrorMsg(MSG_OPENFILE_ERROR);
    		 ::send(sClient, (char*)(&tMsgErrorMsg), sizeof(CCSDef::TMSG_ERROR_MSG), 0);
    		 return false;
    	}
    	//传送文件长度到Client
    	fseek(pFile,0,SEEK_END);//重定位指针到文件末尾
    	g_lLength=ftell(pFile);//返回文件指针相对于文件头的偏移量
    	printf("File Length = %d\n", g_lLength);
    	CCSDef::TMSG_FILELENGTH tMsgFileLength(g_lLength);
    	::send(sClient,(char*)(&tMsgFileLength), sizeof(CCSDef::TMSG_FILELENGTH), 0);
    	// 处理文件全路径名,把文件名分解出来
    	//磁盘号,目录,文件名,后缀名
    	char szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szFname[_MAX_FNAME], szExt[_MAX_EXT];
    	_splitpath(g_szNewFileName, szDrive, szDir, szFname, szExt);
    	strcat(szFname,szExt);
    	CCSDef::TMSG_FILENAME tMsgFileName;
    	strcpy(tMsgFileName.szFileName, szFname);
    	printf("Send File Name: %s\n", tMsgFileName.szFileName);
    	::send(sClient, (char*)(&tMsgFileName), sizeof(CCSDef::TMSG_FILENAME), 0);
    	//分配缓冲区,读取文件内容
    	g_pBuff = new char[g_lLength + 1];
    	if (g_pBuff == NULL)
    	{
    	   return false;
    	}
    	fseek(pFile, 0, SEEK_SET);
    	fread(g_pBuff, sizeof(char), g_lLength, pFile);
    	g_pBuff[g_lLength] = '\0';
    	fclose(pFile);
    	return true;
    }

    【2】客户端:

    头文件同服务器端头文件

    源程序文件:

    /*Client.cpp*/
    #include"Client.h"
    long g_lLength = 0;
    char* g_pBuff = NULL;
    char g_szFileName[MAXFILEDIRLENGTH];
    char g_szBuff[MAX_PACKET_SIZE+1];
    SOCKET g_sClient;
    // 初始化socket库
    bool InitSocket();
    // 关闭socket库
    bool CloseSocket();
    // 把用户输入的文件路径传送到server端
    bool SendFileNameToServer();
    // 与server端连接
    bool ConectToServer();
    // 打开文件失败
    bool OpenFileError(CCSDef::TMSG_HEADER *pMsgHeader);
    // 分配空间以便写入文件
    bool AllocateMemoryForFile(CCSDef::TMSG_HEADER *pMsgHeader);
    // 写入文件
    bool WriteToFile(CCSDef::TMSG_HEADER *pMsgHeader);
    // 处理server端传送过来的消息
    bool ProcessMsg();
    
    int main()
    {
    	while(1)
    	{
    		InitSocket();
    		ConectToServer();
    		CloseSocket();
    	}
    	//system("pause");
    	return 0;
    }
    
    // 初始化socket库
    bool InitSocket()
    {
    	//初始化SOCKET
    	WSADATA wsaData;
    	WORD socketVersion=MAKEWORD(2,2);
    	if(::WSAStartup(socketVersion,&wsaData)!=0)
    	{
    		printf("Init socket dll error\n");
    		exit(-1);
    	}
    	return true;
    }
    // 关闭socket库
    bool CloseSocket()
    {
    	// 关闭套接字
    	::closesocket(g_sClient);
    	// 释放winsock库
    	::WSACleanup();
    	return true;
    }
    // 把用户输入的文件路径传送到server端
    bool SendFileNameToServer()
    {
    	char szFileName[MAXFILEDIRLENGTH];
    	printf("Input the File Directory: ");
    	//fgets(szFileName, MAXFILEDIRLENGTH, stdin);
    	strcpy(szFileName,"E:\\test1.A_exp");
    	// 把文件路径发到server端
    	CCSDef::TMSG_FILENAME tMsgRequestFileName;
    	strcpy(tMsgRequestFileName.szFileName, szFileName);
    	if (::send(g_sClient, (char*)(&tMsgRequestFileName), sizeof(CCSDef::TMSG_FILENAME), 0) == SOCKET_ERROR)
    	{
    	   printf("Send File Name Error!\n");
    	   exit(-1);
    }
    return true;
    }
    // 与server端连接
    bool ConectToServer()
    {
    	// 初始化socket套接字
    	if ((g_sClient = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR)
    	{
    	   printf("Init Socket Error!\n");
    	   exit(-1);
    	}
    	sockaddr_in servAddr;
    	servAddr.sin_family = AF_INET;
    	servAddr.sin_port = htons(PORT);
    	servAddr.sin_addr.S_un.S_addr = ::inet_addr(SERVER_IP);
    	if ((::connect(g_sClient, (sockaddr*)&servAddr, sizeof(sockaddr_in))) == INVALID_SOCKET)
    	{
    	   printf("Connect to Server Error!\n");
    	   exit(-1);
    	}
    	// 输入文件路径传输到server端
    	SendFileNameToServer();
    	// 接收server端传过来的信息,直到保存文件成功为止
    	while (ProcessMsg() == true)
    	{
    		Sleep(1000);
    	}
    	return true;
    }
    // 打开文件失败
    bool OpenFileError(CCSDef::TMSG_HEADER *pMsgHeader)
    {
    	if (g_pBuff != NULL)//如果缓冲区内有数据
    	   return true;
    	assert(pMsgHeader != NULL);
    	printf("Cannot find file!\n");
    	// 重新输入文件名称
    	SendFileNameToServer();
    	return true;
    }
    // 分配空间以便写入文件
    bool AllocateMemoryForFile(CCSDef::TMSG_HEADER *pMsgHeader)
    {
    	assert(pMsgHeader != NULL);
    	if (g_pBuff != NULL)
    	{
    	   return true;
    	}
    	CCSDef::TMSG_FILENAME* pRequestFilenameMsg = (CCSDef::TMSG_FILENAME*)pMsgHeader;
    	printf("File Name: %s\n", pRequestFilenameMsg->szFileName);
    	// 把文件的路径设置为D盘根目录下
    	strcpy(g_szFileName, "D:\\");
    	strcat(g_szFileName, "test2.B_imp");
    	//strcat(g_szFileName, pRequestFilenameMsg->szFileName);
    	// 查找相同文件名的文件是否已经存在,如果存在报错退出
    	FILE* pFile;
    	if ((pFile = fopen(g_szFileName, "r")) != NULL)
    	{
    	   // 文件已经存在,要求重新输入一个文件
    	   printf("The file already exist!\n");
    	   CCSDef::TMSG_ERROR_MSG tMsgErrorMsg(MSG_FILEALREADYEXIT_ERROR);
    	   ::send(g_sClient, (char*)(&tMsgErrorMsg), sizeof(CCSDef::TMSG_ERROR_MSG), 0);
    	   fclose(pFile);
    	   return false;
    	}
    	// 分配缓冲区开始接收文件,如果分配成功就给server端发送开始传送文件的要求
    	g_pBuff = new char[g_lLength + 1];
    	if (g_pBuff != NULL)
    	{
    	   memset(g_pBuff, '\0', g_lLength + 1);
    	   printf("Now ready to get the file %s!\n", pRequestFilenameMsg->szFileName);
    	   CCSDef::TMSG_CLIENT_READY tMsgClientReady;
    	   if (::send(g_sClient, (char*)(&tMsgClientReady), sizeof(CCSDef::TMSG_CLIENT_READY), 0) == SOCKET_ERROR)
    	   {
    		printf("Send Error!\n");
    		exit(-1);
    	   }
    	}
    	else
    	{
    	   printf("Alloc memory for file error!\n");
    	   exit(-1);
    	}
    	return true;
    }
    // 写入文件
    bool WriteToFile(CCSDef::TMSG_HEADER *pMsgHeader)
    {
    	assert(pMsgHeader != NULL);
    	CCSDef::TMSG_FILE* pMsgFile = (CCSDef::TMSG_FILE*)pMsgHeader;
    	int nStart = pMsgFile->tFile.nStart;
    	int nSize = pMsgFile->tFile.nSize;
    	memcpy(g_pBuff + nStart, pMsgFile->tFile.szBuff, nSize);
    	if (nStart == 0)
    	{
    	   printf("Saving file into buffer...\n");
    	}
    	memcpy(g_pBuff + nStart, pMsgFile->tFile.szBuff, nSize);
    	
    	// 如果已经保存到缓冲区完毕就写入文件
    	if (nStart + nSize >= g_lLength)
    	{
    	   printf("Writing to disk....\n");
    	   // 写入文件
    	   FILE* pFile;
    	   pFile = fopen(g_szFileName, "w+b");
    	   fwrite(g_pBuff, sizeof(char), g_lLength, pFile);
    	   delete [] g_pBuff;
    	   g_pBuff = NULL;
    	   fclose(pFile);
    	   // 保存文件成功传送消息给server退出server
    	   CCSDef::TMSG_SENDFILESUCCESS tMsgSendFileSuccess;
    	   while (::send(g_sClient, (char*)(&tMsgSendFileSuccess), sizeof(CCSDef::TMSG_SENDFILESUCCESS), 0) == SOCKET_ERROR)
    	   {
    	   }
    	   printf("Save the file %s success!\n", g_szFileName);
    	   return true;
    	}
    	else
    	{
    	   return false;
    	}
    }
    // 处理server端传送过来的消息
    bool ProcessMsg()
    {
    	CCSDef::TMSG_HEADER *pMsgHeader;
    	int nRecv = ::recv(g_sClient, g_szBuff, MAX_PACKET_SIZE + 1, 0);
    
    	pMsgHeader = (CCSDef::TMSG_HEADER*)g_szBuff;
    	switch (pMsgHeader->cMsgID)
    	{
    	case MSG_OPENFILE_ERROR:   // 打开文件错误
    	   {
    		OpenFileError(pMsgHeader);
    	   }
    	   break;
    	case MSG_FILELENGTH:    // 文件的长度
    	   {
    		if (g_lLength == 0)
    		{
    		 g_lLength = ((CCSDef::TMSG_FILELENGTH*)pMsgHeader)->lLength;
    		 printf("File Length: %d\n", g_lLength);
    		}
    	   }
    	   break;
    	case MSG_FILENAME:     // 文件名
    	   {
    		return AllocateMemoryForFile(pMsgHeader);
    	   }
    	   break;
    	case MSG_FILE:      // 传送文件,写入文件成功之后退出这个函数
    	   {
    		if (WriteToFile(pMsgHeader))
    		{
    			/*Sleep(1000);*/
    		 return false;
    		}
    	   }
    	   break;
    	}
    	return true;
    }


    展开全文
  • C++实现网络文件传输

    热门讨论 2020-07-29 14:18:51
    C++实现多线程网络文件传输
  • 快速实现大文件传输你了解多少?

    千次阅读 2018-09-08 17:57:50
    方方面面的行业都要涉及到大文件传输。例如影视行业需要每天进行视频素材的传输,一个视频小至几十兆,多至几T的视频数据要从拍摄地传输到视频中心。又或者气象行业的各地气象观测点需要实时进行气象观测,即时有效...

    在互联网时代,速度决定效率。在企业生产过程中需要进行信息数据交换、搬运。这时就需要进行大文件的传输。方方面面的行业都要涉及到大文件传输。例如影视行业需要每天进行视频素材的传输,一个视频小至几十兆,多至几T的视频数据要从拍摄地传输到视频中心。又或者气象行业的各地气象观测点需要实时进行气象观测,即时有效地将数据汇总到气象局,以发布准确无误的天气预报。例如互联网科技公司,大数据分析公司向各个行业客户接收各种数据资料。例如大型企业每个月初需要将各分部财务数据传输到总部进行汇总等。面对如此庞大的数据量,企业如何能将大文件安全、稳定、高效地进行传输,那么大文件传输工具对于企业来说是必不可少的。

    目前,市面上文件传输的工具有很多。小文件传输可使用网络共享工具例如QQ、邮箱、等进行传输,虽然点对点传输使用方便,但是对于文件大小确有限制,根据网络环境而言速度有时候也较慢。但对于个人用户小文件传输来说不失为一个方便的选择。

    大文件传输使用filezilla、网盘等进行传输比较稳定,支持断点续传,但是进行大文件传输时速度极慢,丢包率大,传输可靠性差,跨国传输时速度低尤为明显。使用网盘操作不方便,还需要先将文件上传到终端后再进行下载。

    此外,对于大型文件也可采用寄硬盘的方式,可将大量文件送达至目的地,但是运送途中易发生硬盘损坏、快递延误等不可预测地问题,也不能达到实时性。


    若是企业级大文件传输就可以选择使用镭速(Raysync)这款软件了,是一款针对企业大文件传输的企业级传输产品,秉承着更快、更炫、更稳定、更强大的宗旨,在大文件传输方面表现十分优异。可以将大文件可靠迅速地传输到目的地,在跨国传输方面也十分优秀,镭速传输软件有以下优点:

    • 传输采用网页版,30秒安装,操作简单;
    • 这款传输软件支持一对一、一对多、多对一传输,通过多种传输模式混合,灵活地解决超大文件传输难题;
    • 传输数据可靠,传输层面对传输的数据采用多层通道加密技术,数据安全有保障;
    • 支持断点续传,即使传输中断也能无缝进行续传;
    • 充分利用带宽,让传输速度发挥到极致,根据实际测试结果,大文件传输速度最高可提高100倍以上,单条连接最大速度可以支持1Gbps;
    • 传输SDK集成,极简集成,即可将镭速高速传输引擎无缝嵌入。

    速度决定效率,时间决定金钱。现在大数据对于企业来说十分重要,庞大的数据必定需要大文件的快速传输才能将信息实时把握在企业手中。实现了大文件快速传输能提高工作效率,让企业快人一步,如虎添翼。

    展开全文
  • 在木马中文件管理的重要性,是无需质疑的,对于文件的管理,做到并不难,但做好却也不易在我们编写一个功能完整的“文件木马”其实现效果如图所示。为了文章的完整性,我们将分为数篇来介绍,本文主要介绍程序的整体...
    在木马中文件管理的重要性,是无需质疑的,对于文件的管理,做到并不难,但做好却也不易在我们编写一个功能完整的“文件木马”
    其实现效果如图所示。为了文章的完整性,我们将分为数篇来介绍,本文主要介绍程序的整体框架和界面实现,在以后的文章中将以此框架为基础实现详细的功能。


    编写环境

    程序的编写环境为VC6.0+WINDOWS2000 除界面外的其它部分如,程序框架,功能实现 大多用API实现所以若要移值到其它环境还是比较方便的。


    实现目标

    在开始工作前,先明确目得和方向,这样可以避免少走弯路,我们的目标主要有:枚举磁盘,枚举目录,获取文件信息
    上传文件,下载文件,执行文件,创建目录,删除目录等



    传输控制结构


    要实现客户端与服务端的通信,设计一个合理的传输控制结构,会使后面的工作轻松很多,为了使代码易读
    首先对要使用的命令进行预定义其各个命令定义如下

    #define GetDriver 0x01 //磁盘信息
    #define GetDirInfo 0x02 //目录信息
    #define ExecFile 0x03 //执行文件
    #define GetFile 0x04 //下载文件
    #define PutFile 0x05 //上传文件
    #define DelFile 0x06 //删除文件
    #define DelDir 0x07 //删除目录
    #define CreateDir 0x08 //创建目录
    #define FileInfo 0x09 //文件信息
    #define GetScreen 0x10 //查看屏幕


    在程序的网络通信中主要有 操作命令 ,命令对像,和具体数据三部分,对于命令的传输定义如下结构

    typedef struct
    {
    int ID; //操作命令
    BYTE lparam[BUF_LEN*2]; //命令对像

    }COMMAND;


    因为在程序中打交道最多的就是文件,对文件的详细属性定义如下结构


    typedef struct
    {
    char FileName[MAX_PATH]; //文件名称
    int FileLen; //文件长度
    char Time[50]; //时间信息
    BOOL IsDir; //为目录否
    BOOL Error; //错误信息
    HICON hIcon; //图标句柄

    }FILEINFO;








    服务端结构




    服务端还是比较简单的其整体思路如下


    1.服务端循环接受连接,并把连接交给线程处理
    2.线程接受"命令数据",并跟据命令ID将命令对像和SOCKET句柄传给处理函数
    3.函数执行指定功能,并返回执行结果

    对整体结构的描述,我们用伪代码表述如下

    main()
    { /*初示化设置......*/

    while(true)
    {
    if(client=accept(server,(sockaddr *)&clientaddr,&len))//循环接受连接
    {
    CreateThread(NULL,NULL,SLisen,(LPVOID)client,NULL,NULL);//传递线程处理
    }
    }
    /*清理释放资源......*/

    WSACleanup();
    }

    服务端程序运行后循环接受连接,如果有新的连接就传递给新的线程处理,线程代码如下

    DWORD WINAPI SLisen(LPVOID lparam)
    {
    SOCKET client=(SOCKET)lparam;
    COMMAND command;
    while(1)
    {
    if(recv(client,(char*)&command,sizeof(command),0)==SOCKET_ERROR)//接受命令数据
    {
    cout<<"The Clinet Socket is Closed/n";
    break;
    }else
    {
    switch(command.ID)//判断命令ID
    {
    case GetDriver://将命令对像和SOCKET句柄传递给处理函数
        GetDriverProc (command,client);
        break;
    case DelFile:
        DelFileProc (command,client);
        break;
    /*其它命令......*/
    }
    }
    }
    }

    线程式的功能是接受客户端的"命令数据",并跟跟据命令ID 将命令对像传递给处理函数,由函数完成指定的功能
    以删除文件命令为例其函数格式如下

    DWORD DelFileProc (COMMAND command,SOCKET client)
    {
    if(DeleteFile((char*)command.lparam)==0)//command.lparam为命令对像,这里为要删除的文件路径
    {
    send(client,"删除失败...");
    }
    else
    {
    send(client,"删除成功...");
    }
    }

    很容易看出,处理函数接受"命令对像"和客户端SOCKET句柄,执行后会把结果传递回去....







    客户端结构


    客户端结构的实现思路如下

    1.跟服务端建立连接
    2.发送用户命令
    3.启动一个线程,用于接受服务端的返回信息

    对整体结构的描述,我们用伪代码表述如下

    void CMyDlg::OnConnect()
    {
    if(connect(server,(SOCKADDR*)&serveraddr,sizeof(serveraddr))<0)//连接....
    {
    return ;
    }
    CreateThread(NULL,NULL,CLisen,this,NULL,NULL);//创建线程用于接受SERVER返回信息
    }


    对于用户发送的命令我们仍以删除文件为例说明其代码如下

    void CMyDlg::OnMenuDelFile()
    {
    HTREEITEM CurrentNode =   m_tree.GetSelectedItem(); //取得选择的节点
    CString FullPath =GetFullPath(CurrentNode); //取得节点全目录
    COMMAND command;
    command.ID=DelFile; //设置命令为删除文件 //删除文件
    command.lparam=FullPath.LockBuffer()); //将路径加入命令对像
    send(server,command);
    }


    用于接受SERVER返回信息的线程,和服务端接受命令线程相似,这里就不再说明了,有兴趣可以看下源代码

    到这里程序的流程框架就介绍完了,下面我们再看一下程序的界面设置.


    界面实现

    程序的主界面如上图所示,主程序是一个对话框,主要包括一个树控件m_tree和列表控件m_list分别
    用于显示磁盘目录和文件,在对话框初示化时用以下代码设置树控件的属性

    DWORD dwStyle = GetWindowLong(m_tree.m_hWnd,GWL_STYLE);
    dwStyle |=TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT;
    SetWindowLong(m_tree.m_hWnd,GWL_STYLE,dwStyle);

    对于列表框控件则没有太多要求,要留意的是,如果显示图标应该把Styles显示属性设置为ICON

    VC的做出的界面,常常让人有种摔键盘的冲动。其实稍微留意一下其设置,也可以让它漂亮一些
    比如上图所示的界面就是经过简单设置得到的,而没有用其它类库,有点兴趣?其设置方法为:

    1.在对话框属性中设置Styles 的Border属性为Thin
    2.选重More Styles "可见" 属性
    3.选重Extended Styles的"静态边"属性

    这样再运行一下程序是不是感觉清新不少?

    到这里程序的主要结构框架和界面实现就介绍完了,下一篇将详细介绍其各种功能的实现
    展开全文
  • 文件传输

    2018-04-25 22:09:43
    不同系统之间的文件传输####1.文件归档####1.文件归档,就是把多个文件变成一个归档文件2.tar c ##创建 f ##指定归档文件名称 t ##显示归档文件中的内容 r ##向归档文件中添加文件 --get ##取出单个文件 ...
  • 前言:因自己负责的项目(jetty内嵌启动的SpringMvc)中需要实现文件上传,而自己对java文件上传这一块未接触过,且对 Http 协议较模糊,故这次采用渐进的方式来学习文件上传的原理与实践。该博客重在实践。 一. ...
  • 互联网大文件传输方式

    千次阅读 2019-06-25 14:02:21
    特别是一些企业级的用户,经常会需要传输一些大型文件给别人,比如一些视频音频,庞大的数据信息,较大的应用程序,游戏等等,但是又不知道该如何发送大文件,下面将会介绍几种不同的传输文件的方式。 QQ传输 ...
  • PPT演示文稿等文件传输,中经常使用视频和图像,因此这些类型的媒体文件附件也较大;企业大文件跨国传输(因网络环境问题,常规的传输方式不适合大文件跨国传输);企业的数据量急剧增长,海量数据分发与收集传输...
  • 文件传输作为日常生活、工作中需求量较高的一项功能,工作中总会遇到需要将文件从一个设备转移到另一个设备上查看、存储,或者将资料回传的情况。一般大小的文件可以用QQ或者微信的文件传输助手来解决,或者任意一个...
  • VNC双向传输文件和文件夹

    万次阅读 2020-05-27 16:59:54
    VNC双向传输文件和文件夹 ...文章目录VNC双向传输文件和文件夹@[toc]1.viewer向server传输1.1 viewer向server传输文件1.2 viewer向server传输文件夹2.server向viewer传输2.1 server向viewer传输文件2.2 se...
  • 首先要安装虚拟机工具VMWare Tool这样鼠标进出使用也方便。...使用Feiq等文件传输工具进行传输。此方法只要主机和虚拟机之间网络互通即可。3.使用共享文件夹的方式。给虚拟机添加共享文件夹指向一个本机的...
  • VM:如何向vmware虚拟机中传输文件(或者共享文件夹)之详细攻略(图文教程) 目录 如何向vmware虚拟机中传输文件 1、外部点击安装VMware Tools 2、内部客户机进行安装 3、共享文件夹 如何向...
  • 简单三步实现window10与Ubuntu之间的文件传输

    万次阅读 多人点赞 2018-10-09 20:52:55
    2. 使用FileZilla传输文件需要SSH服务,Ubuntu作为服务端使用需要安装SSH服务端,参考:Ubuntu下使用SSH和FileZilla远程登陆 ,使用以下命令安装: sudo apt-get install openssh-serv...
  • 两台电脑如何传文件最快方法。我们在使用电脑的时候,有的情况下需要我们队两台电脑之间互相的传输文件。那么我们应该通过什么样的方法传输最快速呢?我们一起来看看吧。  首先我们需要一根平时上网连接网络时用...
  • Docker容器和本机之间的文件传输

    万次阅读 多人点赞 2017-11-25 20:00:44
    有了这个长长的ID的话,本机和容器之间的文件传输就简单了。docker cp 本地文件路径 ID全称:容器路径进入容器之后就能够看到刚才上传进来的文件了。如果是容器传输文件到本地的话,反过来就好了:docker cp ID全称:...
  • 网络传输文件使用什么软件可以高速传输?通过网络传输文件总是在速度上得不到很好的体现,更不用说是传输文件了。本身支持大文件网络传输的工具就是不是很多,很多的传输工具对文件的大小都有所限制,要是想要...
  • xshell如何传输文件

    万次阅读 2018-06-27 18:50:28
    上传文件的执行命令:#rz 就会打开本地选择文件对话框,选择文件,确定就可以上传到当前所在目录。如果覆盖原文件,执行:#rz -y5.下载文件,执行:#sz {文件}弹出选择本地保存文件对话框。6.Alt+P打开属性框。...
  • 如何在linux和windows之间传输文件

    万次阅读 热门讨论 2018-08-21 15:25:30
    本文介绍一种可以在linux和windows之间传输文件很方便的一个辅助程序 首先是下载该程序: 记得要在网络连接的情况下,在命令行输入 yum install lrzsz 记的特别注意,在linux下安装要切换到root,管理员模式哦...
  • 跨国传输文件都有哪些好的方式—免费的!!大数据文件跨地域传输,众多问题一拥而现......分享几个实用方法。开始....1).公有云网盘,包括Dropbox/...有客户端软件,支持文件同步功能,传输支持断点续。WeTrans...
1 2 3 4 5 ... 20
收藏数 1,525,554
精华内容 610,221
关键字:

文件传输